Eager Load Depending on Type of Association in Ruby on Rails

后端 未结 7 2340
温柔的废话
温柔的废话 2021-02-07 22:13

I have a polymorphic association (belongs_to :resource, polymorphic: true) where resource can be a variety of different models. To simplify the questio

7条回答
  •  情深已故
    2021-02-07 22:23

    You need to define associations in models like this:

    class Issue < ActiveRecord::Base
      belongs_to :resource, polymorphic: true
    
      belongs_to :order, -> { includes(:issues).where(issues: { resource_type: 'Order' }) }, foreign_key: :resource_id
      belongs_to :customer, -> { includes(:issues).where(issues: { resource_type: 'Customer' }) }, foreign_key: :resource_id
    end
    
    class Order < ActiveRecord::Base
      belongs_to :address
      has_many :issues, as: :resource
    end
    
    class Customer < ActiveRecord::Base
      belongs_to :location
      has_many :issues, as: :resource
    end
    

    Now you may do required preload:

    Issue.includes(order: :address, customer: :location).all
    

    In views you should use explicit relation name:

    <%- @issues.each do |issue| -%>
    <%- case issue.resource -%>
    <%- when Customer -%>
    <%= issue.customer.name %> <%= issue.customer.location.name %>
    <%- when Order -%>
    <%= issue.order.number %> <%= issue.order.address.details %>
    <%- end -%>
    

    That's all, no more n-plus-one queries.

提交回复
热议问题