gpt4 book ai didi

ruby-on-rails - 用 OR 组合两个命名范围(而不是 AND)

转载 作者:行者123 更新时间:2023-12-04 10:45:57 25 4
gpt4 key购买 nike

我想找到所有 Annotations他们的 body 是:

  • 等于 ”?”
  • 像“[?]”

  • 做到这一点的最佳方法是什么?

    我想用 SearchLogic如果可能,但 SearchLogic 允许您执行以下每项操作:
  • Annotation.body_equals('?')
  • Annotation.body_like('[?]')

  • 您可以随时将它们链接在一起: Annotation.body_equals('?').body_like('[?]')
    我不确定如何将它们与 OR 结合起来.

    Note that you can combine named scopes with OR if their argument is the same.例如,我可以这样做:
     Annotation.body_equals_or_body_like('?')

    但这无济于事。

    请注意,我不依赖于 SearchLogic,但对于不需要打破其抽象的解决方案来说,它会很棒。

    最佳答案

    我找不到任何简单的解决方案,但是这个问题引起了我的兴趣,所以我推出了自己的解决方案:

    class ActiveRecord::Base

    def self.or_scopes(*scopes)
    # Cleanup input
    scopes.map! do |scope|
    scope = scope.respond_to?(:to_a) ? scope.to_a : [*scope]
    scope.unshift(scope.shift.to_sym)
    end

    # Check for existence of scopes
    scopes.each{|scope| raise ArgumentError, "invalid scope: #{scope.first}" unless self.scopes.has_key?(scope.first) }

    conditions = scopes.map do |scope|
    scope = self.scopes[scope.first].call(self, *scope[1..-1])
    self.merge_conditions(scope.proxy_options[:conditions])
    end

    or_conditions = conditions.compact.join(" OR ")

    merged_scopes = scopes.inject(self){|merged, scope| merged.scopes[scope.first].call(self, *scope[1..-1]) }

    # We ignore other scope types but so does named_scopes
    find_options = merged_scopes.scope(:find).merge(:conditions => or_conditions)

    self.scoped(find_options)
    end

    end

    考虑以下设置:
    class Person < ActiveRecord::Base
    named_scope :men, :conditions => { :sex => 'M' }
    named_scope :women, :conditions => { :sex => 'F' }
    named_scope :children, :conditions => "age < 18"
    named_scope :named, lambda{|name|
    { :conditions => { :name => name } }
    }
    end

    您可以使用一系列范围的名称来调用它:
    Person.or_scopes(:women, :children)

    这将返回一个这样的范围:
    Person.or_scopes(:women, :children).proxy_options
    # => {:conditions=>"(`people`.`sex` = 'F') OR (age < 18)"}

    当范围需要参数时,您还可以使用数组数组调用它:
    Person.or_scopes(:women, [:named, 'Sue']).proxy_options
    # => {:conditions=>"(`people`.`sex` = 'F') OR (`people`.`name` = 'Sue')"}

    在您的情况下,Horace,您可以使用以下内容:
    Annotation.or_scopes([:body_equals, '?'], [:body_like, '[?']).all

    关于ruby-on-rails - 用 OR 组合两个命名范围(而不是 AND),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1482940/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com