2012-03-14 4 views
3

Je donne les résultats suivants:Arel et association polymorphique rejoint

class BaseReseller < ActiveRecord::Base 

    set_table_name "resellers" 

    acts_as_nested_set 

    has_many :merchants, :as => :merchant_owner, :dependent => :destroy 
end 

class IPSP < BaseReseller 
end  

class Agent < BaseReseller 
end 

class Reseller < BaseReseller 
end 

class Merchant < ActiveRecord::Base 
    belongs_to :merchant_owner, :polymorphic => true 
end 

class MerchantsController < ApplicationController 
    ... 
    def index 
    ... 
    @merchants = Merchant.joins(:merchant_owner) # breaks! 
    end 
end 

Remarquez que je suis en train de rejoindre le marchand avec le merchant_owner polymorphes et obtenez ceci: ActiveRecord :: EagerLoadPolymorphicError: Ne peut pas charger avec impatience l'association polymorphique : merchant_owner. @merchants = Merchant.includes (: merchant_owner) fonctionne initialement, mais lorsque je commence à parcourir le tableau @merchants dans les vues, il se brise avec la même erreur - semble-t-il parce que nous travaillons avec des relations paresseusement chargées et seulement quand une méthode non-Arel est invoquée, elle va réellement à la base de données.

Des idées? Est-ce que Arel supporte les jointures d'associations polymorphes? Des solutions de contournement? Je peux tomber au SQL pur mais c'est piggy.

Merci

Répondre

0

Le problème était une colonne manquante dans l'une des tables. Rails supporte très bien les associations polymorphes entre les hiérarchies STI, mais attention aux colonnes correctes pour le polymorphisme, STI, etc.

0

Cela peut être trop demander de Arel, je ne suis pas sûr d'une excellente solution. Dans votre cas, il semble que tous les merchant_owners partagent la même table de revendeurs. Il est donc logique de vouloir se joindre à l'association polymorphe, mais en général, les associations polymorphes peuvent se rapporter à différents modèles (pour différentes tables) . Cela deviendrait très moche en SQL et probablement assez lent dans le cas général, c'est pourquoi je pense qu'EagerLoadPolymorphicError existe. Pour votre situation, il pourrait être judicieux de travailler autour avec quelque chose comme:

Merchant.joins("INNER JOIN resellers on merchant_owner_id = resellers.id") 

Bien sûr, il serait plus propre pour ce joindre à une portée de votre modèle pour que vous puissiez faire juste Merchant.joined_with_owners et SQL relégués à la couche de modèle. Cela ne fonctionnerait cependant pas si d'autres modèles, non revendeurs, avaient beaucoup de commerçants. Je suis un peu surpris que vous voyez la même erreur avec Merchant.includes (: merchant_owner), je ne vois pas cela avec des données similaires même si j'accède à divers attributs, mais pourrait être dû à diverses différences.

Essayez-vous d'effectuer un chargement avec impatience pour des raisons de performances ou parce que vous avez des clauses Arel supplémentaires qui dépendent des attributs du revendeur? Si c'est pour la performance, il vaut mieux revenir sur SQL ...

+1

En fait, vous voudrez probablement protéger cette jointure en ajoutant "and merchant_owner_type in ('Agent' , 'Revendeur', 'IPSP') " – njorden

Questions connexes