使用ActiveRecord转义查询对象中的参数?

Jar*_*eck 20 ruby activerecord

给定查询对象(不是AR模型)

class ComplexQuery
  QUERY = <<-SQL
    ...
  SQL

  def new(param1, param2)
    ...
  end

  def execute
    # format and interpolate parameters into QUERY
    # pass finished SQL to `execute` or `select_all`
  end
end
Run Code Online (Sandbox Code Playgroud)

我怎样才能方便地逃避所有参数?

我已经成功完成了三种技术,但没有一种方便.

  1. 使用raw_connectionwhich(对我来说)返回一个实例PG::Conn并调用exec_params.我对此不满意,因为exec_params需要一组冗长的参数来指定数据类型.
  2. include ActiveRecord::Sanitization在我的查询对象中,并使用其中一个方便的方法,如replace_named_bind_variables.我并不满足于此,因为replace_named_bind_variablesprotected我必须使用send.
  3. 写一个module代替.出于某种原因,当我include ActiveRecord::Sanitization进入模块时,我能够使用其受保护的方法.我对此不满意,因为我想有时不执行它来实例化我的查询对象,例如用于测试.

包括ActiveRecord::Sanitizationclass像的最佳解决方案感觉,但我必须做一些错误的,因为我应该能够使用protected方法.

我正在寻找一个解决方案:

  1. 转义多个参数
  2. 旨在供ActiveRecord的消费者使用
  3. 推断参数的数据类型并相应地对其进行格式化

我能够找到一些相关的问题

Jus*_*ard 6

最好的方法可能是使用原始Postgres驱动程序创建一个准备好的语句.不幸的是,ActiveRecord没有公开这样做的方法.他们可能很快就会添加它,因为mysql2支持预处理语句.但与此同时,这里是如何使用PGrails中的原始驱动程序.

http://deveiate.org/code/pg/PG/Connection.html#method-i-prepare

conn = ActiveRecord::Base.connection.raw_connection
conn.prepare('my_query', 'SELECT foo FROM bar WHERE baz=$1 OR baz=$2')
result = conn.exec_prepared('my_query', ['param1', 'param2'])
Run Code Online (Sandbox Code Playgroud)

注意使用$符号来表示位置参数.数字对应于您传递给的数组中参数的位置exec_prepared.