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


107

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

回答:


181

RailsはRubyをmattr_accessor(モジュールアクセサ)とcattr_accessor(および_ reader/ _writerバージョン)の両方で拡張します。RubyのがAS 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 = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"

1
あなたの例では、それmattr_accessorがクラスインスタンス変数(@variables)の略であることを説明していますが、ソースコードは、それらが実際にクラス変数を設定/読み取りしていることを明らかにしているようです。この違いについて説明してもらえますか?
sandre89

38

ここにソースがあります 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"

これは、default_url_options(mattr_accessor)を直接設定するときに、かなり難しい問題でした。いったんクラスがそれらを1つの方法で設定し、別の方法でそれらを異なる方法で設定して、無効なリンクを作成します。
エリックデイビス

Railsの最新バージョンでcattr_*は、のエイリアスになりましたmattr_*cattr_accessorソースを
ouranos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.