ruby on rails-如何在Rails3中使用无范围关联关系?

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

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

在其他情况下,我可以使用unscoped来绕过default_scope,例如 在my_photo.unscoped.product中。但是:

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

my_photo.unscoped.product没有意义,因为my_photo没有名为unscoped的方法。my_photo.product.unscoped也没有意义,因为my_photo.product可能已经为零。

crispy asked 2019-10-07T23:28:22Z
7个解决方案
61 votes

哦。 我自欺欺人。 以为以下内容不起作用...但它可以:

Product.unscoped do
  my_photo.product
end

请注意,您必须使用应忽略的Product调用模型的非作用域。

同样,继承必须得到尊重。 如果在Product中有Productclass FinancialProduct < Productdefault_scope,则以下两种组合均可使用:

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的另一个怪癖。

crispy answered 2019-10-07T23:29:02Z
49 votes

另一个选择是重写getter方法并取消作用域超级:

class Photo < ActiveRecord::Base
  belongs_to :product

  def product
    Product.unscoped{ super }
  end
end

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

johnmcaliley answered 2019-10-07T23:29:34Z
24 votes

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

用法:

belongs_to :user, unscoped: true

支持:

  • 属于
  • has_one
  • 有很多

还支持多态关联。

markets answered 2019-10-07T23:30:34Z
7 votes

如果需要始终不限制特定关联,则可以在定义关联时取消限制:

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

由于某些原因,特定的where密钥无法为我正确加载,因此我只是取消了整个2559420494172914914的范围,这是在我的情况下可以解决的另一种选择:

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

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

Chris Peters answered 2019-10-07T23:31:13Z
5 votes

在Rails 4中,您可以将关联与不合要求的过滤器的显式取消作用域一起使用,即my_photo.product.unscope(where: :visible)

Kamran answered 2019-10-07T23:31:40Z
1 votes

它不是主要主题,而是有关ActiveRecord#的问题:我们(希望)使用初始化程序对其进行了修复

 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]

no-dashes answered 2019-10-07T23:32:13Z
0 votes

新答案

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

值得重复一遍,但是如果您经常必须避免使用范围,那么它可能应该是默认设置。 创建visible非默认作用域,并在您的关联中显式使用它。

noodl answered 2019-10-07T23:32:52Z
translate from https://stackoverflow.com:/questions/4758145/how-to-use-unscoped-on-associated-relations-in-rails3