This is what I did in one of my projects which is live right now and works very well.
First the category model, it has a name attribute and I am using a gem acts_as_tree
so that categories can have sub categories.
class Category < ActiveRecord::Base
acts_as_tree order: :name
has_many :categoricals
validates :name, uniqueness: { case_sensitive: false }, presence: true
end
Then we will add something called a categorical
model which is a link between any entity(products) that is categorizable
and the category
. Note here, that the categorizable
is polymorphic.
class Categorical < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, polymorphic: true
validates_presence_of :category, :categorizable
end
Now once we have both of these models set up we will add a concern that can make any entity categorizable
in nature, be it products, users, etc.
module Categorizable
extend ActiveSupport::Concern
included do
has_many :categoricals, as: :categorizable
has_many :categories, through: :categoricals
end
def add_to_category(category)
self.categoricals.create(category: category)
end
def remove_from_category(category)
self.categoricals.find_by(category: category).maybe.destroy
end
module ClassMethods
end
end
Now we just include it in a model to make it categorizable.
class Product < ActiveRecord::Base
include Categorizable
end
The usage would be something like this
p = Product.find(1000) # returns a product, Ferrari
c = Category.find_by(name: 'car') # returns the category car
p.add_to_category(c) # associate each other
p.categories # will return all the categories the product belongs to
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…