2012-10-11 38 views
3

我在名为propertiesusers表中有hstore列。将postgres hstore sql转换为Arel

如何将where条件中的静态sql字符串转换为aRel语法?

User.where("properties -> 'is_robber' = 'true'") #=> ...some users 

我曾尝试:

ut = User.arel_table 
condition = ut["properties -> 'is_robber'"].eq('true') 
User.where(condition) #=> throws pg error 

和产生错误的SQL:

SELECT "users".* FROM "users" WHERE "users"."properties -> 'is_robber'" = 'true' 

比起我所需要的:

SELECT "users".* FROM "users" WHERE "users".properties -> 'is_robber' = 'true' 

回答

12

您可以通过创建自己的阿雷尔::节点:: InfixOperation与阿雷尔做到这一点:

ut = Arel::Table.new(:user) 
hstore_key = Arel::Nodes::InfixOperation.new("->", ut[:properties], 'is_robber') 
User.where(hstore_key.eq('true')) 

会产生:

SELECT "users".* FROM "users" WHERE "users"."properties" -> 'is_robber' = 'true' 

如果你从来没有听说过缀记号所,Wikipedia gives a good explaination

中缀记法是常用的算术和逻辑公式表示法,其中操作符被写入在它们所操作的操作数之间是中缀风格(例如, 2 + 2)。计算机解析前缀符号(例如+ 2 2)或后缀符号(例如2 2 +)并不那么简单,但许多编程语言由于其熟悉性而使用它。

不幸的是,没有太多的Arel文档,没有InfixOperation节点的文档,所以它可能会令人沮丧的开始。当你正在寻找如何使用Arel执行特定的SQL操作时,最好的方法是查看the nodes directory in the source code

+0

这不适用于arel 6.0.3,正确的方法是: hstore_key = Arel :: Nodes :: InfixOperation.new(“ - >”,ut [:properties],Arel ::节点:: SqlLiteral.new( “ 'is_robber'”)) – fabi

-1

如果使用activerecord-postgres-hstore宝石,你就可以于:

class User < ActiveRecord::Base 
    serialize :data, ActiveRecord::Coders::Hstore 
end 

User.where("data -> 'speed' = 'ludicrous'") 

更多信息:
* https://github.com/softa/activerecord-postgres-hstore
* http://railscasts.com/episodes/345-hstore

的RailsCast临情节对创建范围,干将,和setter自动的极好示例代码。

+0

谢谢你的时间。我读过/看过这些。我正在使用那颗宝石。但是我的问题仍然存在:我如何将'User.where(“data - >'speed'='ludicrous'”)这样的东西转换成一个简单的语法? – shuriu

+0

@shuriu是你使用的语法;它可以与其他arel查询和作用域相结合。 –

+1

为什么这个''data - >'speed'='ludicrous'''困扰我,是因为它只是一个静态字符串。我想要做的是动态构造'where':查询另一个数据属性,或更改运算符或值。使用aRel很容易,因为您可以链接方法,并且正确且神奇地构建您的sql。无论如何,我想我会稍后编辑这个问题,以更清楚我想要达到的目标。 – shuriu