Is it possible to get the ActiveRecord::Relation object for an association
Do association methods, such as those defined by
has_many
andbelongs_to
utilizeActiveRecord::Relation
?If so, is it possible to get the
ActiveRecord::Relation
object that is being used.
We're all aware that Rails 3 is heavily using ActiveRecord::Relation
objects, and Arel::Relation
objects in the background, when creating queries using the Query Interface. Whenever we use the select
, joins
, etc. methods of the Query Interface, a ActiveRecord::Relation
object is returned. However, this doesn't seem to be the case when calling an association method of a model. Instead, the query is executed immediately and an instance, or an array of instances, of the associated model is returned.
Consider the following models:
post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
user.rb
class user &开发者_StackOverflow社区lt; ActiveRecord::Base
has_many :posts
end
Example:
u = User.first
u.posts
Calling u.posts
returns an array of posts, not an instance of ActiveRecord::Relation
. I'm wondering if it's possible to get the ActiveRecord::Relation
that is being used by the association, if it is being used at all, perhaps by using Arel::Table
?
My reasoning for wanting the ActiveRecord::Relation
should be obvious: It is because I want to chain off the existing association and manipulate the query to suit a different purpose.
For a few minutes I used the where(nil)
hack, then I had a brainwave and tried something random:
User.first.posts.scoped
That's it! :D
Yeah, Rails + Arel is really poorly documented. Looking forward to it maturing to the point where I can actually look things up and get actual answers.
in Rails 4, use .scope
or .spawn
to access the relation object instead of the CollectionProxy
. See the documentation.
By taking the time to actually read the Edge Guides documentation, I was able to find an answer in Section 4.3 has_many
Association Reference. In short, the documentation does not shed light on whether it possible to get the ActiveRecord::Relation
object or whether an ActiveRecord::Relation
object is being used, but it does provide detail on how to reuse the association and tailor its result.
Section 4.3.1 Methods Added by has_many
lists the collection
.where
as being one of the methods that is added by the has_many
association. And section 4.3.1.11 collection
.where(…)
shows that you would use it just as you would user the where
method of the query interface. More importantly, it gives a hint that objects are lazily loaded when using this method on the collection, and sure enough, an ActiveRecord::Relation
object is returned.
u.posts.where("").class # => ActiveRecord::Relation
u.posts.where("").to_sql # => SELECT `posts`.* FROM `posts` WHERE `posts`.user_id = 1
Admittedly, not the ideal solution, but it does give me something I can chain off of.
In an ActiveSupport::Concern
, you can't call the private method spawn
or use scope
or scoped
.
I needed to use this.
where(true)
精彩评论