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
oyvindhauge.dll
sumber

Jawaban:

123

The Rails Style Guide merekomendasikan menggunakan self[:attr]lebih read_attribute(:attr).

Anda bisa menggunakannya seperti ini:

def name
  name_trans || self[:name]
end
Wonsup Lee
sumber
Mengapa lebih baik? Jangan hanya menautkan ke situs lain, sertakan bagian yang relevan di sini. Tautan bisa menjadi tidak valid
JamesT
2
Untuk konteks yang lebih banyak lihat di sini: github.com/bbatsov/rails-style-guide/issues/155
mimsugara
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
meagar
sumber
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。

lei liu
sumber
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
Patrick Oscity
sumber
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
onemanstartup
sumber
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
fangxing
sumber
0

Anda dapat menggunakan metode Rails read_attribute. Dokumen Rails

Rajat Bansal
sumber
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