ActiveRecord-Attributmethoden überschreiben

150

Ein Beispiel für das, wovon ich spreche:

class Person < ActiveRecord::Base
  def name=(name)
    super(name.capitalize)
  end
  def name
    super().downcase  # not sure why you'd do this; this is just an example
  end
end

Dies scheint zu funktionieren, aber ich habe gerade den Abschnitt über das Überschreiben von Attributmethoden in den ActiveRecord :: Base-Dokumenten gelesen und es wird vorgeschlagen, das read_attributeund zu verwendenwrite_attribute Methoden verwenden. Ich dachte, dass etwas mit dem, was ich im obigen Beispiel mache, nicht stimmt. Warum sollten sie diese Methoden andernfalls als "richtigen Weg" zum Überschreiben von Attributmethoden segnen? Sie erzwingen auch eine viel hässlichere Sprache, also muss es einen guten Grund geben ...

Meine eigentliche Frage: Stimmt etwas mit diesem Beispiel nicht?

Ajedi32
quelle

Antworten:

211

Gareths Kommentare wiederholen ... Ihr Code funktioniert nicht wie geschrieben. Es sollte folgendermaßen umgeschrieben werden:

def name=(name)
  write_attribute(:name, name.capitalize)
end

def name
  read_attribute(:name).downcase  # No test for nil?
end
Aaron Longwell
quelle
Genau das, was ich brauchte. Danke Aaron.
Bong
18
Das stimmt nicht mehr. Entweder super oder das funktioniert jetzt. Ich habe die Hash-Notation jedoch nicht getestet.
Heartpunk
2
In Schienen 3 funktioniert die hier von Aaron angegebene Lesemethode, aber der Schreiber, den das angegebene Originalplakat (den Namen an Super weitergeben), funktioniert einwandfrei, und IMHO ist sauberer als das manuelle Schreiben des Attributs, wie Aaron vorschlägt.
Batkins
1
Ich habe die von Mipadi unten angegebene Hash-Methode getestet und sie funktioniert wie ein Zauber (Rails v 3.2.6)
Almathie
Ist es nicht die richtige Antwort? Danke @Aaron, hat auch für mich gearbeitet.
Sadiksha Gautam
94

Als Erweiterung der Antwort von Aaron Longwell können Sie auch eine "Hash-Notation" verwenden, um auf Attribute zuzugreifen, die Accessoren und Mutatoren überschrieben haben:

def name=(name)
  self[:name] = name.capitalize
end

def name
  self[:name].downcase
end
Mipadi
quelle
Die Hash-Notation funktioniert möglicherweise, self.attributesprengt aber den Stack in 3.2.16.
jrhorn424
Dies hat den Vorteil, dass es ||=für die Standardeinstellung unterstützt :def name; self[:name] ||= 'anon'; end
Paul Cantrell
Für mich funktioniert diese Hash-Notation. Aber ich weiß nicht, warum es funktioniert. Kann jemand erklären?
Radiantshaw
-1

Ich habe ein Rails-Plugin, mit dem das Überschreiben von Attributen wie erwartet funktioniert. Sie finden es auf Github .

Installieren:

./script/plugin install git://github.com/chriseppstein/has_overrides.git

Benutzen:

class Post < ActiveRecord::Base

  has_overrides

  module Overrides
    # put your getter and setter overrides in this module.
    def title=(t)
      super(t.titleize)
    end
  end
end

Sobald Sie das getan haben, funktionieren die Dinge einfach:

$ ./script/console 
Loading development environment (Rails 2.3.2)
>> post = Post.new(:title => "a simple title")
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil>
>> post.title = "another simple title"
=> "another simple title"
>> post.title
=> "Another Simple Title"
>> post.update_attributes(:title => "updated title")
=> true
>> post.title
=> "Updated Title"
>> post.update_attribute(:title, "singly updated title")
=> true
>> post.title
=> "Singly Updated Title"
chriseppstein
quelle