2015-11-05 31 views
0

用戶想要通過屬性進行搜索和/或對結果進行排序。以下是一些示例請求帶有許多可選參數的Rails模型查詢

/posts?order=DESC&title=cooking 
/posts?order=ASC 
/posts?title=cooking 

如何有條件地鏈接這些選項以形成查詢?

到目前爲止,我有一個非常難看的方法,很快就會變得難以維護。

def index 
    common = Hash.new 
    common["user_id"] = current_user.id 

    if params[:order] && params[:title] 

     @vacancies = Post.where(common) 
          .where("LOWER(title) LIKE ?", params[:title]) 
          .order("title #{params[:order]}") 

    elsif params[:order] && !params[:title] 

     @vacancies = Post.where(common) 
          .order("title #{params[:order]}") 

    elsif params[:title] && !params[:order] 

     @vacancies = Post.where(common) 
          .where("LOWER(title) LIKE ?", params[:title]) 
    end 
    end 

回答

1

請記住,查詢方法,如whereorder是爲了被鏈接。你想要做什麼是一個基本查詢開始(如Post.where(common),你在任何情況下使用),然後有條件地連接其他的方法:

def index 
    common = Hash.new 
    common["user_id"] = current_user.id 

    @vacancies = Post.where(common) 

    if params[:order] 
    @vacancies = @vacancies.order(title: params[:order].to_sym) 
    end 

    if params[:title] 
    @vacancies = @vacancies.where("LOWER(title) LIKE ?", params[:title]) 
    end 
end 

附:您的原始代碼有.order("title #{params[:order]}")。這是非常危險的,因爲它會讓你面臨SQL注入攻擊。作爲一個經驗法則從不使用字符串連接(#{...})與您從最終用戶獲得的值在打算將結果傳遞到數據庫時使用。因此,我已將其更改爲.order(title: params[:order])。 Rails將使用這個散列構造一個安全的查詢,所以你不必擔心注入攻擊。

您可以在官方Ruby on Rails Security Guide的Rails中瞭解更多關於SQL注入攻擊的信息。

+1

優秀的答案。一件小事,必須將'順序'轉換爲符號才能正常工作:'params [:order] .to_sym'。錯誤只表示:asc和:desc被接受的方向。 – frostbite

+0

好的。我已經更新了我的答案。 –