70

情報セキュリティの制約により、製品の既定のスコープがあります。

class Product < ActiveRecord::Base
  has_many :photos

  default_scope where('visible = 1')
end

ただし、関連付けられている Photo モデルでは、表示されてはならない製品も検索する必要があります。

class Photo < ActiveRecord::Base
  belongs_to :product
end

my_photo.product

他の場合では、default_scope をバイパスするためにunscopedProduct.unscoped.find_by_title('abc')を使用できます。でも:

レコードの関連付けを使用するときにスコープを削除するには?

my_photo.unscoped.productmy_photo には というメソッドがないため意味がありませんunscoped。すでに nil である可能性があるため、どちらもmy_photo.product.unscoped意味がありません。my_photo.product

4

7 に答える 7

71

おー。私はだまされました。以下はうまくいかないと思った...しかし、うまくいく:

Product.unscoped do
  my_photo.product
end

バイパスする必要のあるを使用して、モデルで unscoped を呼び出す必要があることに注意してくださいdefault_scope

また、継承を尊重する必要があります。class InsuranceProduct < Productclass FinancialProduct < Productとがある場合、次の 2 つの組み合わせのすべてが機能しますdefault_scopeProduct

InsuranceProduct.unscoped do
  my_record.insurance_products
end

FinancialProduct.unscoped do
  my_record.financial_products
end

Product.unscoped do
  my_record.products
end

ただし、スコープは で定義されていますが、以下は機能しませんProduct

Product.unscoped do
  my_record.financial_products
end

Ruby / Rails における STI のもう 1 つの癖だと思います。

于 2011-01-21T13:08:21.190 に答える
54

もう 1 つのオプションは、getter メソッドをオーバーライドし、super のスコープを解除することです。

class Photo < ActiveRecord::Base
  belongs_to :product

  def product
    Product.unscoped{ super }
  end
end

スコープを解除する必要がある関連付けられたモデルが 1 つあるという同じ状況に遭遇しましたが、他のほとんどすべてのケースでは、デフォルトのスコープが必要でした。これにより、関連ゲッターを複数の場所で使用している場合、スコープ外への余分な呼び出しを節約できます。

于 2012-06-13T15:43:24.307 に答える
17

特定の関連付けを常にスコープ外にする必要がある場合は、関連付けを定義するときにスコープを解除できます。

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

何らかの理由で、特定のwhereキーが正しく読み込まれなかったので、全体のスコープを解除しましたwhere。これは、私の場合にうまくいく別のオプションです。

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

他の回答も検討する価値がありますが、これは Rails 4.1+ の別のオプションです。

于 2016-10-29T17:32:51.553 に答える
1

それは主なトピックではありませんが、ActiveRecord#becomes に関するあなたの問題についてです: 私たちは (うまくいけば) 初期化子でそれを修正しました

クラス ActiveRecord::Base

   def become_with_association_cache(クラス)
     になった = become_without_association_cache(klass)
     become.instance_variable_set("@association_cache", @association_cache)
     なりました
   終わり
   alias_method_chain :becomes, :association_cache

 終わり

https://gist.github.com/2478161

于 2012-04-24T09:21:46.397 に答える
0

新しい答え

この質問は、関連付けのデフォルトの where 句をバイパスする方法を理解するのに役立ちます。

繰り返しますが、定期的にスコープを回避する必要がある場合は、おそらくデフォルトにする必要があります。visibleデフォルト以外のスコープを作成し、それを関連付けで明示的に使用します。

于 2011-01-21T11:56:33.023 に答える