Bir Rails modülünde mattr_accessor nedir?


107

Gerçekten Raylar belgelerinde bu bulamadık ama gibi görünüyor 'mattr_accessor' olduğunu Modülü için doğal sonucu 'attr_accessor' normal Ruby içinde (alıcı & ayarlayıcı) sınıfına .

Örneğin. sınıfta

class User
  attr_accessor :name

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

Örneğin. bir modülde

module Authentication
  mattr_accessor :current_user

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

Bu yardımcı yöntem, ActiveSupport tarafından sağlanır .

Yanıtlar:


181

Rails, Ruby'yi hem mattr_accessor(Modül erişimcisi) hem de (ve cattr_accessorayrıca _ reader/ _writersürümleri) ile genişletir . Ruby gibi, attr_accessoriçin alıcı / ayarlayıcı yöntemleri üretir durumlarda , cattr/mattr_accessoren alıcı / ayarlayıcı yöntemleri sağlamak sınıfı ya da modül seviyesi. Böylece:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

İçin Kısa:

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

Her iki sürüm de aşağıdaki gibi modül düzeyindeki değişkenlere erişmenize izin verir:

>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"

1
Örneklerinizde, bunun mattr_accessorsınıf örneği değişkenlerinin kısa olacağını açıklıyorsunuz @variable, ancak kaynak kodu aslında sınıf değişkenlerini ayarladıklarını / okuduklarını gösteriyor gibi görünüyor. Bu farkı açıklar mısınız lütfen?
sandre89

38

İşte kaynağı cattr_accessor

Ve

İşte kaynağı mattr_accessor

Gördüğünüz gibi hemen hemen aynılar.

Neden iki farklı versiyon olduğuna gelince? Bazen cattr_accessorbir modülde yazmak istersiniz , böylece Avdi'nin bahsettiği gibi yapılandırma bilgileri için kullanabilirsiniz .
Ancak, cattr_accessorbir modülde çalışmaz, bu nedenle modüller için de çalışmak üzere kodu aşağı yukarı kopyaladılar.

Ek olarak, bazen bir modülde bir sınıf yöntemi yazmak isteyebilirsiniz, öyle ki herhangi bir sınıf modülü içerdiğinde, o sınıf yönteminin yanı sıra tüm örnek yöntemlerini de alır. mattr_accessorayrıca bunu yapmanıza izin verir.

Bununla birlikte, ikinci senaryoda, davranışı oldukça tuhaftır. Aşağıdaki kodu inceleyin, özellikle @@mattr_in_modulebitlere dikkat edin

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"

Bu, default_url_options'ı doğrudan (mattr_accessor) ayarlarken beni oldukça zorlayan bir şeydi. Sınıf bir kez onları bir şekilde ayarlayacak ve diğeri onları farklı bir şekilde ayarlayacak ve böylece geçersiz bağlantılar oluşturacaktır.
Eric Davis

Rails'in son sürümünde cattr_*artık mattr_*. cattr_accessorKaynağa
ouranos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.