Eager loading of polymorphic associations in ActiveRecord

后端 未结 3 764
日久生厌
日久生厌 2021-02-06 11:48

This is my first time using Rails and I was wondering if it\'s possible to load a has one polymorphic association in one SQL query? The models and associations between them are

相关标签:
3条回答
  • 2021-02-06 12:27

    (This is for Rails 3 syntax.)

    MetaWhere is an awesome gem for making complex queries that are outside of ActiveRecord's usual domain easy and ruby-like. (@wayne: It supports outer joins as well.)

    https://github.com/ernie/meta_where

    Polymorphic joins are a little trickier. Here's how I did mine with MetaWhere:

    Image.joins(:asset.type(AssetModel)).includes(:asset)
    

    In fact, I made a convenience method in my polymorphic-association-having class:

      def self.join_to(type)
        joins(:asset.type(type)).includes(:asset)
      end
    

    So it will always query & eager load a particular type of asset. I haven't tried mixing it with multiple types of join in one query. Because polymorphism works using the same foreign key to reference different tables, on the SQL level you have to specify it as separate joins because one join only joins to one table.

    This only works with ActiveRecord 3 because you have access to the amazing power of AREL.

    0 讨论(0)
  • 2021-02-06 12:37

    I ran up against this issue myself. ActiveRecord leans more toward the end of making it easy for Rubyists (who may not even be all too familiar with SQL) to interface with the database, than it does with optimized database calls. You might have to interact with the database at a lower level (e.g. DBI) to improve your performance. Using ActiveRecord will definitely affect how you design your schema.

    The desire for SQL efficiency got me thinking about using other ORMs. I haven't found one to suit my needs. Even those that move more toward transact SQL itself (e.g. Sequel) have a heavy Ruby API. I would be content without a Ruby-like API and just manually writing my T-SQL. The real benefit I'm after with an ORM is the M, mapping the result set (of one or more tables) into the objects.

    0 讨论(0)
  • 2021-02-06 12:45

    After digging through the Rails source I've discovered that you can force a join by referencing a table other than the current model in either the select, conditions or order clauses.

    So, if I specify an order on the Asset table:

    Image.first(
          :conditions => {:id => id},
          :include => :asset,
          :order => "asset.id"
    )
    

    The resulting SQL will use a left outer join and everything in one statement. I would have preferred an inner join, but I guess this will do for now.

    0 讨论(0)
提交回复
热议问题