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


150

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

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

これは機能しているようですが、ActiveRecord :: Base docsの属性メソッドのオーバーライドに関するセクションを読んだだけで、read_attributeおよびwrite_attributeメソッドの使用を提案しています。上記の例で私がやっていることに何か問題があるに違いないと思いました。そうでなければ、なぜこれらのメソッドを属性メソッドをオーバーライドする「正しい方法」として祝福するのでしょうか?彼らはもっと醜いイディオムを強制しているので、それには正当な理由があるに違いない...

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

回答:


211

Garethのコメントをエコーし​​ています...コードは記述どおりに機能しません。次のように書き直す必要があります。

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

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

まさに私が必要としたもの。アーロン、ありがとう。
ボン

18
これはもはや真実ではありません。スーパーまたはこれのいずれかが現在機能します。ただし、ハッシュ表記はテストしていません。
ハートパンク2011

2
Rails 3では、Aaronによってここで指定されたリーダーメソッドは機能しますが、元のポスターが指定した(superに名前を与える)ライターは問題なく機能し、Aaronが示唆するように、IMHOは手動で属性を書き込むよりもきれいです。
Batkins、2011年

1
私は以下のmipadiによって与えられたハッシュ方式をテストしましたが、それは魅力のように機能します(Rails v 3.2.6)
almathie

正解ではないですか?@Aaronに感謝します。
サディクシャゴータム

94

Aaron Longwellの回答の拡張として、「ハッシュ表記」を使用して、オーバーライドされたアクセサーとミューテーターを持つ属性にアクセスすることもできます。

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

def name
  self[:name].downcase
end

ハッシュ表記は機能するかもしれませんself.attributeが、3.2.16でスタックをブローします。
jrhorn424 2014年

これは、それがサポートしているという利点がある||=不履行のために:def name; self[:name] ||= 'anon'; end
ポール・カントレル

私にとって、このハッシュ表記は機能します。しかし、なぜ機能するのかはわかりません。誰かが説明できますか?
radiantshaw 2018


-1

私はあなたが期待するようにスーパーで属性オーバーライドを機能させるrailsプラグインを持っています。githubで見つけることができます。

インストールするには:

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

使用するには:

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

あなたがそれをした後、物事はうまくいく:

$ ./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"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.