Preciso acessar uma constante ActiveRecord de um módulo incluído em um aplicativo Rails.
class User < ApplicationRecord
include ModOne
OPTIONS = {a: 1}.freeze
...
end
Module ModOne
extend ActiveSupport::Concern
included do
do_semething(self::OPTIONS)
end
class_methods do
def do_something(opts)
...
end
end
end
Mas eu entendo
NameError: constante não inicializada Usuário (chame 'User.connection' para estabelecer uma conexão)::OPTIONS Você quis dizer? Usuário::OPTIONS
O que estou perdendo aqui?
Também tentei substituir self
por base_class
e evento User
, mas recebo o mesmo erro.
É simplesmente uma questão de ordem. Você tem que definir a constante primeiro. As classes Ruby são realmente apenas um bloco de código e rodam de cima para baixo e quando você chama,
include
você também está chamando o#included
método no módulo.Mas uma abordagem melhor se você quiser que a funcionalidade fornecida por um módulo seja personalizável é simplesmente escrever um método macro em vez de depender de tudo
Module#included
:Esse padrão pode ser encontrado em qualquer lugar em Ruby e é uma ótima maneira de contornar o fato de que ele
Module#include
não permite que você passe nenhum argumento adicional.Neste exemplo, o
awesomeize
método apenas armazena as opções como uma variável de instância de classe.Uma das razões mais fortes pelas quais isso é preferível é que ele permite que você defina uma assinatura para a interface entre o módulo e seus consumidores em vez de apenas fazer suposições. Algumas gems como Devise até usam esse método para incluir seus submódulos.