# ActiveRecord hook to implement an automatic eager loading feature

**URL:** <https://discuss.rubyonrails.org/t/activerecord-hook-to-implement-an-automatic-eager-loading-feature/69190>\
**Category:** rubyonrails-core\
**Created:** [June 26, 2014, 12:28am UTC](https://discuss.rubyonrails.org/t/activerecord-hook-to-implement-an-automatic-eager-loading-feature/69190 "2014-06-26T00:28:23Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![G\_Sobrinho](https://avatars.discourse-cdn.com/v4/letter/g/b3f665/32.png) [@G\_Sobrinho](https://discuss.rubyonrails.org/u/G_Sobrinho)\
**Post date:** [June 26, 2014, 12:28am UTC](https://discuss.rubyonrails.org/t/activerecord-hook-to-implement-an-automatic-eager-loading-feature/69190/1 "2014-06-26T00:28:23Z")

</div>

Hello guys,

The Salsify Engineering team made a gem to automatic eager load associations on rails, take a look here: [http://blog.salsify.com/engineering/automatic-eager-loading-rails](http://blog.salsify.com/engineering/automatic-eager-loading-rails)

If you want to avoid to read the entire post, they made this:

> > blogs = Blogs.limit(5).to\_a

> # SELECT \* FROM blogs LIMIT 5

> 

> > blogs.each { |blog| blog.posts.to\_a }

> # SELECT \* FROM posts WHERE blog\_id IN (1,2,3,4,5)

Which I think that may make a huge sense for a lot of applications.

But active record seems to not provide a hook to do overwrite internals like that, they had to monkey patch a lot of methods here: [https://github.com/salsify/goldiloader/blob/master/lib/goldiloader/active\_record\_patches.rb](https://github.com/salsify/goldiloader/blob/master/lib/goldiloader/active_record_patches.rb)

I’m not pretty comfortable with active record source code but my suggestion is to make a accessor or a hook to use a custom collection proxy class.

Currently when we call blog.posts we receive a ActiveRecord::Associations::CollectionProxy object.

What if we can change active record to use a custom builder object, or a lambda, like that?

> ActiveRecord::Base.association\_builder = lambda do |source, instance, association|

> SharedAssociationProxy.build(source: source, instance: instance, association: association)

> end

> 

> class SharedAssociationProxy \< ActiveRecord::Associations::CollectionProxy

> def self.build(source:, instance:, association:)

> ```
> registry[source, association] ||= new(source.klass, association)
> 
> ```

> ```
> registry[source, association].append(instance)
> 
> ```

> end

> 

> def to\_a(instance)

> ```
> objects.select do |object|
> 
> ```

> ```
> object[reflection.primary_key] == object.id
> 
> ```

> ```
> end
> 
> ```

> end

> 

> protected

> 

> def objects

> ```
> @objects ||= reflection.klass.where(reflection.primary_key => instances.map(&:id))
> 
> ```

> end

> end

> 

> blogs = Blogs.limit(5).to\_a

> blogs.first.posts # will use the blogs as source since it fetched a collection

> =\> SharedAssociationProxy.build(source: blogs, instance: blog, association: :posts)

> 

> blog = Blog.first

> blog.posts # will use the blog as source since it was the only fetched

> =\> SharedAssociationProxy.build(source: blog, instance: blog, association: :posts)

Like I said, I’m not pretty comfortable with active record source code, then I don’t know the exactly details that need to be passed to the builder, lets focus just on the concept.

If we want a toggle option like the fully\_load made by Salsify guys, we can just check for it on the lambda or the builder.

About the to\_a method, it would be necessary to receive the model instance that is calling the to\_a method to do the necessary work, it would happen for all methods that can have a custom implementation: first, last, to\_a, etc.

What do you guys think about that?

Cheers,

Gabriel Sobrinho

[gabrielsobrinho.com](http://gabrielsobrinho.com)

---

<div class="post-metadata">

**Author:** ![G\_Sobrinho](https://avatars.discourse-cdn.com/v4/letter/g/b3f665/32.png) [@G\_Sobrinho](https://discuss.rubyonrails.org/u/G_Sobrinho)\
**Post date:** [June 26, 2014, 12:33am UTC](https://discuss.rubyonrails.org/t/activerecord-hook-to-implement-an-automatic-eager-loading-feature/69190/2 "2014-06-26T00:33:18Z")

</div>

Another interesting use would be on octopus which would allow us to send the association query to the right shard: [GitHub - thiagopradi/octopus: Database Sharding for ActiveRecord](https://github.com/tchandy/octopus)

We currently have a lot of monkey patches to make it work too: [octopus/association\_shard\_tracking.rb at master · thiagopradi/octopus · GitHub](https://github.com/tchandy/octopus/blob/master/lib/octopus/association_shard_tracking.rb)
