Belongs_to not saving foreign key


#1

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?


#2

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 removed_email_address@domain.invalid wrote:

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


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


#3

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


#4

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.


#5

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


#6

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. removed_email_address@domain.invalid


#7

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/