Bagaimana cara menimpa metode pengambil dalam model ActiveRecord?


98

Saya mencoba untuk menimpa metode pengambil untuk model ActiveRecord. Saya memiliki atribut yang disebut namemodel Category, dan saya ingin dapat melakukan sesuatu seperti ini:

def name
  name_trans || name
end

Jika name_transatribut bukan nil, maka kembalikan, jika tidak nameatribut kembalikan . Bagaimana saya melakukan ini?

Ini kemudian harus dipanggil secara normal seperti ini:

@category.name

Jawaban:



98

Update: Metode yang disukai sesuai dengan Rails Style Guide adalah dengan menggunakan self[:name]bukannya read_attributedan write_attribute. Saya akan mendorong Anda untuk melewatkan jawaban saya dan lebih memilih yang ini .


Anda dapat melakukannya persis seperti itu, kecuali yang perlu Anda gunakan read_attributeuntuk benar-benar mengambil nilai atribut name dan menghindari panggilan rekursif ke namemetode:

def name 
  name_trans || read_attribute(:name)
end

2
Tahu mengapa Rubocop lebih suka self[:name]lebih read_attribute[:name]?
Zack Xu

18

Saya ingin menambahkan opsi lain untuk menimpa metode pengambil, yaitu : super.

def name
  name_trans || super
end

ini berfungsi tidak hanya pada metode pengambil atribut, tetapi juga metode pengambil asosiasi, juga。


1
Inilah yang saat ini direkomendasikan oleh pemandu Rails, untuk getter DAN setter: api.rubyonrails.org/classes/ActiveRecord/…
sandre89

5

Mengganti pengambil dan menggunakan read_attributetidak berfungsi untuk pengaitan, tetapi Anda dapat menggunakannya alias_method_chain.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Bisakah Anda memberikan contoh yang tepat ...?
Arup Rakshit

Baik. Saya baru saja melihat doco . Sekarang jika saya memanggil nameobjek model, mana yang akan dipanggil - name_with_overrideatau name_without_override?
Arup Rakshit

1
namesekarang akan menelepon name_with_override. Jika Anda ingin memanggil metode asli karena suatu alasan, Anda dapat menelepon name_without_override.
Patrick Oscity

O begitu .. Terima kasih atas balasan Anda //
Arup Rakshit

2

Jika Anda menggunakan atribut toko seperti ini

store :settings, accessors: [:volume_adjustment] 

atau menggunakan permata seperti hstore_accessor tautan permata

Jadi Anda akhirnya menggunakan storemetode pada model, lalu untuk mengganti metode yang tidak dapat Anda gunakan self.read_attribute, Anda harus menggunakan sebagai gantinya super:

def partner_percentage
  super.to_i || 10
end

0

Jika seseorang ingin memperbarui nilai setelah name_transdalam metode pengambil, Anda dapat menggunakan 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

Anda dapat menggunakan metode Rails read_attribute. Dokumen Rails


Meskipun tautan ini mungkin menjawab pertanyaan, jawaban hanya tautan tidak diperbolehkan di SO, tambahkan beberapa konteks pada jawaban Anda dari apa yang ada di balik tautan itu. Terima kasih! :)
AJT82
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.