Alex Zakruzhetskyi
Alex Zakruzhetskyi

Reputation: 1433

Rails search with 2 select_tag

I'd like to use two select_tags for my search. Actually, it all works fine separately, but I'd like to use choose one option in a first/second tag, then the search begins, and later - choose an option in a second/first tag, and see more detailed search result. For now, I have:

Product model:

class Product < ApplicationRecord
  belongs_to :position
  has_and_belongs_to_many :size
end

Size model:

class Size < ApplicationRecord
  has_and_belongs_to_many :products
  has_many :items
end

Position model:

class Position < ApplicationRecord
  has_many :products
end

My application.html.erb:

<div class="container">
    <div class="row text-center">
      <div class="col-sm-6">
        <%= form_tag(products_path, method: 'GET', remote: true) do %>
          <%= select_tag 'size_id', options_from_collection_for_select(Size.all, 'id', 'title'),
                         onchange: ('this.form.submit();'), class: 'form-control', id: 'filter1', include_blank: true %>
        <% end %>
      </div>
      <div class="col-sm-6">
        <%= form_tag(products_path, method: 'GET') do %>
          <%= select_tag 'position_id', options_from_collection_for_select(Position.all, 'id', 'title'),
                         onchange: ('this.form.submit();'), class: 'form-control', id: 'filter2', include_blank: true %>
        <% end %>
      </div>
    </div>
  </div>

And a products_controller:

class ProductsController < ApplicationController
  def index    
    if params[:position_id]
      position = Position.find(params[:position_id])
      @products = position.products
      respond_to do |format|
        format.html
        format.json { render json: @products }
      end
    elsif params[:size_id]
      size = Size.find(params[:size_id])
      @products = size.products
      respond_to do |format|
        format.html
        format.json { render json: @products }
      end
    else
      @products = Product.all
      respond_to do |format|
        format.html
        format.json { render json: @products }
      end
    end
  end
end

So, how can I do a search that will work not separately? Thanks ahead.

Upvotes: 1

Views: 157

Answers (2)

Diego Nolde
Diego Nolde

Reputation: 61

First of all, I believe you should put both select_tags in the same form if you want them to work together.

  <div class="container">
    <div class="row text-center">
      <%= form_tag(products_path, method: 'GET', remote: true) do %>
      <div class="col-sm-6">
          <%= select_tag 'size_id', options_from_collection_for_select(Size.all, 'id', 'title'),
                         onchange: ('this.form.submit();'), class: 'form-control', id: 'filter1', include_blank: true %>
      </div>
      <div class="col-sm-6">
          <%= select_tag 'position_id', options_from_collection_for_select(Position.all, 'id', 'title'),
                         onchange: ('this.form.submit();'), class: 'form-control', id: 'filter2', include_blank: true %>
      </div>
      <% end %>
    </div>
  </div>

Then you need to change your controller to use the parameters you have:

def index
  @products = Product.scoped  # or Product.all if you are using Rails 4.0.13 or newer
  @products = @products.where(position_id: params[:position_id]) if params[:position_id].present?
  @products = @products.where(size_id: params[:size_id]) if params[:size_id].present?
  respond_to do |format|
    format.html
    format.json { render json: @products }
  end
end

With that, the controller will add only the paramenter you send to the WHERE part of your SQL command.

> Product.scoped
  SELECT `products`.* FROM `products` 

> Product.scoped.where(position_id: 1)
  SELECT `products`.* FROM `products` WHERE `products`.`position_id` = 1

> Product.scoped.where(size_id: 1)
  SELECT `products`.* FROM `products` WHERE `products`.`size_id` = 1

> Product.scoped.where(position_id: 1).where(size_id: 1)
  SELECT `products`.* FROM `products` WHERE `products`.`position_id` = 1 AND `products`.`size_id` = 1

Upvotes: 1

Chetan Datta
Chetan Datta

Reputation: 445

search_parameters = {
  :position_id => params[:position_id],:size_id => params[:size_id]}
  .select { |key,value| value.present? }

@products = Product.where(
  search_parameters, params[:position_id], params[:size_id])

Upvotes: 0

Related Questions