ActiveRecord: Nested :include erroneous behavior


#1

Hi,
Found a simple example breaking on moving to 2.2 from 2.0. This
example illustrates the usage of nested :include finder options.

class Book < ActiveRecord::Base
has_many :distributors
end

class Distributor < ActiveRecord::Base
belongs_to :book
has_many :agents
end

class Agent < ActiveRecord::Base
belongs_to :distributor
has_many :shops
end

class Shop < ActiveRecord::Base
belongs_to :agent
end

Schema - http://pastie.org/426261

def test_should_load_avatars
shop_1= Shop.create!
shop_2= Shop.create!
book= Book.create!(:distributors => [Distributor.create!(:agents=>
[Agent.create!(:shops => [shop_2, shop_2])])])

loaded_version = Book.find(book.id, :include => [:distributors =>
{:agents => :shops}], :order => ‘shops.id’)

assert(loaded_version.distributors.first.agents.first.shops.size ==
2) #THIS ASSERTION FAILS WITH SHOPS.SIZE BEING 1, INSTEAD OF 2
end

On some investigation, I found that the query fired was correct, but
Rails was unable to instantiate the ‘shops’ collection properly.

Any help on this issue would be appreciated.

Thanks


#2

On Mar 25, 5:19 am, Akshay R. removed_email_address@domain.invalid wrote:

  1. #THIS ASSERTION FAILS WITH SHOPS.SIZE BEING 1, INSTEAD OF 2
    end

On some investigation, I found that the query fired was correct, but
Rails was unable to instantiate the ‘shops’ collection properly.

The problem is not to do with the nested-ness of the includes but
because you have an agent with the same shop twice (the line in
question that removes duplicates is
http://github.com/rails/rails/blob/f97832b1e4406a76d268a96b521d2297adec0ae3/activerecord/lib/active_record/associations.rb#L1781

Fred


#3

Bad paste. The problem again. Looks like it is a problem only when there
is
a has_one relationship.

class Book < ActiveRecord::Base
has_one :distributor
end

class Distributor < ActiveRecord::Base
belongs_to :book
has_many :agents
end

class Agent < ActiveRecord::Base
belongs_to :distributor
has_many :shops
end

class Shop < ActiveRecord::Base
belongs_to :agent
end

Schema - http://pastie.org/426261

def test_should_load_avatars
shop_1= Shop.create!
shop_2= Shop.create!
book= Book.create!(:distributor => Distributor.create!(:agents=>
[Agent.create!(:shops => [shop_1, shop_2])]))

loaded_version = Book.find(book.id, :include => [:distributor =>
{:agents
=> :shops}], :order => ‘shops.id’)

assert(loaded_version.distributor.agents.first.shops.size == 2)
#THIS ASSERTION FAILS WITH SHOPS.SIZE BEING 1, INSTEAD OF 2
end

This fails on Rails 2.2.2.
Any help on this would be much appreciated,
Akshay

On Mar 25, 2009 4:04am, Frederick C. removed_email_address@domain.invalid
wrote:

On Mar 25, 5:19 am, Akshay R. removed_email_address@domain.invalid> wrote:

def test_should_load_avatars

shop_1= Shop.create!

shop_2= Shop.create!

book= Book.create!(:distributors => [Distributor.create!(:agents=>

[Agent.create!(:shops => [shop_2, shop_2])])])

loaded_version = Book.find(book.id, :include => [:distributors =>

{:agents => :shops}], :order => ‘shops.id’)

assert(loaded_version.distributors.first.agents.first.shops.size ==

  1. #THIS ASSERTION FAILS WITH SHOPS.SIZE BEING 1, INSTEAD OF 2

end

On some investigation, I found that the query fired was correct, but

Rails was unable to instantiate the ‘shops’ collection properly.

The problem is not to do with the nested-ness of the includes but

because you have an agent with the same shop twice (the line in

question that removes duplicates is

http://github.com/rails/rails/blob/f97832b1e4406a76d268a96b521d2297adec0ae3/activerecord/lib/active_record/associations.rb#L1781

Fred

Any help on this issue would be appreciated.

Thanks


#4

Created a ticket for this issue at -
http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2341


#5

On Mar 25, 1:45 pm, removed_email_address@domain.invalid wrote:

Bad paste. The problem again. Looks like it is a problem only when there is
a has_one relationship.

Do you need all these models/associations or is there a small test
case that fails ?

Fred


#6

On Mar 25, 6:39 pm, akshay rawat removed_email_address@domain.invalid wrote:

Thanks for looking at it.A one file test -http://pastie.org/426840

Another thing I saw was that the that test passes when :include is replaced
with :joins.

Not surprising - in that case the association isn’t eager loaded at
all. If it passes without the order clause then you’ve narrowed it
down to the joins based include mechanism.

Fred


#7

Yup, it passes without the :order option, indicating that there is a
problem
with the join based mechanism. Thanks

On Wed, Mar 25, 2009 at 2:49 PM, Frederick C. <


#8

So is this a valid Rails bug ? Should I create a ticket for it on
Lighthouse
?


#9

On Mar 25, 10:01 pm, akshay rawat removed_email_address@domain.invalid wrote:

So is this a valid Rails bug ? Should I create a ticket for it on Lighthouse
?

Seems like you already have :-). I’d definitely check against 2.3.2 -
I remember there being a fix for a :include bug somewhere.

Fred


#10

Just checked, this test fails on Rails 2.3.2 too.
Thanks for looking into it.

On Wed, Mar 25, 2009 at 6:24 PM, Frederick C. <


#11

The ticket is at
https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2341-nested-finder-include-option-with-has_one#ticket-2341-4

Not sure how the ticket assignment thing works :wink:

Thanks


#12

Thanks for looking at it.A one file test - http://pastie.org/426840

Another thing I saw was that the that test passes when :include is
replaced
with :joins.

On Wed, Mar 25, 2009 at 2:05 PM, Frederick C. <