web-dev-qa-db-ja.com

Railsモジュールのmattr_accessorとは何ですか?

Railsドキュメンテーションでこれを見つけることができませんでしたが、 'mattr_accessor'Module 'attr_accessor'(getter&setter)for normalの結果Rubyclass).

例えば。クラスで

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によって提供されます。

103
JasonOng

Railsは、Rubyでmattr_accessor(モジュールアクセサ)とcattr_accessor(および_reader/_writerバージョン)の両方を拡張します。Rubyとして] attr_accessorインスタンスのゲッター/セッターメソッドを生成し、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 = "[email protected]"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "[email protected]"
174
Avdi

これはcattr_accessorのソースです

そして

これはmattr_accessorのソースです

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

なぜ2つの異なるバージョンがあるのですか?モジュールにcattr_accessorを書きたい場合がありますので、それを設定情報に使用できます Avdiの言及のように
ただし、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"
37
Orion Edwards