所以我想动态地将过滤器参数传递给我的 where 方法所以基本上我有这个
@colleges = College.where(@filter).order(@sort_by).paginate(:page => params[:page], :per_page => 20)
@where 只是一个用这个方法构建的字符串
def get_filter_parameters
if params[:action] == 'index'
table = 'colleges'
columns = College.column_names
else
table = 'housings'
columns = Housing.column_names
end
filters = params.except(:controller, :action, :id, :sort_by, :order, :page, :college_id)
filter_keys = columns & filters.keys
@filter = ""
first = true
if filter_keys
filter_keys.each do |f|
if first
@filter << "#{table}.#{f} = '#{filters[f]}'"
first = false
else
@filter << " AND #{table}.#{f} = '#{filters[f]}'"
end
end
else
@filter = "1=1"
end
问题是我不知道将原始 SQL 放到这样的 where 方法中有多好。我知道通常你可以做类似 :state => 'PA' 的事情,但我该如何动态地做到这一点?
更新
好的,我现在传递一个散列并得到这个:
if params[:action] == 'index'
columns = College.column_names
else
columns = Housing.column_names
end
filters = params.except(:controller, :action, :id, :sort_by, :order, :page, :college_id)
filter_keys = columns & filters.keys
@filter = {}
if filter_keys
filter_keys.each do |f|
@filter[f] = filters[f]
end
end
这足以防止注入(inject)吗?
最佳答案
在此代码中:
College.where(:state => 'PA')
我们实际上是传入一个哈希对象。这意味着这是等价的。
filter = { :state => 'PA' }
College.where(filter)
因此您可以构建此哈希对象而不是字符串:
table = "colleges"
field = "state"
value = "PA"
filter = {}
filter["#{table}.#{field}"] = value
filter["whatever"] = 'omg'
College.where(filter)
但是,对此要小心!
根据此信息的来源,您会将用户提供的字符串放入查询的字段名称中,从而使自己容易受到 SQL 注入(inject)攻击。如果使用得当,Rails 会清理查询中的值。但是,通常列名由应用程序代码固定,不需要清理。因此,您可能会通过这种方式绕过一层 SQL 注入(inject)保护。
关于sql - 将数组传递给 Rails where 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12905305/