Ruby-on-rails 如何在 Rails3 中对关联关系使用 unscoped?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4758145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:09:42  来源:igfitidea点击:

How to use unscoped on associated relations in Rails3?

ruby-on-railsruby-on-rails-3scopearel

提问by crispy

I have a default scope on products due to information security constraints.

由于信息安全限制,我对产品有一个默认范围。

class Product < ActiveRecord::Base
  has_many :photos

  default_scope where('visible = 1')
end

In my associated Photo model, however, I also have to find products that should not be visible.

然而,在我关联的照片模型中,我还必须找到不应该可见的产品。

class Photo < ActiveRecord::Base
  belongs_to :product
end

my_photo.product

In other cases, I can use unscopedin order to bypass the default_scope, e.g. in Product.unscoped.find_by_title('abc'). However:

在其他情况下,我可以使用unscoped来绕过 default_scope,例如在Product.unscoped.find_by_title('abc'). 然而:

How to remove the scope when using associations of a record?

使用记录关联时如何删除范围?

my_photo.unscoped.productdoes not make sense as my_photo does not have a method called unscoped. Neither does my_photo.product.unscopedmake sense as my_photo.productmay already be nil.

my_photo.unscoped.product没有意义,因为 my_photo 没有名为unscoped. 两者都没my_photo.product.unscoped有意义,因为my_photo.product可能已经为零。

回答by crispy

Oh. I fooled myself. Thought the following would not work... but it does:

哦。我骗了自己。认为以下不起作用......但它确实:

Product.unscoped do
  my_photo.product
end

Notice that you have to call unscoped on the model with the default_scopethat should be bypassed.

请注意,您必须在模型上调用 unscoped 并default_scope绕过它。

Also, inheritance has to be respected. If you have class InsuranceProduct < Productand class FinancialProduct < Productand a default_scopein Product, all of the following two combinations will work:

此外,必须尊重继承。如果您有class InsuranceProduct < Productandclass FinancialProduct < Product和 a default_scopein Product,则以下所有两种组合都将起作用:

InsuranceProduct.unscoped do
  my_record.insurance_products
end

FinancialProduct.unscoped do
  my_record.financial_products
end

Product.unscoped do
  my_record.products
end

However, the following will not workalthough the scope is defined in Product:

但是,尽管范围在 中定义,但以下内容将不起作用Product

Product.unscoped do
  my_record.financial_products
end

I guess that's another quirk of STI in Ruby / Rails.

我想这是 Ruby/Rails 中 STI 的另一个怪癖。

回答by johnmcaliley

Another option is to override the getter method and unscope super:

另一种选择是覆盖 getter 方法并取消作用域 super:

class Photo < ActiveRecord::Base
  belongs_to :product

  def product
    Product.unscoped{ super }
  end
end

I ran into the same situation where I had one associated model that needed to be unscoped, but in almost every other case it needed the default scope. This should save you the extra calls to unscoped if you are using the assocation getter in more than one place.

我遇到了同样的情况,我有一个需要取消作用域的关联模型,但在几乎所有其他情况下,它都需要默认作用域。如果您在多个地方使用关联 getter,这应该可以为您节省对 unscoped 的额外调用。

回答by markets

I'm probably a bit late to the party, but some time ago I found myself in the same situation and I wrote a gem to do this easily: unscoped_associations.

我参加聚会可能有点晚了,但前一段时间我发现自己处于同样的情况,我写了一个 gem 来轻松做到这一点:unscoped_associations

Usage:

用法:

belongs_to :user, unscoped: true

Support for:

支持:

  • belongs_to
  • has_one
  • has_many
  • 属于
  • has_one
  • 有很多

Polymorphic associations are also supported.

还支持多态关联。

回答by Chris Peters

If you need for a specific association to always be unscoped, you can unscope it when defining the association:

如果你需要一个特定的关联总是无范围的,你可以在定义关联时取消它的范围:

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

For some reason, the specific wherekey wasn't loading correctly for me, so I just unscoped the entire where, which is another option that happens to work out in my case:

出于某种原因,特定where键没有为我正确加载,所以我只是取消了整个 的范围where,这是在我的情况下碰巧适用的另一个选项:

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

The other answers are worth looking at too, but this is another option for Rails 4.1+.

其他答案也值得一看,但这是 Rails 4.1+ 的另一种选择。

回答by Kamran

In Rails 4 you can use the association with an explicit unscope of the undesirable filter i.e. my_photo.product.unscope(where: :visible)

在 Rails 4 中,您可以将关联与不需要的过滤器的显式非作用域关联,即 my_photo.product.unscope(where: :visible)

回答by no-dashes

It's not on the main topic but on your problem with ActiveRecord#becomes: We (hopefully) fixed it with an initializer

它不是关于主要主题,而是关于您的 ActiveRecord#becomes 问题:我们(希望)用初始化程序修复了它

 class ActiveRecord::Base

   def becomes_with_association_cache(klass)
     became = becomes_without_association_cache(klass)
     became.instance_variable_set("@association_cache", @association_cache)
     became
   end
   alias_method_chain :becomes, :association_cache

 end

https://gist.github.com/2478161

https://gist.github.com/2478161

回答by noodl

New answer

新答案

This questionshould help you figure out how to bypass the default where clause for your association.

这个问题应该可以帮助您弄清楚如何绕过关联的默认 where 子句。

It's worth repeating though that if you're regularly having to avoid a scope then it probably should be a default. Create a visiblenon-default scope and use that explicitly in your associations.

值得重申的是,如果您经常不得不避免使用范围,那么它可能应该是默认设置。创建一个visible非默认范围并在您的关联中明确使用它。