2016-07-24 65 views
0

我是Ruby on Rails的新手,所以你原諒自己,如果問題很傻...如何獲取最後一個ActiveRecord查詢數據?

我有一個表和兩種形式,第一種形式是過濾(通過複選框),第二種是搜索表格。

我想要的是用已經應用的過濾器搜索表格。我真的不知道要做什麼......我如何從控制器搜索方法訪問「已經過濾」的數據。

的源代碼:

prices_controller.rb

def filter() 
@prices = Price.where(date: Date.today).order(price: :asc) 
    if params[:filter1] != nil 
    @prices = @prices.where('filter1_field IN (?)', params[:filter1]) 
    end 
    if params[:filter2] != nil 
    @prices = @prices.where('filter2_field IN (?)', params[:filter2]) 
    end 
    respond_to do |format| 
    format.js 
    end 
end 

def search() 
    # Here I would like to use filtered prices, not all prices 
    @prices = Price.where(date: Date.today).order(price: :asc) 
    if params[:search] != nil 
    @prices = @prices.where('name LIKE ?', "%#{params[:search]}%") 
    end 
end 

它的工作原理,但我不使用過濾值... 是否有什麼辦法可以挽救的最後一個查詢或類似的東西。我嘗試返回到ActiveRecord :: Relation的搜索方法,但在此類中不存在的方法。其他替代方法是使用相同的形式進行過濾和搜索。

我接受任何類型的建議。

非常感謝。

+0

兩個網頁過濾器1有/過濾器2? – Ven

+0

在同一頁面中,有兩種形式和一張表格。第一種形式的操作是過濾器,參數是filter1和filter2。第二種形式的行爲是搜索,參數是搜索。 – Antonio

+0

好吧,所以這兩種形式是兩種不同的動作 – Ven

回答

1

你不能這樣做,因爲直接

  1. 應用於過濾器的請求,並觸發該請求的搜索是各色2 nt請求。
  2. Rails爲每個請求初始化一個新的控制器實例,所以用於過濾的控制器和用於搜索的控制器是2個不同的對象。他們不共享任何實例變量。

但是,您可以將篩選器階段返回的ID存儲在會話中,並在搜索階段使用這些ID。

def filter 
    @prices = Price.where(date: Date.today).order(price: :asc) 
    if params[:filter1] != nil 
    @prices = @prices.where('filter1_field IN (?)', params[:filter1]) 
    end 
    if params[:filter2] != nil 
    @prices = @prices.where('filter2_field IN (?)', params[:filter2]) 
    end  

    session[:price_ids] = @prices.pluck(:id) 

    respond_to do |format| 
    format.js 
    end 
end 

def search 

    @prices = session[:price_ids].present? ? 
      Price.where(id: session[:price_ids]) : 
      Price.all 

    @prices = @price.where(date: Date.today).order(price: :asc) 
    if params[:search] != nil 
    @prices = @prices.where('name LIKE ?', "%#{params[:search]}%") 
    end 
end 

這種方法,你必須從在適當的時候會議,它可以是很難做定義刪除價格ID的缺點。

另一種方法是確保瀏覽器在每次請求搜索時都發送過濾器(除非您的Rails應用程序是單頁應用程序的API)。每當過濾器發生變化時,這種方法都需要重定向。

def filter 
    redirect_to search_path(params.slice(:filter1, :filter2)) 
end 

def search 
    @prices = Price.where(date: Date.today).order(price: :asc) 
    if params[:filter1] != nil 
    @prices = @prices.where('filter1_field IN (?)', params[:filter1]) 
    end 
    if params[:filter2] != nil 
    @prices = @prices.where('filter2_field IN (?)', params[:filter2]) 
    end 
    if params[:search] != nil 
    @prices = @prices.where('name LIKE ?', "%#{params[:search]}%") 
    end 
end 

和搜索表單應該包含2隱藏字段的過濾器

<%= form_tag '/prices/search', method: :get do %> 
    <%= hidden_field_tag :filter1, params[:filter1] %> 
    <%= hidden_field_tag :filter2, params[:filter2] %> 
    <!-- other form stuff ... --> 
<% end %> 
+0

它適用於我。謝謝 – Antonio

1

這裏有一個非常糟糕的錯誤:你的IN壞了。

的ActiveRecord做SQL消毒(防止SQL注入),所以當你寫:

query.where("a in ?", "hey") 

你得到WHERE a in "hey" SQL一邊。 在你的查詢中是一樣的:你的IN參數將被串化。

如果您filter1a,b,c,查詢將是這樣的:

WHERE a iN ("a,b,c") 

這是不是你想要的所有東西。當您傳遞數組時,ActiveRecord能夠生成IN。所以這個:

query.where(a: [1, 2, 3]) 

將產生:

WHERE q IN (1, 2, 3) 

這是你想要的!


現在,關於代碼本身...

最簡單的方法做你想做的是把代碼移動到另一個方法,而重複使用它在這兩個地方:

def filter() 
@prices = build_filter_query(Date.today, params[:filter1], params[:filter2]) 
    respond_to do |format| 
    format.js 
    end 
end 

def search() 
    @prices = build_filter_query(Date.today, params[:filter1], params[:filter2], params[:search]) #pass in an extra param here! 
end 

private 
    def build_filter_query(date, filter1, filter2, search = nil) 
    # use a local variable here 
    prices = Price.where(date: Date.today).order(price: :asc) 
    if filter1 
     prices = prices.where(filter_field1: filter1) 
    end 
    if filter2 
     prices = prices.where(filter2_field: filter2) 
    end 
    if search 
     prices = prices.where('name LIKE ?', "%#{search}%") 
    end 
    return prices 
    end 
+0

它不起作用。當我提交搜索表單時,filter1和filter2參數將爲零,因爲它們是另一種形式。 – Antonio

+0

啊!請注意,您沒有發佈您的HTML,所以我無法猜測。一個更簡單的選項是使用相同的表單和不同的按鈕。 – Ven

相關問題