Reputation: 3553
I'm a bit lost on how to handle multiple param inputs in a URL to build filters in Rails 3.2
Basically, I would like to take http://example.com/products/?category=24 and http://example.com/products/?category=24&country=24 to work together.
I have the following models Product
, Country
, Category
, Categorization
I can build a simple condition in my ProductController
def index
@products = product.all
if params[:country]
@products = Country.find(params[:country]).products
end
if params[:category]
@products = Category.find(params[:category]).products
end
end
I wanted to know the best way to tackle this since my Category
and Product
models through the Categorization
model through with a has_many association.
class Product < ActiveRecord::Base
has_many :categorization
belongs_to :country
end
class Category < ActiveRecord::Base
has_many :categorization
has_many :products, through: :categorization
attr_accessible :name
end
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :product
attr_accessible :category, :product
end
My view layouts template is a simple list of category and country links. So if somebody clicks a category called "Toys" and the clicks on the country "England" it should build a link like so: http://www.example.com/products/category=12&country_id=1
<div class="wrapper">
<div class="products">
</div>
<div class="sidebar>
<h2>Categories</h2>
<ul>
<% @categories.each do |category| %>
<li><%= link_to category.name, params.merge(category: category.id) %></li>
<% end %>
</ul>
<h2>Countries</h2>
<ul>
<% @countries.each do |country| %>
<li><%= link_to country.name, params.merge(country: country.id) %></li>
<% end %>
</ul>
</div>
</div>
Updated
I've gone with the suggestion of creating a filter on the model class and the below code works but it seems quite messy and not DRY.. can someone assist on another approach.
# Product Model
class Product < ActiveRecord::Base
# Search filter
def self.filter_by_params(params)
if params.has_key?(:category) && params.has_key?(:country_id)
scoped.joins(:categorization).where("category_id = ? AND country_id = ?", params[:category], params[:country_id])
elsif params.has_key?(:category)
scoped.joins(:categorization).where("category_id = ?", params[:category])
elsif params.has_key?(:country_id)
scoped.where(country_id: params[:country_id])
else
scoped
end
end
end
# Product Controller
def index
@product = Product.filter_by_params(params)
end
Many thanks for any advice.
WD
Upvotes: 3
Views: 1554
Reputation: 3766
I would change your ProductsController
as follows:
def index
@products = Product.filter_by_params(params)
end
Then in your Product
model:
def self.filter_by_params(params)
scoped = self.scoped
scoped = scoped.where(:country_id => params[:country_id]) if params[:country_id]
scoped = scoped.where(:category_id => params[:category_id]) if params[:category_id]
scoped
end
You'll need to change your view to pass category_id and country_id.
Upvotes: 8