user2092653
user2092653

Reputation: 53

search items by category_id with select_tag drop down in rails

I have edited my first code and now it's better and cleaner thanks to @FunTimeFreddie, but the issue it's not yet properly solved. I'll come back with the right answer sooner.

In a search form I need to filter all menuitems: 1. per category 2. per category and search “query” 3. per min price && || max price … and so on, with all possible combinations

I’ve manage to make a search in all menuitems with a “query”, min_price and max_price --all possible combinations from the search form. I can NOT manage to have the list of results of the chosen category, what am I doing wrong?

This is my model(edited):

class Menuitem < ActiveRecord::Base

belongs_to :menu_category

include Filterable

scope :newest_first, lambda { order('menuitems.created_at DESC') }
scope :last_one, lambda { order('menuitems.created_at ASC').last }

scope :search_keyword, lambda { |query|
    where(["title LIKE ? or body LIKE ?", "%#{query}%", "%#{query}%"]) if query != ""
}

scope :menu_category_id, lambda { |menu_category_id|
    where( "menu_category_id = ?", menu_category_id ) if menu_category_id != ""
}

scope :min_price, lambda { |price|
    where("price > ?", price) if price != ""
}

scope :max_price, lambda { |price|
    where("price < ?", price) if price != ""
}
end

This is my controller(edited):

class MenuitemsController < ApplicationController
def index
@menuitems = Menuitem.newest_first.filter(params.slice(:menu_category_id, :search_keyword, :min_price, :max_price))
end

And this is my view:

<%= simple_form_for :menuitem, :method => 'get', :url => {:action => 'index'} do |f| %>
            <p>
                <%= f.select :menu_category_id, options_for_select(@menucategories.map {|s| [s.title, s.id]}, params[:menu_category_id]), :selected => params[:menu_category_id], :onchange => "this.form.submit();", prompt: "Select category" %>
            </p>
            <p>
            <%= f.input :search_keyword, input_html: { name: 'search_keyword', :value => params[:search_keyword]}, label: 'search recipe title', :required => false %>
            <%= f.input :min_price, input_html: { name: 'min_price', :value => params[:min_price]}, label: 'min price:', :required => false %>
            <%= f.input :max_price, input_html: { name: 'max_price', :value => params[:max_price]}, label: 'max price:', :required => false %>
            <%= f.button :submit, "search" %>
          </p>
        <% end %>

Upvotes: 0

Views: 997

Answers (2)

FunTimeFreddie
FunTimeFreddie

Reputation: 61

There seems to be two issues with the category parameter. The first is it is a nested parameter within params[:menuitem], so in order to access it we need to call params[:menuitem][:menu_category_id]. Not too sure why this is happening to be honest, though I would recommend in this instance using a form_tag as opposed to form_for, given that we are not adding or editing the menuitems table itself.

The second issue is the category parameter is passed as a string, whereas we need it as an integer. We'll need to convert to parameter before applying it.

Now I'm not familiar with the .filters method (is this part of a gem?) but I got this to work the old fashioned way just by concatenating all the scopes together in one line as follows...

# menuitems controller
  def index
    @menuitems = Menuitem.newest_first.min_price(params[:min_price]).max_price(params[:max_price]).search_keyword(params[:search_keyword]).menu_category_id(params[:menuitem][:menu_category_id].to_i)
  end

Note, another way of changing the data type would be to do so in the scope. You could do this as follows

# menuitem model
scope :menu_category_id, lambda { |menu_category_id|
where( "menu_category_id = ?", menu_category_id.to_i ) if menu_category_id != ""

}

Upvotes: 0

FunTimeFreddie
FunTimeFreddie

Reputation: 61

You can save yourself the trouble of all the IF statements in your controller for all of the combinations by adding an IF statement within the scopes. For example, and this can similarly be applied to the four scopes associated to your form,

# menuitem model
scope :search_keyword, lambda { |query|
    where(["name LIKE ?", "%#{query}%"]) if query != ""
}

This will allow to include only a single line in your controller, the line beneath your first IF statement, as this will handle the blank parameters.

Upvotes: 1

Related Questions