2016-12-23 51 views
0

我有下面的代碼,我正在使用基於用戶的搜索過濾帖子的結果。我如何確保參數存在,有效和消毒?Rails消毒和驗證用戶輸入where條款

Post.where("title LIKE ? AND cost >= ? AND cost <= ? AND status = 'open'", "%#{search_params[:keywords]}%", 
        "#{search_params[:min] && !search_params[:min].empty? ? search_params[:min] : 0}", 
        "#{search_params[:max] && !search_params[:max].empty? ? search_params[:max] : 999999999}"); 
+0

的'#sanitize_sql_for_conditions'方法應該在這裏派上用場 - [see docs](http://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html#method-i-sanitize_sql_for_conditions) – Zoran

回答

0

有 - 像往常一樣 - 有很多方法可以解決這個問題。

我認爲最好的是use a form model。幫助實施此模式的好寶石是virtusreform,但您也可以使用plain ActiveModel

這個想法是表單對象進行驗證,如果它無效,控制器可以呈現驗證錯誤。

如果您在網上搜索「Rails form model pattern」或類似內容,您會發現更多文章。下面是另一個看起來很好的例子:https://webuild.envato.com/blog/creating-form-objects-with-activemodel-and-virtus/

在相關說明中,您可能希望將這個複雜查詢封裝在作用域中,或者 - 如果您的應用程序將要增長 - 甚至是查詢對象。請參閱this article以獲取更多高級模式,這些模式在更復雜的Rails應用程序中可能具有優勢。

關於輸入的清理,只要你使用參數綁定而不是手動字符串連接,Rails會自動清理輸入以防止SQL注入。如果你想做更多的事情 - 比如從搜索查詢或某事中刪除停用詞。像這樣,你可能會更好用預先存在的搜索框架,如sphinx,pg_searchtextacular

0

我會通過組合型數範圍有一定的條件解決這個問題:

# in your models/post.rb 
scope :min_cost, ->(cost) { 
    cost = 0 if cost.blank? 
    where('cost >= ?', cost) 
} 
scope :max_cost, ->(cost) { 
    cost = 999_999_999 if cost.blank? 
    where('cost <= ?', cost) 
} 
scope :cost_between, ->(min, max) { min_cost(min).max_cost(max) } 
scope :open, -> { where(status: 'open') } 
scope :search, ->(title) { where("title LIKE ?", "%#{title}%") if title } 

在控制器的使用該作用域是這樣的:

Post.open.search(search_params[:keywords]) 
     .cost_between(search_params[:min], search_params[:max])