Zastąp metody atrybutów ActiveRecord


150

Przykład o czym mówię:

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

Wydaje się, że to działa, ale właśnie przeczytałem sekcję dotyczącą zastępowania metod atrybutów w dokumentacji ActiveRecord :: Base i sugeruje użycie metod read_attributei write_attribute. Pomyślałem, że coś musi być nie tak z tym, co robię w powyższym przykładzie; w przeciwnym razie dlaczego mieliby błogosławić te metody jako „właściwą drogę” do zastępowania metod atrybutów? Wymuszają też znacznie brzydszy idiom, więc musi być dobry powód ...

Moje prawdziwe pytanie: czy coś jest nie tak z tym przykładem?

Odpowiedzi:


211

Powtarzając komentarze Garetha ... Twój kod nie będzie działał tak, jak został napisany. Powinien zostać przepisany w ten sposób:

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

def name
  read_attribute(:name).downcase  # No test for nil?
end

Dokładnie to, czego potrzebowałem. Dzięki Aaron.
bong

18
To już nie jest prawdą. Albo super, albo to działa teraz. Nie testowałem jednak notacji hash.
heartpunk

2
W railsach 3 działa metoda czytnika określona tutaj przez Aarona, ale autor, który podał oryginalny plakat (przekazujący nazwę do super) działa dobrze, a IMHO jest czystszy niż ręczne zapisywanie atrybutu, jak sugeruje Aaron.
Batkins

1
Przetestowałem metodę haszowania podaną przez mipadi poniżej i działa jak urok (Rails v 3.2.6)
almathie

Czy to nie jest właściwa odpowiedź? Dzięki @Aaron, również dla mnie pracował.
Sadiksha Gautam,

94

Jako rozszerzenie odpowiedzi Aarona Longwella możesz także użyć „notacji mieszającej”, aby uzyskać dostęp do atrybutów, które przesłaniały akcesory i mutatory:

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

def name
  self[:name].downcase
end

Notacja z krzyżykiem może działać, ale self.attributezdmuchuje stos w wersji 3.2.16.
jrhorn424

Ma to tę zaletę, że obsługuje ||=domyślne:def name; self[:name] ||= 'anon'; end
Paul Cantrell

U mnie działa ta notacja hash. Ale nie wiem, dlaczego to działa. Czy ktoś może wyjaśnić?
radiantshaw


-1

Mam wtyczkę rails, która sprawia, że ​​nadpisywanie atrybutów działa z super, jak można się spodziewać. Możesz go znaleźć na githubie .

Żeby zainstalować:

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

Używać:

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

Kiedy już to zrobisz, wszystko po prostu działa:

$ ./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"
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.