Ruby on Rails:不使用 find 时如何为 SQL 清理字符串?

Posted

技术标签:

【中文标题】Ruby on Rails:不使用 find 时如何为 SQL 清理字符串?【英文标题】:Ruby on Rails: How to sanitize a string for SQL when not using find? 【发布时间】:2011-01-30 15:56:09 【问题描述】:

我正在尝试清理一个涉及用户输入的字符串,而不必在可能的情况下手动制作我自己的可能有问题的正则表达式,但是,如果这是唯一的方法,如果有人能指出我的正确之处,我也将不胜感激指向不太可能遗漏任何内容的正则表达式。 Rails 中有许多方法可以让你输入本地 SQL 命令,人们如何逃避用户输入?

我要问的问题是一个广泛的问题,但在我的特殊情况下,我正在使用我的 Postgres 数据库中的一个列,据我所知,Rails 本身并不理解该列,即 tsvector,它包含纯文本搜索信息。 Rails 能够像字符串一样对其进行读写,但是,与字符串不同的是,当我在模型中执行 vector= 之类的操作时,它似乎不会自动转义它。

例如,当我执行 model.name='::',其中 name 是一个字符串时,它可以正常工作。当我执行 model.vector='::' 时,它会出错:

ActiveRecord::StatementInvalid: PGError: ERROR:  syntax error in tsvector: "::"
"vectors" = E'::' WHERE "id" = 1

这似乎是分号缺少转义导致的问题,我可以手动设置vector='::'就好了。

我也有个好主意,也许我可以这样称呼:

ActiveRecord::Base.connection.execute "UPDATE medias SET vectors = ? WHERE id = 1", "::"

但是,这种语法不起作用,因为原始 SQL 命令无法访问 find 使用 ? 转义和输入字符串的方法。标记。

这让我觉得与使用任何类型的用户输入调用 connection.execute 相同,因为这一切都归结为清理字符串,但我似乎找不到任何方法来手动调用 Rails 的 SQL 字符串清理方法。谁能给点建议?

【问题讨论】:

【参考方案1】:

将此方法添加到您的模型中:

class Media < ActiveRecord::Base
  def self.execute_sql(*sql_array)     
    connection.execute(send(:sanitize_sql_array, sql_array))
  end
end

现在您可以执行任何 SQL,例如:

Media.execute_sql('UPDATE medias SET vectors = ? WHERE id = 1', '::')

参考

1) sanitize_sql_array

【讨论】:

感谢您的提示,正如您所说的那样工作。然而,不幸的是,Rails 似乎实际上并没有清理 SQL 的冒号 (:),而且我仍然在该行遇到错误。也许要求对冒号进行消毒是 tsvector 独有的。看来我将不得不走老旧的正则表达式路线。

以上是关于Ruby on Rails:不使用 find 时如何为 SQL 清理字符串?的主要内容,如果未能解决你的问题,请参考以下文章

使用 find_by 加载 Ruby on Rails

在 ruby​​ on rails 中使用连接表

Ruby on Rails:高级搜索,nil:Nilclass 的未定义方法 []

如何使用链接/按钮更改列属性 - Ruby on Rails

Ruby on Rails——堆栈级别太深

Ruby on Rails:无法加载rack / handler /