class ProductCategory include SimplyStored::Couch property :name property :position, type: Fixnum, default: 0 belongs_to :supplier has_and_belongs_to_many :products, storing_keys: true attr_protected :supplier_id validates :name, presence: true validates :position, numericality: true validates :supplier_id, presence: true def self.for_user(user, options = {}) table = options[:table] raise "ProductCategory.for_user requires a table" unless table.present? list = options[:list] || table.active_list # Get supplier objects products = table.supplier.products product_categories = table.supplier.product_categories || [] # sort categories product_categories.sort_by!{|pc| (pc.position || 90000).to_i } # Append other category if not defined by supplier other = product_categories.find(&:other?) || (product_categories << self.other).last # Container for non categorized products # Initialize base return object h = {table_number: table.number, table_occupied: table.occupied?, supplier_name: table.supplier.name, my_list: list.try(:user_ids).to_a.include?(user.id)} (products - product_categories.map(&:products).flatten).each{ |p| other.add_product(p) } h[:categories] = product_categories.map{|pc| {name: pc.name, products: pc.products.to_a.map{|p| p.as_json}}}.select{|pc| pc && pc[:products].present?} h end def other? %w[other overig].include?(name.to_s.downcase) end def self.other(options = {}) new(options.reverse_merge(name: I18n.t('user.product_category.other_name'))) end end