Rails bug? Conditions on associations ignored by eager loadi

I’m looking for someone to confirm the following as a bug in Rails
1.0 before I post it to Trac.

If I use eager loading on an association that has conditions defined,
the conditions are ignored.

The following example illustrates the problem. I have two tables:

create_table “blogs”, :force => true do |t|
t.column “name”, :string
end

create_table “posts”, :force => true do |t|
t.column “blog_id”, :integer
t.column “subject”, :string
t.column “published”, :boolean
end

The model for blogs looks like this:

class Blog < ActiveRecord::Base
has_many :posts
has_many :published_posts, :class_name => ‘Post’, :foreign_key
=> ‘blog_id’, :conditions => ‘published = 1’
end

Now add some sample data for blogs:

example:
id: 1
name: Example

and for posts:

published:
id: 1
blog_id: 1
subject: Published
published: 1

unpublished:
id: 2
blog_id: 1
subject: Unpublished
published: 0

The problem is that:

Blog.find(:all, :include => :published_posts).first.published_posts

returns all the posts for the blog, not just the published ones. The
SQL generated looks like this:

SELECT posts.id AS t1_r0, posts.blog_id AS t1_r1,
blogs.id AS t0_r0, posts.subject AS t1_r2,
blogs.name AS t0_r1, posts.content AS t1_r3,
posts.published AS t1_r4
FROM blogs LEFT OUTER JOIN posts ON posts.blog_id = blogs.id

The following, on the other hand, returns just the posts marked as
published:

Blog.find(:all).first.published_posts

If anyone wants a simple sample project to test this, let me know and
I’ll tar up my example.

Cheers,

Pete Y.

On 1/30/06, Pete Y. [email protected] wrote:

I’m looking for someone to confirm the following as a bug in Rails
1.0 before I post it to Trac.

If I use eager loading on an association that has conditions defined,
the conditions are ignored.

This bug has been around for quite a long time. If you look at
ActiveRecord::Associations::ClassMethods#association_join you’ll see
that it doesn’t add the reflection conditions when it joins the tables
(which it would need to do to properly load the eager associations).
FWIW, the patch in ticket 1562 fixes this (and some other long
standing bugs/limitations), and should apply cleanly to 1.0 (though
probably not Edge Rails).

On 1/30/06, Pete Y. [email protected] wrote:

Thanks, Jeremy. Looks like that path addresses one of my other most
hated issues: the inability to use eager loading on two associations
that reference the same table.

Given this patch isn’t applicable to edge rails due to major internal
reworking of ActiveRecord, any idea what’s happening with this
functionality for rails 1.1? I don’t really want to commit my code to
depending on the patch, given that I’m looking forward to being able
to use :through on associations in the near future.

You’d have to ask the Rails core team. They closed the ticket with a
wontfix, because another patch merged it (2172), and then that patch
has languished as an XPATCH, with the author stating it needs a
complete rewrite. The patch in ticket 1562 isn’t perfect but does
work and passes every test but one. I’d like to refactor it so it you
could manually specify the alias name to use when eager loading, which
would fix the main problem with it (it aliases all tables even if it
isn’t necessary). But it’s not going to be worth it unless the core
team plans on applying it.

Assuming I’m not using the patch, is there a way to work around the
issue? Simply applying the condition again as a :conditions argument
to find won’t work, because the condition needs to be applied to the
association rather than the where clause of the whole query.

I converted the patch to a plugin, the details are on the wiki
(http://wiki.rubyonrails.org/rails/pages/Allow+Multiple+Associations+Same+Table+Plugin).

Thanks, Jeremy. Looks like that path addresses one of my other most
hated issues: the inability to use eager loading on two associations
that reference the same table.

Given this patch isn’t applicable to edge rails due to major internal
reworking of ActiveRecord, any idea what’s happening with this
functionality for rails 1.1? I don’t really want to commit my code to
depending on the patch, given that I’m looking forward to being able
to use :through on associations in the near future.

Assuming I’m not using the patch, is there a way to work around the
issue? Simply applying the condition again as a :conditions argument
to find won’t work, because the condition needs to be applied to the
association rather than the where clause of the whole query.

Cheers,

Pete Y.

Thanks again, Jeremy. The plugin works a treat, and saves me mucking
around with freezing my app to Rails 1.0, patching, etc.

I might post something on the rails core list about the status of
these things for Rails 1.1.

Cheers,

Pete Y.