Dynamic eager loading associations

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.

Originally, the business scenario and possible solution in Rails was shared by me in my blog.

Does it make sense to implement something similar in ActiveRecord?

2 Likes

Is CanCanCan not the best fit for this use case?

In your case:

can :read, Song, published: true

See cancancan/fetching_records.md at develop · CanCanCommunity/cancancan · GitHub

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.

But you can use scopes to eager load relations too. :upside_down_face:

Do you mean calling merge? Something like that?

Artist.includes(:songs).merge(Song.visible_for(current_user))

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?

Like in the example below:

Artist.includes(:songs, :liked_songs).merge(Song.visible_for(current_user))