This project is archived and is in readonly mode.

#576 ✓wontfix
cainlevy

allow explicit association preloading (:load vs :include)

Reported by cainlevy | July 8th, 2008 @ 07:49 PM | in 2.x

The attached patch adds a :load option for ActiveRecord.

I've found it useful to be able to specify associations for preloading through a :load option that is independent of the :include option. There are two benefits that I can see:

1) When any :include association is referenced in condition/grouping/order SQL, then all :include associations are retrieved via SQL joins. Adding a separate :load option allows a developer to optimize which associations are joined and which are preloaded.

2) Associations that are preloaded do not affect the result set, whereas associations that are loaded through SQL joins do.

In my case, I'm using the :load option to set up named_scope's that do nothing more than optimize a result set for a particular context, e.g. Posts.for_home_page.by_recency.

Comments and changes to this ticket

  • cainlevy

    cainlevy July 9th, 2008 @ 12:09 AM

    After some discussion in #rails-contrib, I came to see this new option as completing a triad:

    • :include names associations that should be eager loaded but may also be needed for sql references (e.g. in conditions, orders, etc.)
    • :joins names associations that are needed for sql references but should not be loaded
    • :load names associations that should be loaded but are not needed for sql references

    API bloat is something to be taken seriously. In this case I feel like the new option rounds out the use cases, and is not bloat.

    Thoughts?

  • hiroshi

    hiroshi August 17th, 2008 @ 01:36 PM

    I express approval about the :load option.

    cainlevy suggested capabilities against optimization, moreover, I point out that a problem of 'join' eager loading has_many association with group option.

    For example, Ticket has_many :tags, and I would like to find tickets which has tags, 'foo' and 'bar', also I prefer eager loading because search result will show tags for each ticket. The code can be like that:

    
    #
    Ticket.find(:all,
      :include => :tags,
      :joins => "INNER JOIN tags AS t ON t.ticket_id = tickets.id",
      :conditions => ["t.name IN (:tags)", {:tags => ['foo', 'bar']}],
      :group => "t.ticket_id HAVING COUNT(t.ticket_id) >= 2")
    

    This call of find() internally uses find_with_associations (join eager loading) instead of preload_associations. Any of the resulted ticket included only one tag (because ticket is grouped by own id), but they may have two or more tags.

  • hiroshi

    hiroshi August 17th, 2008 @ 01:49 PM

    I also found a quick option (a hack?) for explicit association preloading.

    
    tickets = Ticket.find(:all,
    # :include => :tags,
      :joins => "INNER JOIN tags AS t ON t.ticket_id = tickets.id",
      :conditions => ["t.name IN (:tags)", {:tags => ['foo', 'bar']}],
      :group => "t.ticket_id HAVING COUNT(t.ticket_id) >= 2")
    Ticket.send(:preload_associations, tickets, :tags)
    

    It worked (for me).

  • Pratik

    Pratik August 18th, 2008 @ 04:30 PM

    Please discuss in the core mailing list. Meanwhile, you could write a simple plugin with hiroshi's suggestion.

  • Pratik

    Pratik August 18th, 2008 @ 04:31 PM

    • State changed from “new” to “wontfix”
  • cainlevy

    cainlevy August 18th, 2008 @ 10:38 PM

    I use the following patch in my own project:

    
    class ActiveRecord::Base
      class << self
        private
        def find_every_with_explicit_preloading(options)
          returning find_every_without_explicit_preloading(options) do |records|
            to_load = merge_includes(scope(:find, :load), options[:load])
            preload_associations(records, to_load) if to_load
          end
        end
        alias_method_chain :find_every, :explicit_preloading
    
        VALID_FIND_OPTIONS << :load
      end
    end
    

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Pages