Issue with includes and merging associated model scope #7211

Closed
jerefrer opened this Issue Jul 31, 2012 · 2 comments

Comments

Projects
None yet
2 participants

To keep my code DRY I tend to reuse my scopes from my associated models in that way :

class ArticleType < ActiveRecord::Base
  scope :blogable, where(:blogable => true)
end
class Article < ActiveRecord::Base
  belongs_to :article_type

  scope :blogable, lambda { includes(:article_type).merge ArticleType.blogable        }
end

I like to use includes in each and every scope like that for performance reasons, as the associated article_type is often needed in the views.

Anyway, I then decided that the blogable scope needed to be more specific, leading to a bit more complex condition :

class ArticleType < ActiveRecord::Base
  scope :blogable, where('NOT blogable AND title != ?', 'NotBlog')
end

And then ... Errr (same with MySQL) :

SQLite3::SQLException: no such column: blogable: SELECT "articles".* FROM "articles"  WHERE (NOT blogable)

I tweaked things bit a realized that this scope works when using joins and not includes in the Article class.

So to me it appears there is a bug when using includes while merging a scope with custom SQL condition.

Here is a sample app showing the issue : https://github.com/jerefrer/cross_model_scope_bug

What do you think ?

The solution is that you have to use joins. Active Record does not force a join when using includes, since includes is a strategy to preload records to avoid N+1 queries - not meant for joins, they happen when necessary if Active Record knows it can do it without harm. And since the SQL condition is a string, it'll be added "raw" to the query, so you need to use joins. Note that in Rails master you'll have the references method for this particular scenario (please read the docs linked for more info).

Thanks!

Ok then, I'll use joins until Rails 4 is out ...

Thanks for the quick reply !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment