feat: Category API to handle linked categories and parent-sub categories (#4879)
This commit is contained in:
@@ -8,10 +8,20 @@ class Api::V1::Accounts::CategoriesController < Api::V1::Accounts::BaseControlle
|
||||
|
||||
def create
|
||||
@category = @portal.categories.create!(category_params)
|
||||
@category.related_categories << related_categories_records
|
||||
render json: { error: @category.errors.messages }, status: :unprocessable_entity and return unless @category.valid?
|
||||
|
||||
@category.save!
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def update
|
||||
@category.update!(category_params)
|
||||
@category.related_categories = related_categories_records if related_categories_records.any?
|
||||
render json: { error: @category.errors.messages }, status: :unprocessable_entity and return unless @category.valid?
|
||||
|
||||
@category.save!
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -29,9 +39,13 @@ class Api::V1::Accounts::CategoriesController < Api::V1::Accounts::BaseControlle
|
||||
@portal ||= Current.account.portals.find_by(slug: params[:portal_id])
|
||||
end
|
||||
|
||||
def related_categories_records
|
||||
@portal.categories.where(id: params[:category][:related_category_ids])
|
||||
end
|
||||
|
||||
def category_params
|
||||
params.require(:category).permit(
|
||||
:name, :description, :position, :slug, :locale
|
||||
:name, :description, :position, :slug, :locale, :parent_category_id, :linked_category_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,28 +2,56 @@
|
||||
#
|
||||
# Table name: categories
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# description :text
|
||||
# locale :string default("en")
|
||||
# name :string
|
||||
# position :integer
|
||||
# slug :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# portal_id :integer not null
|
||||
# id :bigint not null, primary key
|
||||
# description :text
|
||||
# locale :string default("en")
|
||||
# name :string
|
||||
# position :integer
|
||||
# slug :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# linked_category_id :bigint
|
||||
# parent_category_id :bigint
|
||||
# portal_id :integer not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_categories_on_linked_category_id (linked_category_id)
|
||||
# index_categories_on_locale (locale)
|
||||
# index_categories_on_locale_and_account_id (locale,account_id)
|
||||
# index_categories_on_parent_category_id (parent_category_id)
|
||||
# index_categories_on_slug_and_locale_and_portal_id (slug,locale,portal_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (linked_category_id => categories.id)
|
||||
# fk_rails_... (parent_category_id => categories.id)
|
||||
#
|
||||
class Category < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :portal
|
||||
has_many :folders, dependent: :destroy_async
|
||||
has_many :articles, dependent: :nullify
|
||||
has_many :category_related_categories,
|
||||
class_name: :RelatedCategory,
|
||||
dependent: :destroy_async
|
||||
has_many :related_categories,
|
||||
through: :category_related_categories,
|
||||
class_name: :Category,
|
||||
dependent: :nullify
|
||||
has_many :sub_categories,
|
||||
class_name: :Category,
|
||||
foreign_key: :parent_category_id,
|
||||
dependent: :nullify,
|
||||
inverse_of: 'parent_category'
|
||||
has_many :linked_categories,
|
||||
class_name: :Category,
|
||||
foreign_key: :linked_category_id,
|
||||
dependent: :nullify,
|
||||
inverse_of: 'linked_category'
|
||||
belongs_to :parent_category, class_name: :Category, optional: true
|
||||
belongs_to :linked_category, class_name: :Category, optional: true
|
||||
|
||||
before_validation :ensure_account_id
|
||||
validates :account_id, presence: true
|
||||
@@ -31,6 +59,7 @@ class Category < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
validates :locale, uniqueness: { scope: %i[slug portal_id],
|
||||
message: 'should be unique in the category and portal' }
|
||||
accepts_nested_attributes_for :related_categories
|
||||
|
||||
scope :search_by_locale, ->(locale) { where(locale: locale) if locale.present? }
|
||||
|
||||
|
||||
19
app/models/related_category.rb
Normal file
19
app/models/related_category.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: related_categories
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# category_id :bigint
|
||||
# related_category_id :bigint
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_related_categories_on_category_id_and_related_category_id (category_id,related_category_id) UNIQUE
|
||||
# index_related_categories_on_related_category_id_and_category_id (related_category_id,category_id) UNIQUE
|
||||
#
|
||||
class RelatedCategory < ApplicationRecord
|
||||
belongs_to :related_category, class_name: 'Category'
|
||||
belongs_to :category, class_name: 'Category'
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
json.id category.id
|
||||
json.name category.name
|
||||
json.slug category.slug
|
||||
json.locale category.locale
|
||||
json.description category.description
|
||||
json.position category.position
|
||||
json.account_id category.account_id
|
||||
@@ -5,3 +5,23 @@ json.locale category.locale
|
||||
json.description category.description
|
||||
json.position category.position
|
||||
json.account_id category.account_id
|
||||
|
||||
json.related_categories do
|
||||
if category.related_categories.any?
|
||||
json.array! category.related_categories.each do |related_category|
|
||||
json.partial! 'api/v1/accounts/categories/associated_category.json.jbuilder', category: related_category
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if category.parent_category.present?
|
||||
json.parent_category do
|
||||
json.partial! 'api/v1/accounts/categories/associated_category.json.jbuilder', category: category.parent_category
|
||||
end
|
||||
end
|
||||
|
||||
if category.linked_category.present?
|
||||
json.linked_category do
|
||||
json.partial! 'api/v1/accounts/categories/associated_category.json.jbuilder', category: category.linked_category
|
||||
end
|
||||
end
|
||||
|
||||
3
app/views/api/v1/accounts/categories/show.json.jbuilder
Normal file
3
app/views/api/v1/accounts/categories/show.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.partial! 'category', category: @category
|
||||
end
|
||||
Reference in New Issue
Block a user