Is it possible to get the ActiveRecord::Relation object for an association
Solution 1
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.
Solution 2
in Rails 4, use .scope
or .spawn
to access the relation object instead of the CollectionProxy
. See the documentation.
Solution 3
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.
Solution 4
In an ActiveSupport::Concern
, you can't call the private method spawn
or use scope
or scoped
.
I needed to use this.
where(true)
John
Updated on June 06, 2022Comments
-
John almost 2 years
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, andArel::Relation
objects in the background, when creating queries using the Query Interface. Whenever we use theselect
,joins
, etc. methods of the Query Interface, aActiveRecord::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 < ActiveRecord::Base has_many :posts end
Example:
u = User.first u.posts
Calling
u.posts
returns an array of posts, not an instance ofActiveRecord::Relation
. I'm wondering if it's possible to get theActiveRecord::Relation
that is being used by the association, if it is being used at all, perhaps by usingArel::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. -
John over 13 yearsLove it. Much cleaner! I'm giving you the CHECKMARK. And I agree about the Arel documentation. I've been reading scraps and bits all over the place about it. It seems very powerful, but without good documentation, it can be quite annoying as well. :)
-
brittohalloran over 12 yearsis there a way to call
.scoped
on a custom array that I made? -
Matchu over 11 years(The answer to that is no:
scoped
only makes sense on a top-level class :/) -
Roman almost 11 yearsInterestingly .scoped even works for has_and_belongs_to_many, which otherwise returns an Array.
-
Cyzanfar over 7 years
.scoped
is depreciated