如何在Rails中清理sql片段

时间:2010-06-09 19:07:06

标签: sql ruby-on-rails sanitize

我必须清理sql查询的一部分。我可以这样做:

class << ActiveRecord::Base
  public :sanitize_sql
end

str = ActiveRecord::Base.sanitize_sql(["AND column1 = ?", "two's"], '')

但它不安全,因为我公开了受保护的方法。有什么更好的方法呢?

6 个答案:

答案 0 :(得分:42)

你可以使用:

ActiveRecord::Base::sanitize(string)

答案 1 :(得分:14)

ActiveRecord::Base.connection.quote在Rails 3.x

中完成了这个技巧

答案 2 :(得分:8)

这个问题没有说明答案必须来自ActiveRecord,也没有说明它应该是哪个版本的Rails。出于这个原因(并且因为它是最重要的和少数几个)关于如何在Rails中清理参数的答案......

这是一个适用于Rails 4的解决方案:

ActiveRecord::Sanitization::ClassMethods中您有 sanitize_sql_for_conditions 及其他两个别名 sanitize_conditions sanitize_sql 。这三者确实完全相同。

sanitize_sql_for_conditions

  

接受SQL条件的数组,散列或字符串并进行清理   它们是一个有效的SQL片段,用于WHERE子句

同样在ActiveRecord中你有

sanitize_sql_for_assignment

  

接受SQL条件的数组,散列或字符串并对其进行清理   到一个有效的SQL片段用于SET子句

  • 默认情况下,上述方法包含在ActiveRecord :: Base中,因此包含在任何ActiveRecord模型中

请参阅docs

但是,在ActionController中,您有ActionController::Parameters,允许您

  

选择哪些属性应列入白名单以进行批量更新   从而防止意外暴露不应暴露的东西。   为此提供了两种方法:需要允许

params = ActionController::Parameters.new(user: { name: 'Bryan', age: 21 })
req  = params.require(:user) # will throw exception if user not present
opt  = params.permit(:name)  # name parameter is optional, returns nil if not present
user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional

“参数魔术”称为强参数(docs here),您可以使用它来清理控制器中的参数,然后再将其发送到模型。

  • 上述方法默认包含在ActionController::Base中,因此包含在任何Rails控制器中

我希望能帮助任何人,如果只是为了学习和揭开Rails的神秘面纱! :)

答案 3 :(得分:4)

您可以通过间接调用来绕过方法的protected

str = ActiveRecord::Base.__send__(:sanitize_sql, ["AND column1 = ?", "two's"], '')

...至少可以让你不得不将该方法改为public

(我有点怀疑你确实需要这样做,但上面的方法会有效。)

答案 4 :(得分:3)

从滑轨5开始,推荐的方式是使用:ActiveRecord::Base.connection.quote(string)

如此处所述:https://docs.scipy.org/doc/numpy/user/basics.rec.html

ActiveRecord::Base::sanitize(string)已弃用

答案 5 :(得分:0)

请注意,在清理SQL WHERE条件时,最好的解决方案是 sanitize_sql_hash_for_conditions,因为它可以正确处理NULL条件(例如,将生成IS NULL而不是{{ 1}}(如果已传递nil属性)。

由于某种原因,它在Rails 5中已弃用。因此,我推出了一个面向未来的版本,请参见:https://stackoverflow.com/a/53948665/165673