kat*_*ray 16 ruby sql activerecord ruby-on-rails ruby-on-rails-3
我正在使用"where"语法编写Rails 3 ActiveRecord查询,该语法使用SQL IN和SQL OR运算符,并且无法弄清楚如何将它们一起使用.
此代码有效(在我的用户模型中):
Question.where(:user_id => self.friends.ids)
#note: self.friends.ids returns an array of integers
Run Code Online (Sandbox Code Playgroud)
但这段代码
Question.where(:user_id => self.friends.ids OR :target => self.friends.usernames)
Run Code Online (Sandbox Code Playgroud)
返回此错误
syntax error, unexpected tCONSTANT, expecting ')'
...user_id => self.friends.ids OR :target => self.friends.usern...
Run Code Online (Sandbox Code Playgroud)
知道如何在Rails中编写它,或者只是原始SQL查询应该是什么?
Fáb*_*sta 46
您不需要使用原始SQL,只需将模式作为字符串提供,并添加命名参数:
Question.where('user_id in (:ids) or target in (:usernames)',
:ids => self.friends.ids, :usernames => self.friends.usernames)
Run Code Online (Sandbox Code Playgroud)
或位置参数:
Question.where('user_id in (?) or target in (?)',
self.friends.ids, self.friends.usernames)
Run Code Online (Sandbox Code Playgroud)
您也可以使用优秀的Squeel gem,正如@erroric在他的回答中指出的那样(my { }
只有在需要访问self
或实例变量时才需要块):
Question.where { user_id.in(my { self.friends.ids }) |
target.in(my { self.friends.usernames }) }
Run Code Online (Sandbox Code Playgroud)
虽然Rails 3 AR没有给你一个或运算符,你仍然可以实现相同的结果,而不必一直到SQL并直接使用Arel.我的意思是你可以这样做:
t = Question.arel_table
Question.where(t[:user_id].in(self.friends.ids).or(t[:username].in(self.friends.usernames)))
Run Code Online (Sandbox Code Playgroud)
有人可能会说它不是那么漂亮,有些人可能会说这很简单,因为它不包含SQL.无论如何,它肯定会更漂亮,也有它的宝石:MetaWhere
有关详细信息,请参阅此railscast:http: //railscasts.com/episodes/215-advanced-queries-in-rails-3和MetaWhere站点:http://metautonomo.us/projects/metawhere/
更新:后来Ryan Bates又制作了关于metawhere和元搜索的轨道广播:http: //railscasts.com/episodes/251-metawhere-metasearch后来虽然Metawhere(和搜索)已成为或多或少的遗产宝石.即他们甚至不使用Rails 3.1.作者觉得他们(Metawhere和搜索)需要大幅改写.他真的一起去了一块新宝石.Metawhere的继任者是Squeel.在此处阅读有关作者公告的更多信息:http: //erniemiller.org/2011/08/31/rails-3-1-and-the-future-of-metawhere-and-metasearch/ 并查看项目主页: http://erniemiller.org/projects/squeel/"Metasearch 2.0"被称为Ransack,您可以从这里阅读有关它的内容:http: //erniemiller.org/2011/04/01/ransack-the-library-formerly -known-AS-元搜索-2-0 /
或者,您可以使用Squeel.在我看来,它更简单.您可以使用以下语法完成IN(>>
)和OR(|
)操作:
Question.where{(:user_id >> my{friends.id}) | (:target >> my{friends.usernames})}
Run Code Online (Sandbox Code Playgroud)
我通常将我的条件(...)
包括在内以确保适当的操作顺序 - IN都发生在OR之前.
该my{...}
块self
在Squeel调用之前定义的上下文中执行方法- 在本例中Question
.在Squeel块内部,self
指的是Squeel对象而不是Question
对象(有关更多信息,请参阅Squeel自述文件).您可以通过使用my{...}
包装器来恢复原始上下文.
jon*_*tar -7
原始SQL
SELECT *
FROM table
WHERE user_id in (LIST OF friend.ids) OR target in (LIST OF friends.usernames)
Run Code Online (Sandbox Code Playgroud)
每个列表以逗号分隔。我不太了解 Rails ActiveRecord 的东西。对于 AND,您只需在这两个条件之间放置一个逗号,但不知道 OR
归档时间: |
|
查看次数: |
23106 次 |
最近记录: |