Keep loading some associations of one ORM object

I am creating a data model for a small application and would like to use an interesting loading in some methods - i.e. those where I know in advance that some associations will be used.

I read the Sequel :: Model :: Association manual for the method .eager

, but it confused me a little. A typical example would be:

Artist.eager( :albums => :tracks ).all

      

which loads all Artist objects with all their album fields preloaded and all tracks preloaded using only three queries. So far so good.

But I will say that I want to download one Artist by its master key and still have albums + tracks preloaded (still three requests, maybe much less than after associations for each album)? I don't see any example. A little experimenting gives me

Artist.eager( :albums => :tracks ).where( :id => id ).all.first

      

which at least works. I confirmed the impatience of loading by calling this, then disabling the db and showing that I can still access the associations.

However, I feel like I'm missing something. The construct that passes the primary key to the clause where

, gets the full set of data, and then asks for the first item, seems pretty awkward. I'm looking for something like this:

Artist.eager( :albums => :tracks )[ id ]

      

.., an easy way to declare that I want to load one object, and eagerly load some of its associations.

I found that I can create a custom association like this:

def eager_albums
  albums_dataset.eager( :tracks ).all
end

      

but this is awkward to use because the code must request communication in a different way.

My question is, does my construct Artist.eager( :albums => :tracks ).where( :id => id ).all.first

do what I think it does in Sequel, and can I do better (simpler code)?

+3


source to share


1 answer


The call Artist.eager( :albums => :tracks ).where( :id => id ).all.first

selects all artists with id equal to "id" and then fetches the first artist from the results array (the call all

materializes the array). Typically this query will only return an array with one artist.

Only after you actually ask for a relationship artist.albums

or association outside of the album will additional requests be made.

You can just do Artist.eager( :albums => :tracks ).where( :id => id ).first

I am using a tactical loadable plugin for loading , so it doesn't need to be used at all as it detects when an association is used with a model instance that is part of a larger result set and automatically loads a loaded load of related models for the entire result set. Now your request becomes Artist[id]

orArtist[id].albums.all

Another handy plugin I use is proxy plugins so I don't have to deal with using association.some_array_method

vsassociation_dataset.some_ds_method



Finally, the dataset associations plugin allows you to describe a query starting from some model or model class and chaining through associations with the target model while allowing you to define constraints (or not) along the way.

For example, "find all tracks longer than 3 minutes on any album released in the last 2 weeks by UK-born artists":

Artist.where(country_of_birth: 'UK').albums.where{ release_date > Date.today - 14}.tracks.where{ duration > 3.minutes }.all

Hope this sheds some light.

+5


source







All Articles