我有一个表格,用户可以使用多种不同类型的组合以各种方式进行过滤。有了我从用户那里获得的所有输入数据,我从SQL中逃脱用户数据非常重要,这导致了我现在遇到的问题。我有两个基于发送到操作的参数动态构建的数组,一个数组包含SQL子句,另一个包含要与其相应的caluse配对的值...例如......
def results
sql_clauses = Array.new
sql_args = Array.new
unless params[:elapsed_time].nil?
sql_clauses << "elapsed_time = ?"
sql_args << params[:elaped_time]
end
unless params[:age_greater_than].nil?
sql_clauses << "age > ?"
sql_args << params[:age_greater_than]
end
.....
@results = Model.where(sql_clauses.join(" and "), sql_args.join(", "))
end
现在这将sql_clauses数组发送到where方法没问题。但它在第二个参数上爆炸,因为它返回一个字符串,并且它期望各个变量与每个“?”相对应。出现在sql_clauses数组中的字段。我已尝试过KandadaBoggu在Comine arrays of conditions in rails上提供的解决方案。这些选项都不适合我,但可能是因为我使用的是2个数组而不是1个。
有人知道我的问题的解决方案吗?
答案 0 :(得分:5)
无需使用字符串在Rails 3中构建动态查询.ActiveRecord方法(如select,where,order,limit等)返回ActiveRecord :: Relation对象,这些对象可以链接而不会触发多个数据库调用:
cars = Car.where(:colour => 'black') # No database queries are generated here.
rich_ppls_cars = cars.order('cars.price DESC').limit(10) # Still no db queries.
当我们在ActiveRecord :: Relation对象上调用.all
,.first
,.last
或.each
时,将会查询数据库。
示例代码
假设您正在使用以下列查询模型:
你有一个看起来像这样的params哈希:
{ :elapsed_time => 34, :age_greater_than => 14, :max_rows => 20 }
您的控制器操作可能如下所示:
def results
query = ModelName.select([:name, :elapsed_time, :age])
query = query.where(:elapsed_time => params[:elapsed_time]) if params[:elapsed_time].present?
query = query.where('age > ?', params[:age_greater_than]) if params[:age_greater_then].present?
query = query.limit(params[:max_rows]) if params[:max_rows].present?
@dynamic_query = query
end
请注意,我正在使用.present?
测试是否存在params键。这可以防止我们将params散列中的空字符串误解为有效数据。
参考资料
答案 1 :(得分:1)
尝试这样的事情:
def results
sql_clauses = []
sql_clauses << "elapsed_time = :elapsed_time" if params[:elapsed_time]
sql_clauses << "age > :age_greater_than" if params[:age_greater_than]
.....
@results = Model.where(sql_clauses.join(" and "), params)
end
where支持各种用于构建条件的差异语法。
如果你有很多可能包含的文件,我会以某种方式制作一个映射字典,如下所示:
map = {
:elapsed_time => "elapsed_time =",
:age_greater_than => "age >"
}
然后循环通过params
键并构建map
中存在的子句。