114

これは Rails のドキュメントで実際に見つけることができませんでしたが、「mattr_accessor」は、通常の Rubyクラスの「attr_accessor」 (getter & setter)のモジュールの結果のようです。

例えば。クラスで

class User
  attr_accessor :name

  def set_fullname
    @name = "#{self.first_name} #{self.last_name}"
  end
end

例えば。モジュールで

module Authentication
  mattr_accessor :current_user

  def login
    @current_user = session[:user_id] || nil
  end
end

このヘルパー メソッドはActiveSupportによって提供されます。

4

2 に答える 2

189

Rails は Ruby をmattr_accessor(Module アクセサー) とcattr_accessor(および _ reader/_writerバージョン) の両方で拡張します。Rubyはインスタンスattr_accessorのgetter/setter メソッドを生成するため、クラスまたはモジュールレベルで getter/setter メソッドを提供します。したがって:cattr/mattr_accessor

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

の略です:

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

どちらのバージョンでも、次のようにモジュール レベルの変数にアクセスできます。

>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"
于 2008-10-09T01:49:21.817 に答える
40

のソースはこちらcattr_accessor

のソースはこちらmattr_accessor

ご覧のとおり、それらはほとんど同じです。

なぜ2つの異なるバージョンがあるのですか? 場合によっては、 Avdi の言及などcattr_accessorの構成情報に使用できるように、モジュールに書き込みたいことがあります。 ただし、モジュールでは機能しないため、多かれ少なかれコードをコピーして、モジュールでも機能します。
cattr_accessor

さらに、モジュール内にクラス メソッドを記述したい場合があります。これにより、任意のクラスにモジュールが含まれるたびに、そのクラス メソッドとすべてのインスタンス メソッドが取得されます。mattr_accessorまた、これを行うことができます。

ただし、2 番目のシナリオでは、その動作はかなり奇妙です。次のコードを観察し、特に@@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"
于 2008-10-09T19:51:35.923 に答える