【问题标题】:Ruby Activerecord: find same value in multiple fieldsRuby Activerecord:在多个字段中找到相同的值
【发布时间】:2018-05-15 14:49:59
【问题描述】:

我在 SQL 中使用以下查询在我的模型的多个字段中查找相同的值,但希望以更正确的 Activerecord 方式进行。

MyModel.where("'some_value' in (a_field, another_field)").first.try(:id)

以下不起作用,因为它是 AND,我需要 OR

MyModel.where(a_field: 'some_value', another_field: 'some_value').first.try(:id)

有什么建议吗? 出于好奇:如果我使用第一个(有效)并使用putsp 查看结果,我会看到两次结果吗?我想知道为什么..

在这个例子中编辑我只使用了两个字段,但实际上可能有更多这样一个或不可行且不干

【问题讨论】:

标签: ruby-on-rails ruby activerecord


【解决方案1】:

有一个or 方法可用...

MyModel.where(a_field: 'some_value').or(MyModel.where(another_field: 'some_value')).first.try(:id)

你可以做多个字段

test_value = 'some_value'

my_models = MyModel.where(id: nil)

%i(a_field another_field third_field fourth_field fifth_field).each do |field|
  my_models = my_models.or(MyModel.where(field => test_value))
end

【讨论】:

  • thx Steve,在我的示例中可以使用,但实际上有多个字段并且它不是 DRY ,如果没有更好的建议,我会接受并且必须使用 SQL 解决方案iaa
  • 我已编辑建议您可以为多个字段执行此操作的方法。我无法测试此链接,但它应该可以工作吗?
  • 不过,有时 SQL 是最好的选择。 :)
【解决方案2】:

Ransack 是用于构建复杂查询的 gem。

它同时支持orand 运算符。

对于具有相同值的多个列进行搜索,您可以通过以下方式构建 ransack 查询。

MyModel.ransack(field1_or_field2_or_field3_eq: 'some_value')

Ransack 提供各种选项来获得您的结果,例如(equal_to 条件、like_condition 等...)。

如果您不想使用任何外部 gem,那么我认为 @steve 的回答很恰当。

【讨论】:

    【解决方案3】:

    多种方法:

    导轨:

    Post.where('id = 1').or(Post.where('id = 2'))
    

    参考:https://github.com/rails/rails/commit/9e42cf019f2417473e7dcbfcb885709fa2709f89

    使用 rais_or Gem: https://github.com/khiav223577/rails_or

    EX: user = User.where(account: account).or(email: account).take
    

    使用 ARel # Arel 最适合复杂查询

    t = Post.arel_table
    results = Post.where(
      t[:author].eq("Someone").
      or(t[:title].matches("%something%"))
    )
    

    【讨论】:

      【解决方案4】:

      我忘记了这个问题,这是我现在的做法

      def search_in_all_fields model, text
        model.where(
          model.column_names
            .map {|field| "#{field} like '%#{text}%'" }
            .join(" or ")
        )
      end
      

      或者更好地作为模型本身的作用域

      class Model < ActiveRecord::Base
        scope :search_in_all_fields, ->(text){
          where(
            column_names
              .map {|field| "#{field} like '%#{text}%'" }
              .join(" or ")
          )
        }
      end
      

      你只需要这样称呼它

      Model.search_in_all_fields "test"
      

      在你开始之前..,确保这里没有sql注入还是更好更短

      class Model < ActiveRecord::Base
        scope :search_all_fields, ->(text){
          where("#{column_names.join(' || ')} like ?", "%#{text}%")
        }
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-03
        • 1970-01-01
        • 2021-08-14
        • 2023-03-15
        • 2021-11-23
        • 1970-01-01
        • 2012-04-05
        相关资源
        最近更新 更多