Rails在where中查询引用属性

时间:2014-06-16 09:45:59

标签: mysql sql ruby-on-rails sqlite

示例模型用户:

create_table "users" t.string "name" t.boolean "admin" t.boolean "internal" end

需要在SQL查询的where子句中使用“admin”或“internal”查询

。在编写查询时,不知道将使用哪个布尔值,因此变量(例如usertype)用于存储字符串“admin”或“internal”。它基本上意味着我想在where子句中使用引用属性。

执行以下查询:

User.select("id").where("#{usertype} = 't'")

在我的开发sqlite数据库中工作正常(因为sqlite将true存储为't',false存储为'f'),但我想在另一个数据库(例如Mysql或Postrgres)上使用相同的查询可能不起作用。

或者我试过

User.select("id").where("#{usertype} = ?", true)

它也有效,不使用特定于sqlite的't'。但是,这是一个很好的,独立于数据库的解决方案吗?

1 个答案:

答案 0 :(得分:1)

您应该始终使用truefalse(或将评估'truthy'或'falsy`的变量或代码)并让rails处理转换,但DBMS会存储布尔值。

您可以在第二个示例中执行此操作

User.select("id").where("#{usertype} = ?", true)

所以,答案是“是的,这是一个很好的,独立于数据库的解决方案”。但是,你可以让它更整洁:如果所有条件都是“=”变种,那么你可以使用哈希,比如

{:foo => "bar"}
{"foo" => "bar"} 

都等同于

["foo = ?", "bar"]

这意味着在您的情况下,您可以省去字符串评估,只需将变量传入。

User.select("id").where({usertype => true})

或者,如果您想跳过可选的{& }

User.select("id").where(usertype => true)

编辑:回复关于在ruby代码中使用动态定义的方法的评论,以从对象中获取值。

您可以使用send方法调用对象上的相应访问者。例如,

@foo.bar == 123

相当于

@foo.send("bar") == 123

所以,在你的例子中你会说

a.send(usertype)

作为旁注,如果你想设置 usertype的值(我认为你的情况下没有意义,只是一个例子),你需要调用方法的“setter”版本,可以是admin=internal=。因此,在这种情况下,您 需要使用字符串评估:

@user.send("#{usertype}=", "foo")

就像说

@user.admin = "foo"

@user.internal = "foo"