ActiveRecord::EagerLoadPolymorphicError:Не могу с нетерпением загрузить полиморфную ассоциацию
-
21-09-2019 - |
Вопрос
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, отражающая модель, но должно ли это быть имя таблицы?
Решение
Здесь есть две проблемы:
- Суммирование по полиморфной ассоциации.
- Условие над полиморфной ассоциацией.
На самом деле вы не можете сделать ни одну из этих вещей.Таким образом, вы должны получить ту же ошибку, выполнив эти два запроса:
- Transactions.count(:all, :joins => :account)
- 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
Поэтому вам всегда следует использовать предварительную загрузку для полиморфных ассоциаций.