将变量插入复杂的sql命令

时间:2012-08-28 22:07:18

标签: ruby-on-rails ruby-on-rails-3

我有一个包含多个竞赛和对象的设置。他们与has_many联系在一起:通过与contest_objs的安排。 contest_objs也有投票权,所以我可以参加几个比赛,包括几个对象。我有一个复杂的SQL设置来计算当前的排名。但是,我需要在SQL select语句中为排名指定竞赛。我这样做有困难。这是我到目前为止所得到的:

@objects = @contest.objects.select('"contest_objs"."votes" AS v, name, "objects"."id" AS id, 
                                   (SELECT COUNT(DISTINCT "oi"."object_id")
                                           FROM  contest_objs oi
                                           WHERE ("oi"."votes") > ("contest_objs"."votes"))+1 AS vrank')

选择vrank是否有任何方法可以指定WHERE还包含“oi”。“contest_id”= @ contest.id?

3 个答案:

答案 0 :(得分:3)

由于@ contest.id是一个整数,并且不存在SQL注入的任何风险,您可以使用字符串插值执行以下操作:

Model.select("..... WHERE id = #{@contest.id}")

另一种可能的解决方案是使用ActiveRecord构建子查询,然后调用.to_sql以获取生成的SQL,并将其插入主查询中。

答案 1 :(得分:2)

使用sanitize_sql_array:

sanitize_sql_array('select ? from foo', 'bar')

如果您在模型之外,因为该方法受到保护,您必须这样做:

ActiveRecord::Base.send(:sanitize_sql_array, ['select ? from foo', 'bar'])

http://apidock.com/rails/ActiveRecord/Sanitization/ClassMethods/sanitize_sql_array

答案 2 :(得分:-1)

您可以将变量插入sql命令,如下所示:

Model.select("...... WHERE id = ?", @contest.id)

Rails会为你逃避价值。

修改

这不符合Intrepidd在评论中的说法,使用字符串插值,就像他在答案中所建议的那样。这对于整数参数是安全的。

如果你发现自己在查询中插入了几个字符串,你可以考虑使用find_by_sql,它给你上面提到的?替换,但你不能使用链接,所以需要重写整个查询。