ฉันจะเขียนทับเมธอด getter ในโมเดล ActiveRecord ได้อย่างไร


102

ฉันพยายามเขียนทับเมธอด getter สำหรับโมเดล ActiveRecord ฉันมีแอตทริบิวต์ที่เรียกว่าnameในโมเดลCategoryและฉันต้องการที่จะทำสิ่งนี้:

def name
  name_trans || name
end

หากname_transแอตทริบิวต์ไม่ใช่ศูนย์ให้ส่งคืนหรือส่งคืนnameแอตทริบิวต์ ฉันจะทำอย่างไร

สิ่งนี้ควรถูกเรียกตามปกติดังนี้:

@category.name

คำตอบ:


130

คู่มือสไตล์ Railsแนะนำให้ใช้มากกว่าself[:attr]read_attribute(:attr)

คุณสามารถใช้งานได้ดังนี้:

def name
  name_trans || self[:name]
end

ทำไมถึงดีขึ้น? อย่าเพิ่งเชื่อมโยงไปยังไซต์อื่น ๆ ให้รวมบิตที่เกี่ยวข้องไว้ที่นี่ ลิงก์อาจไม่ถูกต้อง
JamesT

2
ดูบริบทเพิ่มเติมได้ที่นี่: github.com/bbatsov/rails-style-guide/issues/155
mimsugara

99

ปรับปรุง: วิธีการที่ต้องการให้เป็นไปตามคู่มือสไตล์ Railsคือการใช้self[:name]แทนและread_attribute write_attributeผมขอแนะนำให้คุณที่จะข้ามคำตอบของฉันและแทนที่จะชอบคนนี้


คุณสามารถทำได้เช่นนั้นทุกread_attributeประการยกเว้นว่าคุณจำเป็นต้องใช้เพื่อดึงค่าของแอตทริบิวต์ name และหลีกเลี่ยงการเรียกซ้ำไปยังnameเมธอด:

def name 
  name_trans || read_attribute(:name)
end

2
มีความคิดว่าทำไม Rubocop ถึงชอบself[:name]มากกว่าread_attribute[:name]?
Zack Xu

20

ฉันต้องการเพิ่มตัวเลือกอื่นสำหรับการเขียนทับวิธี getter ซึ่งก็คือ: super

def name
  name_trans || super
end

สิ่งนี้ใช้งานได้ไม่เพียง แต่ในวิธี getter แอตทริบิวต์เท่านั้น แต่ยังรวมถึงวิธีการเชื่อมโยง getter ด้วย


2
นี่คือสิ่งที่ Rails Guide แนะนำในปัจจุบันสำหรับ getters และ setters: api.rubyonrails.org/classes/ActiveRecord/…
sandre89

5

การลบล้าง getter และการใช้read_attributeไม่สามารถใช้ได้กับการเชื่อมโยง แต่คุณสามารถใช้alias_method_chainแทนได้

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

คุณสามารถยกตัวอย่างที่เหมาะสม ... ?
Arup Rakshit

ดี. ผมเพิ่งเห็นdoco ตอนนี้ถ้าฉันเรียกnameวัตถุแบบจำลองจะเรียกว่า - name_with_overrideหรือname_without_override?
อานุภาพรักจิตร

1
nameจะโทรname_with_override. หากคุณต้องการเรียกวิธีการเดิมด้วยเหตุผลบางประการคุณสามารถโทรname_without_override.
Patrick Oscity

เห็นแล้ว .. ขอบคุณสำหรับการตอบกลับ //
Arup Rakshit

2

หากคุณใช้แอตทริบิวต์ร้านค้าเช่นนี้

store :settings, accessors: [:volume_adjustment] 

หรือใช้อัญมณีเช่น hstore_accessor ลิงค์อัญมณี

ดังนั้นคุณจึงใช้storeวิธีการแบบจำลองจากนั้นเพื่อแทนที่วิธีการเหล่านั้นที่คุณไม่สามารถใช้ได้self.read_attributeคุณต้องใช้แทนsuperเช่นนั้น:

def partner_percentage
  super.to_i || 10
end

0

หากมีคนต้องการอัปเดตค่าหลังจากname_transในเมธอด getter คุณสามารถใช้ self [: name] =

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

0

คุณสามารถใช้เมธอด Rails read_attribute เอกสารราง


แม้ว่าลิงก์นี้อาจตอบคำถาม แต่ไม่อนุญาตให้ใช้ลิงก์เฉพาะคำตอบใน SO โปรดเพิ่มบริบทให้กับคำตอบของคุณจากสิ่งที่อยู่เบื้องหลังลิงก์นั้น ขอบคุณ! :)
AJT82
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.