Wie kann ich eine Getter-Methode in einem ActiveRecord-Modell überschreiben?

98

Ich versuche, eine Getter-Methode für ein ActiveRecord-Modell zu überschreiben. Ich habe ein Attribut nameim Modell Categoryund möchte in der Lage sein, so etwas zu tun:

def name
  name_trans || name
end

Wenn das name_transAttribut nicht Null ist, geben Sie es zurück, andernfalls geben Sie das nameAttribut zurück. Wie würde ich das machen?

Dies sollte dann normalerweise so genannt werden:

@category.name
oyvindhauge
quelle

Antworten:

123

Der Rails Style Guide empfiehlt die Verwendung von self[:attr]over read_attribute(:attr).

Sie können es so verwenden:

def name
  name_trans || self[:name]
end
Wonsup Lee
quelle
Warum ist es besser? Verlinken Sie nicht nur auf andere Websites, sondern geben Sie hier die relevanten Bits an. Links können ungültig werden
JamesT
2
Für etwas mehr Kontext siehe hier: github.com/bbatsov/rails-style-guide/issues/155
mimsugara
98

Update: Die bevorzugte Methode gemäß dem Rails Style Guide ist die Verwendung self[:name]anstelle von read_attributeund write_attribute. Ich würde Sie ermutigen, meine Antwort zu überspringen und stattdessen diese zu bevorzugen .


Sie können dies genau so tun, außer dass Sie read_attributeden Wert des Attributs name tatsächlich abrufen und den rekursiven Aufruf der nameMethode vermeiden müssen :

def name 
  name_trans || read_attribute(:name)
end
meagar
quelle
2
Jede Idee , warum Rubocop bevorzugt self[:name]über read_attribute[:name]?
Zack Xu
18

Ich möchte eine weitere Option zum Überschreiben der Getter-Methode hinzufügen, die einfach: super ist.

def name
  name_trans || super
end

Dies funktioniert nicht nur bei Attribut-Getter-Methoden, sondern auch bei Assoziations-Getter-Methoden (auch)

lei liu
quelle
1
Dies ist, was die Rails-Guides derzeit für Getter UND Setter empfehlen: api.rubyonrails.org/classes/ActiveRecord/…
sandre89
5

Das Überschreiben und Verwenden von Getter read_attributefunktioniert nicht für Assoziationen, aber Sie können es alias_method_chainstattdessen verwenden.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override
Patrick Oscity
quelle
Können Sie ein richtiges Beispiel geben ...?
Arup Rakshit
Gut. Ich habe gerade das Dokument gesehen . Wenn ich nun namedas Modellobjekt aufrufe, welches wird aufgerufen - name_with_overrideoder name_without_override?
Arup Rakshit
1
namewerde jetzt anrufen name_with_override. Wenn Sie aus irgendeinem Grund die ursprüngliche Methode aufrufen möchten, können Sie sie aufrufen name_without_override.
Patrick Oscity
OI see .. Danke für deine Antworten //
Arup Rakshit
2

Wenn Sie solche Speicherattribute verwenden

store :settings, accessors: [:volume_adjustment] 

oder mit Edelsteinen wie hstore_accessor Edelstein Link

Sie haben also die storeMethode für das Modell verwendet. Um die Methode zu überschreiben, die Sie nicht verwenden können self.read_attribute, müssen Sie stattdessen superFolgendes verwenden:

def partner_percentage
  super.to_i || 10
end
onemanstartup
quelle
0

Wenn jemand den Wert nach der name_transGetter-Methode aktualisieren möchte , können Sie self [: name] = verwenden.

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

Sie können die Rails-Methode read_attribute verwenden. Rails docs

Rajat Bansal
quelle
Während dieser Link möglicherweise die Frage beantwortet, sind Antworten auf nur Links auf SO nicht zulässig. Fügen Sie Ihrer Antwort einen Kontext hinzu, der sich hinter dem Link befindet. Vielen Dank! :)
AJT82