Rails categorization ordering position

Viewed 43

I have a List model in which we can add many Product. Each of these Product is linked to a sub-level Category (that has a parent_id: not-nil).

How could I order the position of the Category and Sub-Category inside a list ?

class List < ApplicationRecord
  has_many :products
  has_many :categories, through: :products
end

class Product < ApplicationRecord
  belongs_to :list
  belongs_to :category

  after_save    :perform_list_category_synchronization
  after_destroy :perform_list_category_synchronization
end

class Category < ApplicationRecord
  has_many :categories, primary_key: :parent_id,
                        foreign_key: :id
  belongs_to :category, optional: true
  has_many :products
end

My guess would be to create a model like this where every time that we change a Product we check that we have a unique element in the table ListCategory containing the category_id of that product, if not, we create it. If the product is deleted and no other product is mentioning this category_id, we delete the record in the ListCategory.

If feel this is really complicated...

class ListCategory < ApplicationRecord
  belongs_to :list
  belongs_to :category
end

I also though about another option where I would create an association model, then when I want to update the position, I update all the records at once.

enter image description here

class ProductCategory < ApplicationRecord
  belongs_to :category
  belongs_to :product
end

Do you have a solution to recommend ?

1 Answers

I might be mis-reading your comments, but if a Product has only one Category, then you should be able to store the Category and the position and Product:

class Product < ApplicationRecord
  belongs_to :list
  belongs_to :category

  after_save    :perform_list_category_synchronization
  after_destroy :perform_list_category_synchronization
end

class Category < ApplicationRecord
  has_many :children, class_name: 'Category', primary_key: :parent_id,
                        foreign_key: :id
  belongs_to :parent, class_name: 'Category', optional: true
  has_many :products
end

If you're re-using the Products on different Lists, then you'll probably need a different change along the lines of:

class List < ApplicationRecord
  has_many :list_products
  has_many :categories, through: :list_products
end

class Product < ApplicationRecord
  has_many :list_products
end

class ListProduct < ApplicationRecord
  belongs_to :list
  belongs_to :category
  belongs_to :product

  after_save    :perform_list_category_synchronization
  after_destroy :perform_list_category_synchronization
end

class Category < ApplicationRecord
  has_many :children, class_name: 'Category', primary_key: :parent_id,
                        foreign_key: :id
  belongs_to :parent, class_name: 'Category', optional: true
  has_many :list_products
end

you would then sort the ListProduct with the position, which wouldn't affect any other List, Product or Category

Related