Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - how to order a model by its has many association?

I have two models:

#Product
class Product < ActiveRecord::Base
  has_and_belongs_to_many :categories
  attr_accessible :name
  ...
end

#Category
class Category < ActiveRecord::Base
  has_and_belongs_to_many :products, :order => "name ASC"

  attr_accessible :name, :priority
end

And I'd like to order my products by the highest priority category and then by products' name

For example I have: 3 categories:

  • Sweets, priority = 3
  • Fruits, priority = 1
  • Desserts, priority = 2

3 products:

  • Chocolate Ice Cream, which has desserts and sweets categories,
  • Cookies, which has desserts and sweets category,
  • Kiwi, which has sweets, fruits and desserts categories

And I'd like them to be ordered like that:

  • Kiwi (first because Fruits is highest priority)
  • Chocolate Ice Cream (second because chocolate comes before cookies and they both have categories with same priority)
  • Cookies

How may I do that in Rails? I don't want my products to be duplicated, I know it would be easy to do something like:

Category.order("priority ASC").each do |cat|
  cat.products.order("name ASC").each do |product|
  end
end

But in that case Kiwi, Chocolate Ice Cream and Cookies would be duplicated because they all have several categories. Is there a simple way to remove duplicates? Or is there a way to order products directly by category highest priority?

Edit: more details about what I want to achieve

What I want in fact, is a huge table where, at the left, I have all the products (and only one line per unique product) sorted by categories... So that I can have something like this:

  • Category - Product
  • Fruit - Banana
  • Fruit - Apple
  • Fruit - Kiwi
  • Desserts - Chocolate Ice Cream
  • Desserts - Cookies
  • Sweet - Chocolate Candy
  • Sweet - Apple Candy
  • ...

See? Even if a fruit is a dessert and sweet, I want it to appears only one time in this table. And I want products to appear in their "most important" category (that why I thought about "priority").

As this huge table will be used to edit products, I want to be able to easily access products' attributes (there'll be one column per attribute). So I really need to do as minimum database requests as possible.


Thanks to anyone who may help me! Kulgar

like image 608
Kulgar Avatar asked Dec 18 '12 08:12

Kulgar


People also ask

What is the difference between Has_one and Belongs_to?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.

What is polymorphic association in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.


2 Answers

To avoid duplicates you can try this,

Product.joins(:categories).group("products.name").order("categories.priority ASC, products.name ASC")
like image 128
shweta Avatar answered Sep 28 '22 08:09

shweta


Maybe try this

products = Product.joins(:categories).order("categories.priority ASC, products.name ASC")

This will fetch duplicated values as well. Let's say you wish to fetch names, maybe you could try this

products.map(&:name).uniq
like image 38
Rahul Avatar answered Sep 28 '22 08:09

Rahul