Comment utiliser non-ciblé sur les relations associées dans Rails3?

J’ai une scope par défaut sur les produits en raison de contraintes de sécurité des informations.

class Product < ActiveRecord::Base has_many :photos default_scope where('visible = 1') end 

Dans mon modèle de photo associé, cependant, je dois également trouver des produits qui ne devraient pas être visibles.

 class Photo < ActiveRecord::Base belongs_to :product end my_photo.product 

Dans d’autres cas, je peux utiliser non- scoped pour contourner le default_scope, par exemple dans Product.unscoped.find_by_title('abc') . Toutefois:

Comment supprimer la scope lors de l’utilisation d’associations d’un enregistrement?

my_photo.unscoped.product n’a pas de sens car my_photo ne dispose pas d’une méthode appelée non- unscoped . my_photo.product.unscoped n’a pas non my_photo.product.unscoped sens puisque my_photo.product peut-être déjà nul.

Oh. Je me suis trompé. Je pensais que ce qui suit ne fonctionnerait pas … mais il le fait:

 Product.unscoped do my_photo.product end 

Notez que vous devez appeler unscoped sur le modèle avec le default_scope qui doit être ignoré.

En outre, l’inheritance doit être respecté. Si vous avez la class InsuranceProduct < Product et class FinancialProduct < Product et un default_scope dans Product , toutes les deux combinaisons suivantes fonctionneront:

 InsuranceProduct.unscoped do my_record.insurance_products end FinancialProduct.unscoped do my_record.financial_products end Product.unscoped do my_record.products end 

Toutefois, les éléments suivants ne fonctionneront pas même si la scope est définie dans Product :

 Product.unscoped do my_record.financial_products end 

Je suppose que c'est un autre caprice de STI dans Ruby / Rails.

Une autre option consiste à remplacer la méthode getter et à supprimer le super:

 class Photo < ActiveRecord::Base belongs_to :product def product Product.unscoped{ super } end end 

J'ai rencontré la même situation où j'avais un modèle associé qui devait être décodé, mais dans presque tous les autres cas, il avait besoin de la scope par défaut. Cela devrait vous permettre d’économiser les appels supplémentaires si vous utilisez le getter d’assocation à plusieurs endroits.

Je suis probablement un peu en retard à la fête, mais il y a quelque temps, je me suis retrouvé dans la même situation et j’ai écrit un bijou pour le faire facilement: unscoped_associations .

Usage:

 belongs_to :user, unscoped: true 

Soutien:

  • appartient à
  • en a un
  • a beaucoup

Les associations polymorphes sont également supscopes.

Si vous souhaitez qu’une association spécifique ne soit jamais tronquée, vous pouvez la désélectionner lors de la définition de l’association:

 belongs_to :product, -> { unscope(where: :visible) } 

Pour une raison quelconque, la clé spécifique where clé ne se chargeait pas correctement, alors je me suis contenté de débloquer l’intégralité de l’ where , ce qui est une autre option qui fonctionne dans mon cas:

 belongs_to :product, -> { unscope(:where) } 

Les autres réponses valent également la peine d’être examinées, mais c’est une autre option pour Rails 4.1+.

Dans Rails 4, vous pouvez utiliser l’association avec un déblocage explicite du filtre indésirable, à savoir my_photo.product.unscope(where: :visible)

Ce n’est pas sur le sujet principal, mais sur votre problème avec ActiveRecord # devient: Nous avons (espérons-le) corrigé avec un initialiseur

  classe ActiveRecord :: Base

    def devient_with_association_cache (klass)
      devenu = devient_avec_association_cache (klass)
      devenu.instance_variable_set ("@ association_cache", @association_cache)
      devenu
    fin
    alias_method_chain: devient,: association_cache

  fin

https://gist.github.com/2478161

Nouvelle réponse

Cette question devrait vous aider à comprendre comment contourner la clause where par défaut pour votre association.

Cela vaut la peine de répéter que si vous devez régulièrement éviter une scope, cela devrait probablement être un défaut. Créez une étendue visible par défaut et utilisez-la explicitement dans vos associations.