如何在rails3中使用AR查询接口指定多个值

wkh*_*tch 27 activerecord ruby-on-rails-3

每节铁轨的2.2指导活动记录查询界面在这里:

这似乎表明我可以传递一个指定条件的字符串,然后是一个值数组,在构建arel时应该在某个点上替换它们.所以我有一个声明生成我的条件字符串,它可以是链接在一起的不同数量的属性与它们之间的AND或OR,我传入一个数组作为第二个arg到where方法,我得到:

ActiveRecord :: PreparedStatementInvalid:绑定变量数错误(1表示5)

这让我相信我做错了.但是,我没有找到任何关于如何正确做到的事情.要以另一种方式重述问题,我需要将一个字符串传递给where方法,例如"table.attribute =?AND table.attribute1 =?OR table.attribute1 =?" 将未知数量的这些条件一起加入或合并,然后传递一些东西,我认为是一个数组作为第二个参数,用于替换第一个参数条件字符串中的值.这是正确的做法,或者,我只是在某个地方错过了一些其他巨大的概念而且我对这一切都错了?我认为,不管怎么说,只要生成一个原始的sql字符串,就必须这样做.

nfr*_*d21 38

这实际上非常简单:

Model.where(attribute: [value1,value2])
Run Code Online (Sandbox Code Playgroud)

  • 是的,当您在构建查询时知道有多少可能的值或者反对时,这很有用,但我正在寻找如何针对未知数量的可能选项进行操作.我相信,我最终把阵列喷射了. (2认同)

Dan*_*ail 24

听起来你正在做这样的事情:

Model.where("attribute = ? OR attribute2 = ?", [value, value])
Run Code Online (Sandbox Code Playgroud)

而你需要这样做:

# notice the lack of an array as the last argument
Model.where("attribute = ? OR attribute2 = ?", value, value)
Run Code Online (Sandbox Code Playgroud)

请查看http://guides.rubyonrails.org/active_record_querying.html#array-conditions,了解有关其工作原理的更多详细信息.

  • 我没有尝试过,但你可以尝试在你的参数值数组上使用splat运算符:`Model.where("attributes =?",*array_of_values)` (15认同)
  • 不幸的是,最后一条评论中的语法不起作用. (3认同)

Ton*_*ado 23

而不是where()像这样多次传递相同的参数

User.where(
  "first_name like ? or last_name like ? or city like ?", 
  "%#{search}%", "%#{search}%", "%#{search}%"
)
Run Code Online (Sandbox Code Playgroud)

你可以轻松提供哈希

User.where(
  "first_name like :search or last_name like :search or city like :search",
  {search: "%#{search}%"}
)
Run Code Online (Sandbox Code Playgroud)

这使得您的查询对于长参数列表更具可读性.


小智 12

听起来你正在做这样的事情:

Model.where("attribute = ? OR attribute2 = ?", [value, value])
Run Code Online (Sandbox Code Playgroud)

而你需要这样做:

#notice the lack of an array as the last argument
Model.where("attribute = ? OR attribute2 = ?", value, value) Have a
Run Code Online (Sandbox Code Playgroud)

请查看 http://guides.rubyonrails.org/active_record_querying.html#array-conditions ,了解有关其工作原理的更多详细信息.

非常接近.您可以使用*my_list将数组转换为参数列表.

Model.where("id = ? OR id = ?", *["1", "2"])
Run Code Online (Sandbox Code Playgroud)

要么

params = ["1", "2"]
Model.where("id = ? OR id = ?", *params)
Run Code Online (Sandbox Code Playgroud)

应该管用


Chr*_*erg 5

如果您想将条件(属性名称和值)的开放式列表链接在一起,我建议使用 arel 表。

由于您的问题如此含糊,因此很难给出具体细节,因此我将仅解释如何针对Post模型和一些属性的简单情况执行此操作,例如title, summary, 和user_id(即用户has_many帖子)。

首先,获取模型的arel表:

table = Post.arel_table
Run Code Online (Sandbox Code Playgroud)

然后,开始构建您的谓词(您最终将使用它来创建 SQL 查询):

relation = table[:title].eq("Foo")
relation = relation.or(table[:summary].eq("A post about foo"))
relation = relation.and(table[:user_id].eq(5))
Run Code Online (Sandbox Code Playgroud)

这里table[:title]table[:summary]table[:user_id]在列表示posts表。当您调用 时table[:title].eq("Foo"),您正在创建一个谓词,大致相当于一个查找条件(获取标题列等于“Foo”的所有行)。这些谓词可以用and和链接在一起or

当您的聚合谓词准备就绪时,您可以通过以下方式获得结果:

Post.where(relation)
Run Code Online (Sandbox Code Playgroud)

这将生成 SQL:

SELECT "posts".* FROM "posts"
WHERE (("posts"."title" = "Foo" OR "posts"."summary" = "A post about foo")
AND "posts"."user_id" = 5)
Run Code Online (Sandbox Code Playgroud)

这将为您提供标题为“Foo”或摘要为“关于 foo 的帖子”的所有帖子,并且属于 ID 为 5 的用户。

请注意,arel 谓词可以无休止地链接在一起以创建越来越复杂的查询。这意味着,如果您有(比如说)属性/值对的散列,并且有某种方式知道是否使用ANDOR对它们中的每一个使用或,您可以逐一循环它们并建立您的条件:

relation = table[:title].eq("Foo")
hash.each do |attr, value|
  relation = relation.and(table[attr].eq(value))
  # or relation = relation.or(table[attr].eq(value)) for an OR predicate
end
Post.where(relation)
Run Code Online (Sandbox Code Playgroud)

除了易于链接条件之外,arel 表的另一个优点是它们独立于数据库,因此您不必担心您的 MySQL 查询是否可以在 PostgreSQL 等中工作。

这是关于 arel 的更多内容的 Railscast:http: //railscasts.com/episodes/215-advanced-queries-in-rails-3?view=asciicast

希望有帮助。