我有一个方法,它采用列名并在我的模型上定义范围。范围使用PostgreSQL窗口函数(如rank()和row_number()),在结果数据集中添加一个额外的列。例如,User.ranked_on_score
应添加别名为rank()
的{{1}}列。
目前,我通过简单的字符串插值(伪代码)来实现它:
score_ranking
考虑到,范围应事先定义为宏,不接受用户的输入,这种方法应该是安全的;尽管如此,我不喜欢它。
我知道window_alias = "#{attr}_rankings"
result_alias = "#{attr}_ranking"
select("users.*, #{window_alias}.#{result_alias}")
.join("JOIN (SELECT id, rank() OVER (ORDER BY #{attr} ASC) as #{result_alias} ...")
方法,但它在我的情况下不起作用。它将参数包装在单引号中,这在sanitize_sql
子句中很好,但如果在WHERE
子句中使用(PG要求标识符用双引号括起来),则会引发语法错误。
是否有任何内置的标识符清理方法?或者我应该这样离开呢?
答案 0 :(得分:3)
你试过quote_column_name
吗?由于某些原因,它没有文档,但应该做你需要的。
window_alias = quote_column_name("#{attr}_rankings")
result_alias = quote_column_name("#{attr}_ranking")
在幕后,它相当于在使用PostgreSQL时调用PGconn.quote_ident
。