I have Four models.
Product Category Categorization Images
Product.rb
has_many :images
has_many :categorizations
has_many :categories, :through => :categorizations
Category.rb
has_many :categorizations
has_many :products, :through => :categorizations
Categorization.rb
belongs_to :category
belongs_to :product
Image.rb
belongs_to :product
When a user clicks to see a product, I want to have a section on the bottom that shows images similar products (based on same category/categories).
I guess my problem is that there are so many nested relationships that I don't know how to extract the relationships out.
Any help is appreciated. Thanks.
Just think of what object you are currently working with and what object you need to access. In this case I assume you set up @product
in the controller, and it seems that you want a collection @similar_products
that you then loop through on the bottom of the page.
We have a product to work with at the beginning. From this, we want products that are in the same categories as the product. So, in your controller do
@similar_products = @product.categories.inject({}) do |result_hash, category|
result_hash[category.name.to_sym] => category.products.reject {|p| p == @product}
result_hash
end
So what we end up with is something that looks like this:
{:category_1 => [product1, product2, product3], :category_2 => [product4,product5]...}
I might recommend limiting the number of products for each category to something like 5 by changing the result_hash assignment to
result_hash[category.name.to_sym] => category.products[0..4]
Now in your view you can loop through the products by category if you like:
<% @similar_products.each do |k,product_array| # remember that the key is the name and the value is an array %>
<% product_array.each do |product| %>
<img src="<%= product.image.path %>" />
<% end %>
<% end %>
result_hash[category.name.to_sym] => category.products.reject {|p| p == @product}
to result_hash[category.name.to_sym] = category.productss.order('rand()').limit(4).reject { |p| p == @product}
. But the issue is that even though I limit it to 4 items, it continues to show more items at times when I refresh the page - noob 2012-04-04 15:54
result_hash[category.name.to_sym] = category.productss.order('rand()').limit(4).reject { |p| p == @product}
but it returned an error - noob 2012-04-04 15:54
uniq!
at the wrong place. You need to apply it to the whole hash with something after the whole inject like @similar_products = @similar_products.to_a.flatten.uniq
which will leave you with an array like [:cat_one,product1,product2,:cat_two,product3,product4]
- JamesSwift 2012-04-04 21:19
enum.with_object({}) {|(*args), hash| hash[key] = value }
Reactormonk 2012-04-05 08:33
with_object
instead ofinject
to avoid uglyresult_hash
constructions - Reactormonk 2012-04-03 21:03