web-dev-qa-db-ja.com

Rails3の関連するリレーションでスコープなしを使用する方法は?

情報セキュリティの制約により、製品にはデフォルトのスコープがあります。

_class Product < ActiveRecord::Base
  has_many :photos

  default_scope where('visible = 1')
end
_

ただし、関連付けられている写真モデルでは、表示されるべきではない製品も見つける必要があります。

_class Photo < ActiveRecord::Base
  belongs_to :product
end

my_photo.product
_

他の場合、default_scopeをバイパスするために nscoped を使用できます。 Product.unscoped.find_by_title('abc')で。しかしながら:

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

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

62
crispy

ああ。私は自分をだましました。以下はうまくいかないと思ったが...

Product.unscoped do
  my_photo.product
end

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

また、継承は尊重されなければなりません。 class InsuranceProduct < Productclass FinancialProduct < ProductProductdefault_scopeがある場合、次の2つの組み合わせはすべて機能します。

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。

62
crispy

別のオプションは、ゲッターメソッドをオーバーライドし、スーパースコープを解除することです。

class Photo < ActiveRecord::Base
  belongs_to :product

  def product
    Product.unscoped{ super }
  end
end

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

50
johnmcaliley

私はおそらくパーティーに少し遅れていますが、しばらく前に私は同じ状況にいることに気付き、これを簡単に行うための宝石を書きました: nscoped_associations

使用法:

belongs_to :user, unscoped: true

へのサポート:

  • 属する
  • has_one
  • 多くを持っています

多態的な関連付けもサポートされています。

24
markets

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

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

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

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

他の答えも見る価値がありますが、これはRails 4.1+。

6
Chris Peters

Rails 4では、望ましくないフィルターの明示的なスコープ解除との関連付けを使用できます。つまり、my_photo.product.unscope(where: :visible)

5
Kamran

メイントピックではなく、ActiveRecord#becomesの問題についてです。初期化子で(できれば)修正しました。

[。 @association_cache)
は
 end 
 alias_method_chain:becomes、:association_cache 
 
 end 
になりました

https://Gist.github.com/2478161

1
no-dashes

新しい答え

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

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

0
noodl