我正在努力清理其中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
params[:parent_id]
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条件?
看来该reset_table_name方法中抛出了错误,网址为https://github.com/rails/rails/blob/7bb620869725ad6de603f6a5393ee17df13aa96c/activerecord/lib/active_record/model_schema.rb#L160,因此也许该方法并非设计用于ActiveRecord ::基类。
reset_table_name
假设您有一个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'