一尘不染

在条件可能为NULL的Rails中清理SQL

sql

我正在努力清理其中WHERE条件可能具有值或为NULL的原始SQL查询。我希望使用Active Record的内置消毒剂…

注意: 出于演示目的,我将使用 简化的 查询-我们真正​​的查询是跨不同模型类型的复杂UNION,这将很难使用AR查询接口来完成)

尝试1:

raw_query = "SELECT * FROM folders WHERE user_id = ? AND parent_id = ?"
sanitized_query = ActiveRecord::Base.send(:sanitize_sql_array, [raw_query, current_user.id, params[:parent_id]])
results = ActiveRecord::Base.connection.execute(sanitized_query);

但是如果params[:parent_id]为nil,则sanitized_query最终应为 SELECT * FROM folders WHERE user_id = 1 AND parent_id = NULL 哪个无效,parent_id = NULL应该是parent_id IS NULL

尝试2:

然后,我找到了sanitize_sql_hash方法,该方法对于建立条件似乎很完美:

sanitized_conditions = ActiveRecord::Base.send(:sanitize_sql_hash, {user_id: current_user.id, parent_id: params[:parent_id]})
sanitized_query = "SELECT * FROM folders WHERE #{sanitized_conditions}"
results = ActiveRecord::Base.connection.execute(sanitized_query);

但是第一行失败:

NoMethodError:未定义的方法“ abstract_class?” 对于对象:类

该方法也被列为已弃用,并将在Rails 5中删除,但这正是我在寻找的东西。还有另一种方法可以从值的哈希值生成安全的WHERE条件?


阅读 145

收藏
2021-05-16

共1个答案

一尘不染

看来该reset_table_name方法中抛出了错误,网址https://github.com/rails/rails/blob/7bb620869725ad6de603f6a5393ee17df13aa96c/activerecord/lib/active_record/model_schema.rb#L160,因此也许该方法并非设计用于ActiveRecord
::基类。

假设您有一个Folder的模型类,它应该可以工作:

Folder.send(:sanitize_sql_hash, {user_id: current_user.id, parent_id: params[:parent_id]})

在快速测试中,我得到了类似的东西:

'"folders"."user_id" = 123 AND "folders"."parent_id" IS NULL'
2021-05-16