145


41

ActiveRecord属性メソッドをオーバーライドする

私が話していることの例:

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

これはうまくいくようですが、私はhttp://rails.rubyonrails.com/classes/ActiveRecord/Base.html[ActiveRecord::Base docs]の属性メソッドのオーバーライドに関するセクションを読んだばかりで、 read_attributeを使用することをお勧めします。 `および write_attribute`メソッド 私は上の例でやっていることに何か問題があるに違いないと思った。そうでなければ、なぜ彼らはこれらのメソッドを属性メソッドをオーバーライドするための「正しい方法」として祝福するのでしょうか? 彼らはまた、より曖昧な慣用句を強制しているので、正当な理由がなければなりません…​

私の本当の質問:この例に何か問題がありますか?

4 Answer


205


Garethのコメントをエコーし​​ています…​ あなたのコードは書かれたように動作しません。 このように書き直す必要があります。

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

def name read_attribute(:name).downcase#nilをテストしませんか? 終わり


89


Aaron Longwellの答えを拡張したものとして、アクセサやミューテータをオーバーライドした属性にアクセスするために「ハッシュ記法」を使うこともできます。

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

def name self [:name] .downcase end


7


このトピックに関するいくつかの素晴らしい情報がhttp://errtheblog.com/posts/18-accessor-missingにあります。

長所と短所は、ActiveRecordがActiveRecord属性アクセサのスーパーコールを正しく処理することです。


-1


私はあなたが期待するように属性の上書きがsuperで動作するようにするrailsプラグインを持っています。 あなたはそれを githubで見つけることができます。

インストールするには:

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

使用するには:

クラスPost <ActiveRecord :: Base

has_overrides

module Overrides#このモジュールにgetterとsetterの上書きを入れます。 def title =(t)スーパー(tタイトル)end end end

それが終わったら、物事はただうまくいく:

$ ./script/console開発環境を読み込む(Rails 2.3.2)>> post = Post.new(:title => "単純なタイトル")
=> #
>> post.title = "もう一つの単純なタイトル"
=> 「もう一つの簡単なタイトル」
>> post.title
=> 「もう一つの簡単なタイトル」
>> post.update_attributes(:title => "更新タイトル")
=> 本当の
>> post.title
=> 「タイトル更新」
>> post.update_attribute(:title、 "単独で更新されたタイトル")
=> 本当の
>> post.title
=> "シングル更新タイトル"