Sequel has a concept of dynamic eager loading associations. Not to be wordy, consider the following code example:
class Artist < Sequel::Model
one_to_many :songs
end
# somewhere in the controller
Artist.eager(songs: -> (ds) { current_user ? ds : ds.where(status: :published) })
The construction with block literally implements this logic: if use is not authenticated there should be visible only published songs, otherwise all songs are visible.
I don’t think it’s the same. CanCan defines a scope. But the suggestion is for having this thing for associations so that it works with eager loading.
That might work. But then it comes to the question: what if there is another association, e.g. “artist has many liked_songs” that needs eager loaded but doesn’t need that filter?
I came here to propose exactly this. I’ve proved out the concept in prior art (occams-record and more recently uberloader), but having proper support in ActiveRecord would be amazing.
I’d be happy to help work on this, but there are a lot of design questions. One difference from the OP is that all my designs so far have used nested blocks for nested associations. An example from uberloader:
widgets = Widget
.where(category_id: category_ids)
# Preload category
.uberload(:category)
# Preload parts, ordered by name
.uberload(:parts, scope: Part.order(:name)) do |u|
# Preload the parts' manufacturer
u.uberload(:manufacturer)
# and their subparts, using custom scopes
u.uberload(:subparts) do
u.scope my_subparts_scope_helper
u.scope Subpart.where(type: params[:subparts_types]
) if params[:subparts_types]&.any?
u.uberload(:foo) do
u.uberload(:bar)
end
end
end
I know it’s a bit different than how AR traditionally does things, but for giant nested associations I find it a heck of a lot more readable. It also allows for other options besides scope to be added at some point.
But more importantly, this doesn’t (necessarily) have anything to do with authorization, as some have suggested. (Even when it does involve authz, not everyone uses CanCan). It’s a more general need for customizable preloads - there’s a ton of ActiveRecord::Relation power locked away behind those deeply nested Hashes we all pass to preload. Let’s unlock it!