简体   繁体   English

如何使用或不使用Rails示波器?

[英]How do I create a rails scope with an or or a not?

I have a two scopes in my user model: 我的用户模型有两个作用域:

scope :hard_deactivated, where(:hard_deactivated => true)
scope :soft_deactivated, where(:soft_deactivated => true)

So far so good 到现在为止还挺好

OR 要么

I want to create a scope :deactivated, which will include all users where hard_deactivated is true OR soft deactivated is true. 我想创建一个范围:deactivated,它将包括hard_deactivated为true或soft deactivated为true的所有用户。 Obviously I could just do this: 显然,我可以这样做:

scope :deactivated, where("hard_deactivated = ? or soft_deactivated = ?", true, true)

but this does not feel very dry. 但这感觉并不干燥。

NOT

Also I would like to create an inverse scope :not_hard_deactivated. 我也想创建一个反作用域:not_hard_deactivated。 I could do this: 我可以这样做:

scope :not_hard_deactivated, where(:hard_deactivated => false)

but again, this feels bad, especially if my scope becomes more complex. 但是同样,这感觉很糟糕,尤其是当我的范围变得更加复杂时。 There should be some way or warpping the SQL generated by the previous scope in a not clause. 应该在not子句中采用某种方式或扭曲由先前范围生成的SQL。

Use an arel table: 使用区域表:

hard_deactivated_true = arel_table[:hard_deactivated].eq(true)
soft_deactivated_true = arel_table[:soft_deactivated].eq(true)

scope :deactivated, where(hard_deactivated_true.and(soft_deactivated_true))
scope :not_hard_deactivated, where(hard_deactivated_true.not)

See: Is it possible to invert a named scope in Rails3? 请参阅: 是否可以在Rails3中反转命名作用域?

For the "NOT" part, you can do something like this: 对于“ NOT”部分,您可以执行以下操作:

extend ScopeUtils

positive_and_negative_scopes :deactivated do |value|
  where(:hard_deactivated => value)
end

And implement this method in a separate module: 并在单独的模块中实现此方法:

module ScopeUtils
  def positive_and_negative_scopes(name)
    [true, false].each do |filter_value|
      prefix = ("not_" if filter_value == false)
      scope :"#{prefix}#{name}", yield(filter_value)
    end
  end
end

Regarding the "OR" case, you might be something similar, depending on what your recurring pattern is. 关于“或”的情况,根据重复模式的不同,可能会有些相似。 In the simple example above it's not worth it, as doesn't help readability. 在上面的简单示例中,这样做不值得,因为这样做不利于可读性。

scopes_with_adjectives_and_negatives :deactivated, [:soft, :hard]

module ScopeUtils
  def scopes_with_adjectives_and_negatives(name, kinds)
    kinds.each do |kind|
      positive_and_negative_scopes name do |filter_value|
        where("#{kind}_#{name}" => filter_value)
      end
    end
    scope :"#{name}", where(kinds.map{|kind| "#{kind}_#{name} = ?"}.join(" OR "), true, true)
    scope :"not_#{name}", where(kinds.map{|kind| "#{kind}_#{name} = ?"}.join(" AND "), false, false)
  end
end

您应该在where方法中使用sql片段(如您的第二个示例中),或在squeel等更多的“糖”类宝石中使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM