ruby-on-rails
  • activerecord
  • scope
  • associations
  • 2011-09-19 3 views 2 likes 
    2

    C'est ma configuration d'association et la portée:Comment puis-je joindre une association has_many avec une portée dans Active Record?

    has_many :owned_products 
    
    has_many :owned_lessons, :through => :owned_products, :source => :lesson, :conditions => "owned_products.product_type = 'Lesson'" 
    
    scope :active_purchase_scope, lambda { 
        where('owned_products.created_at' => (Date.today - CONFIG['downloads']['time_window'].days)..(Date.today)).order('owned_products.created_at DESC') 
    } 
    
    def active_lessons 
        owned_lessons.active_purchase_scope 
    end 
    

    Ceci est l'erreur que je reçois:

    ruby-1.8.7-p334 :005 > User.find_by_username('joeblow').active_lessons 
    NoMethodError: undefined method `active_purchase_scope' for #<User:0x1051a26c8> 
    

    da

    Répondre

    4

    Un scope peut être considérée comme une méthode de classe et un association peut être traité comme une méthode d'instance. Dans votre exemple de code, la méthode owned_lessons renvoie un objet tableau. Vous ne pouvez pas appeler active_purchase_scope sur l'objet de tableau (ou objet utilisateur pour cette question) que la portée ne peut être invoquée sur la classe du modèle (par exemple dans votre cas User.active_purchase_scope)

    Vous pouvez résoudre ce problème en ajoutant la portée sur le modèle Lesson

    class Lesson 
        has_many :owned_products 
    
        scope :active_purchase_scope, lambda { 
        include(::owned_products).where('owned_products.created_at' => 
          (Date.today - CONFIG['downloads']['time_window'].days)..(Date.today)). 
          order('owned_products.created_at DESC') 
        } 
    
    end 
    

    Et réécrire la classe utilisateur comme suit:

    class User 
    
        has_many :owned_products 
    
        has_many :owned_lessons, :through => :owned_products, :source => :lesson, 
           :conditions => "owned_products.product_type = 'Lesson'" 
    
    
        def active_lessons 
        owned_lessons.active_purchase_scope 
        end 
    
    end 
    

    le owned_lessons retourne un champ anonyme sur le modèle Lesson, nous pouvons donc enchaîner avec les s cope active_purchase_scope du même modèle.

    +0

    J'ai compris pourquoi cela ne fonctionnait pas (à cause de la classe Array), mais je ne sais toujours pas comment faire abstraction active_purchase_scope, car tous les produits devront l'utiliser, et pas seulement Lesson. En ce moment, mes modèles de produits n'héritent de rien. Devrais-je essayer de créer un modèle de produit dont tous les produits hériteraient (cela pourrait vraiment perturber les choses, parce que j'ai le product_id dans les tables de jointure) ou pourrais-je accomplir la même chose via un mixin? – pixelearth

    Questions connexes