mattr_accessor ในโมดูล Rails คืออะไร?


107

ฉันไม่สามารถจริงๆพบนี้ในเอกสารทางรถไฟ แต่ดูเหมือนว่า'mattr_accessor'เป็นโมดูลควันหลงสำหรับ'attr_accessor' (ทะเยอทะยานและหมา) ในทับทิมปกติระดับ

เช่น. ในชั้นเรียน

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 attr_accessorสร้างเมธอด getter / setter สำหรับอินสแตนซ์ , cattr/mattr_accessorให้วิธีการ getter / หมาที่ระดับหรือโมดูลระดับ ดังนั้น:

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มันจะสั้นสำหรับตัวแปรอินสแตนซ์คลาส@variableแต่ดูเหมือนว่าซอร์สโค้ดจะเปิดเผยว่าพวกเขากำลังตั้งค่า / อ่านตัวแปรคลาส คุณช่วยอธิบายความแตกต่างนี้ได้ไหม
sandre89

38

นี่คือแหล่งที่มาของ cattr_accessor

และ

นี่คือแหล่งที่มาของ mattr_accessor

อย่างที่คุณเห็นมันเหมือนกันมาก

ทำไมถึงมีสองรุ่นที่แตกต่างกัน? บางครั้งคุณต้องการที่จะเขียนcattr_accessorในโมดูลเพื่อให้คุณสามารถใช้มันสำหรับข้อมูลการกำหนดค่าเช่น Avdi กล่าว
อย่างไรก็ตามcattr_accessorไม่ทำงานในโมดูลดังนั้นพวกเขาจึงคัดลอกโค้ดไปใช้กับโมดูลมากขึ้นหรือน้อยลง

นอกจากนี้บางครั้งคุณอาจต้องการเขียนเมธอดคลาสในโมดูลเช่นเมื่อใดก็ตามที่คลาสใด ๆ มีโมดูลก็จะได้รับเมธอดคลาสนั้นเช่นเดียวกับเมธอดอินสแตนซ์ทั้งหมด mattr_accessorยังให้คุณทำเช่นนี้

อย่างไรก็ตามในสถานการณ์ที่สองพฤติกรรมนี้ค่อนข้างแปลก สังเกตรหัสต่อไปนี้โดยเฉพาะอย่างยิ่งสังเกต@@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"

นี่เป็น gotcha ที่ทำให้ฉันค่อนข้างลำบากเมื่อตั้งค่า default_url_options โดยตรง (mattr_accessor) ครั้งหนึ่งชั้นเรียนจะตั้งค่าวิธีหนึ่งและอีกวิธีหนึ่งจะกำหนดวิธีที่แตกต่างออกไปดังนั้นการสร้างลิงก์ที่ไม่ถูกต้อง
Eric Davis

ในรุ่นล่าสุดของทางรถไฟอยู่ในขณะนี้นามแฝงสำหรับcattr_* mattr_*ดูที่cattr_accessorมา
ouranos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.