Belongs_to not saving foreign key

Under Rails 2.3.2 using a completely brand new project, I have 2
models:

class Author < ActiveRecord::Base

name:string

end

class Book < ActiveRecord::Base

title:string

belongs_to :author # author_id
end

And a simple test where i create a Book with an Author using the
belongs_to and then update the foreign key directly:

require ‘test_helper’

class BookTest < ActiveSupport::TestCase
test “foreign key updating” do
a1 = Author.create! :name => ‘author 1’
b = Book.create! :title => ‘rails’, :author => a1
a2 = Author.create! :name => ‘author 2’
b.update_attributes! :author_id => a2.id
assert_equal a2.id, b.author_id # author_id is still a1.id!
end
end

The test fails on the last line. Am i doing something wrong or is
this expected behaviour?

your Author should :have_many :books
You also want to do something like this:

dave = Author.create(:name => ‘Dave T.’)
pickaxe = dave.books.build(:title => ‘Programming Ruby 1.9’)

On Sun, May 24, 2009 at 3:46 AM, Sean K [email protected] wrote:

belongs_to :author # author_id
b = Book.create! :title => ‘rails’, :author => a1


Jeff S.
http://thequeue.net/blog/

Jeff S. is right. Your Author model should have this line

:has_many :books

In faat you should specify all the db relations in your model files,
all of them.

cheers

Thanks for the replies. However, changing the Author to:

class Author < ActiveRecord::Base
has_many :books
end

doesn’t change the outcome of the test. The problem that i’m having
seems to be that the foreign key (Book.author_id) is not being updated
by update_attributes. This smells like a bug to me.

before the update_attributes line, try adding

b = Book.find(:first, “title => ‘rails’”)

then

b.update_attributes! :author_id => a2.id

It seems that update_attributes will work from found object, not newly
created object, and this is normally done under update action of
controller

You are correct, Jeff, setting the author using the create method on a
has_many works:

test “something” do
a1 = Author.create! :name => ‘author 1’
b = a1.books.create! :title => ‘rails’
a2 = Author.create! :name => ‘author 2’
b.update_attributes! :author_id => a2.id
assert_equal a2.id, b.author_id
end

And so does setting the author via the foreign key:

test “something” do
a1 = Author.create! :name => ‘author 1’
b = Book.create! :title => ‘rails’, :author_id => a1
a2 = Author.create! :name => ‘author 2’
b.update_attributes! :author_id => a2.id
assert_equal a2.id, b.author_id
end

So why doesn’t it like it when the belongs_to is used? Seems odd.

On May 24, 6:04 am, Jeff S. [email protected]

belongs_to :author # author_id
b = Book.create! :title => ‘rails’, :author => a1
a2 = Author.create! :name => ‘author 2’
b.update_attributes! :author_id => a2.id
assert_equal a2.id, b.author_id # author_id is still a1.id!
end
end

The test fails on the last line. Am i doing something wrong or is
this expected behaviour?

Actually when you update the attribute for the one object, the ram-
cached copy isn’t updated for the other (association), so you need to
reload it.

b.reload

you’re probably better off saying:

b.author = a2

I think.


Blog: http://random8.zenunit.com/
Twitter: http://twitter.com/random8r
Learn: http://sensei.zenunit.com/
Latest: How to use Unix basics at http://sensei.zenunit.com/