ActiveRecord::EagerLoadPolymorphicError:Не могу с нетерпением загрузить полиморфную ассоциацию

StackOverflow https://stackoverflow.com/questions/2079867

Вопрос

class Transaction < ActiveRecord::Base
  belongs_to :account, :polymorphic => true
end

class Bankaccount < ActiveRecord::Base
  has_many :transactions, :as => :account
end

class Creditcard < ActiveRecord::Base
  has_many :transactions, :as => :account
end

Пытаюсь сделать суммирование транзакций, где счет активен.

Transaction.sum(:all, :conditions => "account.status = 'active'", :include => :account)

Итак, после некоторого чтения я наткнулся на это:Причина в том, что тип родительской модели является значением столбца, поэтому соответствующее имя таблицы нельзя поместить в предложения FROM/JOIN этого запроса.Имя таблицы — банковские счета и кредитные карты. Означает ли это, что они должны быть в единственном числе?Кроме того, account_type — это строка Bankaccount или Creditcard, отражающая модель, но должно ли это быть имя таблицы?

Это было полезно?

Решение

Здесь есть две проблемы:

  1. Суммирование по полиморфной ассоциации.
  2. Условие над полиморфной ассоциацией.

На самом деле вы не можете сделать ни одну из этих вещей.Таким образом, вы должны получить ту же ошибку, выполнив эти два запроса:

  1. Transactions.count(:all, :joins => :account)
  2. Transactions.find(:all, :conditions => "accounts.status = 'active'", :joins => :account)

Чтобы действительно получить необходимую информацию, вы должны явно перечислить возможные родительские полиморфные ассоциации.Один из способов сделать это — просто использовать SQL и LEFT JOINS, чтобы вы могли использовать один запрос.Используя Rails, это можно выполнить с помощью двух запросов:

Creditcard.sum(
  :all, 
  :select => "transactions.amount", 
  :conditions => "creditcards.status = 'active'", 
  :joins => :transaction
) + Bankaccount.sum(
  :all, 
  :select => "transactions.amount", 
  :conditions => "bankaccounts.status = 'active'", 
  :joins => :transaction
)

P.S:Лучше всего использовать :join вместо :include, если вы не планируете получать доступ к объединенным объектам после запроса.

Другие советы

В дополнение к ответу Пана вы можете даже объединить их вместо того, чтобы добавлять их.который выполняет только один запрос

Для тех, кто получил эту ошибку, даже когда они не пытаются запросить условия полиморфной ассоциации, это связано с тем, что include решил вызвать нетерпеливую_загрузку, когда полиморфные ассоциации поддерживаются только предварительной загрузкой.Это в документации здесь: http://api.rubyonrails.org/v5.1/classes/ActiveRecord/EagerLoadPolymorphicError.html

Поэтому вам всегда следует использовать предварительную загрузку для полиморфных ассоциаций.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top