title: Issue with setter override on ActiveRecord
body: <p>This is not exactly a question, it's rather a report on how I solved an issue with <code>write_attribute</code> when the attribute is an object, on Rails' <code>Active Record</code>. I hope this can be useful to others facing the same problem.</p>
  
  <p>Let me explain with an example. Suppose you have two classes, <code>Book</code> and <code>Author</code>:</p>
  
  <pre><code>class Book &lt; ActiveRecord::Base
    belongs_to :author
  end
  
  class Author &lt; ActiveRecord::Base
    has_many :books
  end
  </code></pre>
  
  <p>Very simple. But, for whatever reason, you need to override the <code>author</code>= method on <code>Book</code>. As I'm new to Rails, I've followed the Sam Ruby's suggestion on Agile Web Development with Rails: use <code>attribute_writer</code> private method. So, my first try was:</p>
  
  <pre><code>class Book &lt; 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
  </code></pre>
  
  <p>Unfortunately, this does not work. That's what I get from console:</p>
  
  <pre><code>&gt;&gt; book = Book.new(:name =&gt; "Alice's Adventures in Wonderland", :pub_year =&gt; 1865)
  =&gt; #&lt;Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil&gt;
  &gt;&gt; book.author = "Lewis Carroll"
  =&gt; "Lewis Carroll"
  &gt;&gt; book
  =&gt; #&lt;Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil&gt;
  &gt;&gt; book.author
  =&gt; nil
  </code></pre>
  
  <p>It seems that Rails does not recognize it is an object and makes nothing: after the attribuition, author is still nil! Of course, I could try <code>write_attribute(:author_id, author.id)</code>, but it does not help when the author is not saved yet (it still has no id!) and I need the objects be saved together (author must be saved only if book is valid).</p>
  
  <p>After search a lot for a solution (and try many other things in vain), I found this message: <a href="http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/4fe057494c6e23e8" rel="nofollow noreferrer">http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/4fe057494c6e23e8</a>, so finally I could had some working code:</p>
  
  <pre><code>class Book &lt; 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
  </code></pre>
  
  <p>This time, the console was nice to me:</p>
  
  <pre><code>&gt;&gt; book = Book.new(:name =&gt; "Alice's Adventures in Wonderland", :pub_year =&gt; 1865)
  =&gt; #&lt;Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil&gt;
  &gt;&gt; book.author = "Lewis Carroll"=&gt; "Lewis Carroll"
  &gt;&gt; book
  =&gt; #&lt;Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil&gt;
  &gt;&gt; book.author
  =&gt; #&lt;Author id: nil, name: "Lewis Carroll", created_at: nil, updated_at: nil&gt;
  </code></pre>
  
  <p>The trick here is the <code>alias_method_chain</code>, that creates an interceptor (in this case <code>author_with_lookup</code>) and an alternative name to the old setter (<code>author_without_lookup</code>). I confess it took some time to understand this arrangement and I'd be glad if someone care to explain it in detail, but what surprised me was the lack of information about this kind of problem. I have to google a lot to find just one post, that by the title seemed initially unrelated to the problem. I'm new to Rails, so what do you think guys: is this a bad practice?</p>