O que é mattr_accessor em um módulo Rails?
-
06-07-2019 - |
Pergunta
Eu não poderia realmente encontrar este na documentação Rails, mas parece que 'mattr_accessor' é o módulo corolário para 'attr_accessor' ( getter e setter) em um normal de rubi class .
Por exemplo. em uma classe
class User
attr_accessor :name
def set_fullname
@name = "#{self.first_name} #{self.last_name}"
end
end
Por exemplo. em um módulo
module Authentication
mattr_accessor :current_user
def login
@current_user = session[:user_id] || nil
end
end
Este método auxiliar é fornecido pelo ActiveSupport .
Solução
trilhos estende rubi com ambos mattr_accessor
(Módulo de assessor) e cattr_accessor
(bem como versões _reader
/ _writer
). Como attr_accessor
de Ruby gera métodos getter / setter para casos , cattr/mattr_accessor
fornecer métodos getter / setter no class ou módulo nível. Assim:
module Config
mattr_accessor :hostname
mattr_accessor :admin_email
end
é a abreviação de:
module Config
def self.hostname
@hostname
end
def self.hostname=(hostname)
@hostname = hostname
end
def self.admin_email
@admin_email
end
def self.admin_email=(admin_email)
@admin_email = admin_email
end
end
Ambas as versões permitem que você acessar as variáveis ??de nível de módulo como assim:
>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"
Outras dicas
Eis a fonte para cattr_accessor
E
Eis a fonte para mattr_accessor
Como você pode ver, eles são praticamente idênticos.
Quanto ao porquê existem duas versões diferentes? Às vezes você quer escrever cattr_accessor
em um módulo, para que você possa usá-lo para informações de configuração como Avdi menciona .
No entanto, cattr_accessor
não trabalho em um módulo, para que eles mais ou menos copiou o código mais ao trabalho para os módulos também.
Além disso, às vezes você pode querer escrever um método de classe em um módulo, de modo que sempre que qualquer classe inclui o módulo, ele recebe esse método classe, bem como todos os métodos de instância. mattr_accessor
também permite que você faça isso.
No entanto, no segundo cenário, de comportamento é muito estranho. Observe o seguinte código, particularmente notar os bits @@mattr_in_module
module MyModule
mattr_accessor :mattr_in_module
end
class MyClass
include MyModule
def self.get_mattr; @@mattr_in_module; end # directly access the class variable
end
MyModule.mattr_in_module = 'foo' # set it on the module
=> "foo"
MyClass.get_mattr # get it out of the class
=> "foo"
class SecondClass
include MyModule
def self.get_mattr; @@mattr_in_module; end # again directly access the class variable in a different class
end
SecondClass.get_mattr # get it out of the OTHER class
=> "foo"