Jak mogę nadpisać metodę pobierającą w modelu ActiveRecord?


98

Próbuję nadpisać metodę pobierającą dla modelu ActiveRecord. Mam atrybut o nazwie namew modelu Categoryi chciałbym móc zrobić coś takiego:

def name
  name_trans || name
end

Jeśli name_transatrybut nie jest nil, zwróć go, w przeciwnym razie zwróć nameatrybut. Jak bym to zrobił?

Należy to wtedy nazwać normalnie w ten sposób:

@category.name

Odpowiedzi:



98

Aktualizacja: Preferowaną metodą według Przewodnika po stylach Rails jest użycie self[:name]zamiast read_attributei write_attribute. Zachęcam do pominięcia mojej odpowiedzi i zamiast tego wolę .


Możesz to zrobić dokładnie w ten sposób, z tym wyjątkiem, że musisz użyć, read_attributeaby faktycznie pobrać wartość atrybutu name i uniknąć rekurencyjnego wywołania namemetody:

def name 
  name_trans || read_attribute(:name)
end

2
Masz jakiś pomysł, dlaczego Rubocop woli self[:name]więcej read_attribute[:name]?
Zack Xu

18

Chciałbym dodać kolejną opcję nadpisywania metody gettera, która jest po prostu super.

def name
  name_trans || super
end

działa to nie tylko na metodzie pobierającej atrybuty, ale także na metodach pobierających asocjacje , także。


1
To właśnie zalecają obecnie przewodniki Rails, dla getterów ORAZ seterów: api.rubyonrails.org/classes/ActiveRecord/ ...
sandre89

5

Zastępowanie metody pobierającej i używanie read_attributenie działa w przypadku skojarzeń, ale alias_method_chainzamiast tego można użyć .

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Czy możesz podać dobry przykład ...?
Arup Rakshit

Dobrze. Właśnie zobaczyłem dokumentację . Jeśli teraz namewywołam obiekt modelu, który zostanie wywołany - name_with_overrideczy name_without_override?
Arup Rakshit

1
nameteraz zadzwoni name_with_override. Jeśli z jakiegoś powodu chcesz wywołać oryginalną metodę, możesz wywołać name_without_override.
Patrick Oscity

O, rozumiem… Dzięki za odpowiedzi //
Arup Rakshit,

2

Jeśli używasz atrybutów sklepu, takich jak ten

store :settings, accessors: [:volume_adjustment] 

lub używając klejnotów, takich jak link do klejnotów hstore_accessor

Skończyło się na użyciu storemetody na modelu, a następnie, aby zastąpić metodę, której nie możesz użyć self.read_attribute, musisz zamiast tego użyć super:

def partner_percentage
  super.to_i || 10
end

0

Jeśli ktoś chce zaktualizować wartość after name_transw metodzie getter, możesz użyć 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

Możesz użyć metody read_attribute Railsów. Dokumenty Rails


chociaż ten link może odpowiedzieć na pytanie, odpowiedzi na same łącza nie są dozwolone w SO, proszę dodać kontekst do odpowiedzi z tego, co znajduje się za tym łączem. Dzięki! :)
AJT82
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.