これはまったく問題ではありませんが、write_attribute
の問題がRails 'Active Record
のオブジェクトである場合の解決方法に関するレポートです。これが同じ問題に直面している他の人にも役立つことを願っています。ActiveRecordでのセッターオーバーライドの問題
例を説明しましょう。非常にシンプルな
class Book < ActiveRecord::Base
belongs_to :author
end
class Author < ActiveRecord::Base
has_many :books
end
:あなたは二つのクラス、Book
とAuthor
があるとします。しかし、何らかの理由でBook
のauthor
=メソッドを無効にする必要があります。私がRailsに慣れていない私は、Railsを使ったAgile Web Developmentに関するSam Rubyの提案に従いました。attribute_writer
privateメソッドを使用してください。だから私の最初の試行は:
class Book < ActiveRecord::Base
belongs_to :author
def author=(author)
author = Author.find_or_initialize_by_name(author) if author.is_a? String
self.write_attribute(:author, author)
end
end
残念ながら、これは動作しません。それは私が、コンソールから得るものです:
>> book = Book.new(:name => "Alice's Adventures in Wonderland", :pub_year => 1865)
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author = "Lewis Carroll"
=> "Lewis Carroll"
>> book
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author
=> nil
それはRailsのは、それがオブジェクトであり、何も行いません認識していないようです:attribuition後、著者はまだゼロであります!もちろん、私はwrite_attribute(:author_id, author.id)
を試すことができますが、作者がまだ保存されていない(まだIDがありません!)と、オブジェクトを一緒に保存する必要があります(著者が本が有効な場合のみ保存する必要があります)。 http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/4fe057494c6e23e8ので、最終的に私はいくつかの作業コード持っていた可能性があり:
は、検索した後、溶液のためにたくさん(と無駄に他の多くのものを試してみてください)、私はこのメッセージを見つけ
class Book < ActiveRecord::Base
belongs_to :author
def author_with_lookup=(author)
author = Author.find_or_initialize_by_name(author) if author.is_a? String
self.author_without_lookup = author
end
alias_method_chain :author=, :lookup
end
にこの時間は、コンソールがいました私にすてきな:
>> book = Book.new(:name => "Alice's Adventures in Wonderland", :pub_year => 1865)
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author = "Lewis Carroll"=> "Lewis Carroll"
>> book
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author
=> #<Author id: nil, name: "Lewis Carroll", created_at: nil, updated_at: nil>
ここのトリックは、古いセッター(author_without_lookup
)への代替名(この場合はauthor_with_lookup
で)インターセプタを作成alias_method_chain
、です。私はこの取り決めを理解するのに時間がかかったと告白します。誰かがそれを詳細に説明してくれたらうれしいですが、私にはこの種の問題に関する情報がないことに驚いたのです。私はただ1つの投稿を見つけるためにたくさんのGoogleを持っていなければなりません。タイトルは当初は問題に無関係だったようです。私はRailsが新しくなっています。だからあなたはどう思うのですか?これは悪い習慣ですか?
を使用してこの問題を解決し、私はこれを行うために思ったが、私は、重複する属性を望んでいませんでした。私が上で提案した方法は非常にうまくいっています。私はちょうどそれを共有したいと思った。私は確かにそれでtext_fieldトリックを作ることができます。しかし、あなたの返信をありがとう! = D –
'delegate:name、:to:author::prefix => true'で' author_name'メソッドを置き換える方が正しいのでしょうか? –
@Adam、それは確かにそれを行う別の方法です。私は通常、複数のメソッドを扱うときにのみ 'delegate'を使います。 1つしかない場合は、メソッドを直接定義する方が好きです。なぜなら、より明確に感じるからです。 – ryanb