【问题标题】:Apply where condition if it exists in rails如果它存在于rails中,则应用where条件
【发布时间】:2020-05-09 16:50:39
【问题描述】:

rails activerecord 中有没有一种方法可以根据条件应用 where 条件?

例如: 假设如果输入参数中存在过滤器,我想应用过滤器。 假设@name 是必填字段,@salary 是可选字段。

@name = "test_name"
@salary = 2000

我想做如下的事情:

Employee.where(name: @name)
        .where(salary: @salary) if @salary.present?

我知道要在多个数据库调用中实现它,但我正在寻找一个选项以在单个数据库调用中实现这一点。

【问题讨论】:

  • 洗劫宝石怎么样?它是一种搜索机制。

标签: ruby-on-rails ruby activerecord ruby-on-rails-5 rails-activerecord


【解决方案1】:

您可以将第一个where 的结果分配给一个变量并有条件地调用第二个where

@employees = Employee.where(name: @name)
@employees = @employees.where(salary: @salary) if @salary.present?

【讨论】:

  • 这不会进行多次数据库调用吗?
  • @vishwastej 我曾经和你有同样的担忧:)。你应该看看这个railscasts.com/episodes/239-activerecord-relation-walkthrough
  • 看起来就像在控制台中一样,因为控制台试图给你即时反馈,从而立即运行;但是 Rails 在需要查询结果之前不会执行查询。在控制台中,您可以运行 @employees = Employee.where(name: @name); nil 并看到它实际上并没有在那里运行查询
  • 我试过这个。但在控制台中,我可以看到 @employees = Employee.where(name: @name) 的输出,而不是 nil。
  • @Stefan 当我在 irb 控制台中运行代码,并且不希望控制台在行间执行查询时(因为结果使用inspect 显示)或者当代码是 . 前缀以进一步链接上一行。您可以简单地打开一个块(使用begin),复制代码并end 块。所以我所说的“一次执行所有内容”的意思基本上是,不要逐行执行。
【解决方案2】:

您只能通过存在的参数进行查询:

args = { name: @name, salary: @salary.presence }
Employee.where(args.compact)

【讨论】:

  • 或者args = { name: @name, salary: @salary.presence }.compact
【解决方案3】:

您可以将所有可能的参数添加到一个哈希中,然后使用 Hash#compact 删除 nil 的参数:

Employee.where({ name: @name, salary: @salary }.compact)

【讨论】:

  • 请注意,一旦@salary 为空字符串,此操作就会失败。 compact 只删除 nil 值而不是空字符串。 OP 在问题中使用present?,它还会检查空字符串。否则是一个很好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2014-07-20
  • 2014-03-08
  • 1970-01-01
  • 2023-03-20
  • 2013-07-05
  • 2022-12-05
  • 1970-01-01
  • 2018-11-29
相关资源
最近更新 更多