1

我有一个包含多个竞赛和对象的设置。它们通过has_many :through 与contest_objs 的安排联系在一起。match_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 吗?

4

3 回答 3

3

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

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

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

于 2012-08-28T22:19:40.767 回答
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

于 2015-01-09T19:28:06.480 回答
-1

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

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

Rails 将为您转义这些值。

编辑:

正如 Intrepidd 在评论中所说的那样,这不起作用,请使用他在回答中建议的字符串插值。这对于整数参数是安全的。

如果您发现自己在查询中插入了多个字符串,您可以考虑使用 find_by_sql,它会为您提供上述 ? 替换,但您不能将它与链接一起使用,因此需要重写整个查询。

于 2012-08-28T22:22:36.567 回答