A bug in has_many :through/lazy loading?

Hi everybody,

I think I’ve encountered a very funny bug in the has_many :through, but
I’m not sure if it me doing something wrong. Let me post the example.

Consider the following migration/database structure:

create_table :books do |t|
t.column :title,:string
end

create_table :authors do |t|
t.column :name,:string
end

create_table :authorships do |t|
t.column :book_id, :numeric
t.column :author_id, :numeric
end

And the following models:

class Author < ActiveRecord::Base
has_many :authorships, :dependent => true
has_many :books, :through => :authorships
end

class Authorship < ActiveRecord::Base
belongs_to :book
belongs_to :author
end

class Book < ActiveRecord::Base
has_many :authorships, :dependent => true
has_many :authors, :through => :authorships
end

Now to the funny part. If I do something like this

b = Book.create(:title => ‘A Book’)
a = Author.create(:name => ‘An Author’)
Authorship.create(:book => b, :author => a)
puts b.authors.length

It will of course output 1

HOWEVER, if I read the b.authors before creating an association, the
b.authors won’t get updated! So, in this example, having

b = Book.create(:title => ‘A Book’)
a = Author.create(:name => ‘An Author’)

puts b.authors.length # ACCESSING THE COLLECTION HERE

Authorship.create(:book => b, :author => a)

puts b.authors.length

Will output both times a zero!

On Feb 8, 2007, at 6:51 AM, Esad H. wrote:

end
And the following models:

puts b.authors.length

Authorship.create(:book => b, :author => a)

puts b.authors.length

Will output both times a zero!

Try: puts b.authors(true).size

See the section of
http://api.rubyonrails.org/classes/ActiveRecord/Associations/
ClassMethods.html
under the “Caching” heading

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

I don’t think it’s a bug (from what i remember of the Rail’s Pragmatic
book) because the association isn’t reloaded.
if you do : b.authors(true).length for reload = true which is set to
false by default, you’ll get the right answer.
But then the railsway to do it is :
b = Book.create(:title => ‘A Book’)
a = Author.create(:name => ‘An Author’)
b.authors << a
and the reload is (should be) done automatically

Charly