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 Thomas’)

pickaxe = dave.books.build(:title => ‘Programming Ruby 1.9’)

Jeff Schoolcraft 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.

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.

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

Sean K wrote:

Sean K wrote:

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?

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.