48
app/controllers/api/v1/accounts/articles_controller.rb
Normal file
48
app/controllers/api/v1/accounts/articles_controller.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
class Api::V1::Accounts::ArticlesController < Api::V1::Accounts::BaseController
|
||||
before_action :portal
|
||||
before_action :fetch_article, except: [:index, :create]
|
||||
|
||||
def index
|
||||
@articles = @portal.articles
|
||||
@articles.search(list_params) if params[:payload].present?
|
||||
end
|
||||
|
||||
def create
|
||||
@article = @portal.articles.create!(article_params)
|
||||
end
|
||||
|
||||
def edit; end
|
||||
|
||||
def show; end
|
||||
|
||||
def update
|
||||
@article.update!(article_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@article.destroy!
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_article
|
||||
@article = @portal.articles.find(params[:id])
|
||||
end
|
||||
|
||||
def portal
|
||||
@portal ||= Current.account.portals.find_by(slug: params[:portal_id])
|
||||
end
|
||||
|
||||
def article_params
|
||||
params.require(:article).permit(
|
||||
:title, :content, :description, :position, :category_id, :author_id
|
||||
)
|
||||
end
|
||||
|
||||
def list_params
|
||||
params.require(:payload).permit(
|
||||
:category_slug, :locale, :query
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,7 @@ class Api::V1::Accounts::CategoriesController < Api::V1::Accounts::BaseControlle
|
||||
before_action :fetch_category, except: [:index, :create]
|
||||
|
||||
def index
|
||||
@categories = @portal.categories
|
||||
@categories = @portal.categories.search(params)
|
||||
end
|
||||
|
||||
def create
|
||||
@@ -31,7 +31,7 @@ class Api::V1::Accounts::CategoriesController < Api::V1::Accounts::BaseControlle
|
||||
|
||||
def category_params
|
||||
params.require(:category).permit(
|
||||
:name, :description, :position
|
||||
:name, :description, :position, :slug, :locale
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,25 +2,34 @@
|
||||
#
|
||||
# Table name: articles
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# content :text
|
||||
# description :text
|
||||
# status :integer
|
||||
# title :string
|
||||
# views :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# author_id :integer
|
||||
# category_id :integer
|
||||
# folder_id :integer
|
||||
# portal_id :integer not null
|
||||
# id :bigint not null, primary key
|
||||
# content :text
|
||||
# description :text
|
||||
# status :integer
|
||||
# title :string
|
||||
# views :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# author_id :bigint
|
||||
# category_id :integer
|
||||
# folder_id :integer
|
||||
# portal_id :integer not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_articles_on_author_id (author_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (author_id => users.id)
|
||||
#
|
||||
class Article < ApplicationRecord
|
||||
include PgSearch::Model
|
||||
|
||||
belongs_to :account
|
||||
belongs_to :category
|
||||
belongs_to :portal
|
||||
belongs_to :folder
|
||||
belongs_to :author, class_name: 'User'
|
||||
|
||||
before_validation :ensure_account_id
|
||||
@@ -32,6 +41,36 @@ class Article < ApplicationRecord
|
||||
|
||||
enum status: { draft: 0, published: 1 }
|
||||
|
||||
scope :search_by_category_slug, ->(category_slug) { where(categories: { slug: category_slug }) if category_slug.present? }
|
||||
scope :search_by_category_locale, ->(locale) { where(categories: { locale: locale }) if locale.present? }
|
||||
|
||||
# TODO: if text search slows down https://www.postgresql.org/docs/current/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS
|
||||
pg_search_scope(
|
||||
:text_search,
|
||||
against: %i[
|
||||
title
|
||||
description
|
||||
content
|
||||
],
|
||||
using: {
|
||||
tsearch: {
|
||||
prefix: true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def self.search(params)
|
||||
records = joins(
|
||||
:category
|
||||
).search_by_category_slug(params[:category_slug]).search_by_category_locale(params[:locale])
|
||||
records.text_search(params[:query]) if params[:query].present?
|
||||
records.page(current_page(params))
|
||||
end
|
||||
|
||||
def self.current_page(params)
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_account_id
|
||||
|
||||
@@ -2,20 +2,22 @@
|
||||
#
|
||||
# Table name: categories
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# description :text
|
||||
# locale :string default("en")
|
||||
# name :string
|
||||
# position :integer
|
||||
# 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
|
||||
# portal_id :integer not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_categories_on_locale (locale)
|
||||
# index_categories_on_locale_and_account_id (locale,account_id)
|
||||
# index_categories_on_locale (locale)
|
||||
# index_categories_on_locale_and_account_id (locale,account_id)
|
||||
# index_categories_on_slug_and_locale_and_portal_id (slug,locale,portal_id) UNIQUE
|
||||
#
|
||||
class Category < ApplicationRecord
|
||||
belongs_to :account
|
||||
@@ -25,7 +27,20 @@ class Category < ApplicationRecord
|
||||
|
||||
before_validation :ensure_account_id
|
||||
validates :account_id, presence: true
|
||||
validates :slug, presence: true
|
||||
validates :name, presence: true
|
||||
validates :locale, uniqueness: { scope: %i[slug portal_id],
|
||||
message: 'should be unique in the category and portal' }
|
||||
|
||||
scope :search_by_locale, ->(locale) { where(locale: locale) if locale.present? }
|
||||
|
||||
def self.search(params)
|
||||
search_by_locale(params[:locale]).page(current_page(params)).order(position: :asc)
|
||||
end
|
||||
|
||||
def self.current_page(params)
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ class User < ApplicationRecord
|
||||
has_many :portals, through: :portals_members
|
||||
has_many :team_members, dependent: :destroy_async
|
||||
has_many :teams, through: :team_members
|
||||
has_many :articles, foreign_key: 'author_id', dependent: :nullify
|
||||
|
||||
before_validation :set_password_and_uid, on: :create
|
||||
|
||||
|
||||
20
app/views/api/v1/accounts/articles/_article.json.jbuilder
Normal file
20
app/views/api/v1/accounts/articles/_article.json.jbuilder
Normal file
@@ -0,0 +1,20 @@
|
||||
json.id article.id
|
||||
json.category_id article.category_id
|
||||
json.title article.title
|
||||
json.content article.content
|
||||
json.description article.description
|
||||
json.status article.status
|
||||
json.account_id article.account_id
|
||||
|
||||
if article.portal.present?
|
||||
json.portal do
|
||||
json.partial! 'api/v1/accounts/portals/portal.json.jbuilder', portal: article.portal
|
||||
end
|
||||
end
|
||||
json.views article.views
|
||||
|
||||
if article.author.present?
|
||||
json.author do
|
||||
json.partial! 'api/v1/models/agent.json.jbuilder', resource: article.author
|
||||
end
|
||||
end
|
||||
3
app/views/api/v1/accounts/articles/create.json.jbuilder
Normal file
3
app/views/api/v1/accounts/articles/create.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.partial! 'article', article: @article
|
||||
end
|
||||
3
app/views/api/v1/accounts/articles/edit.json.jbuilder
Normal file
3
app/views/api/v1/accounts/articles/edit.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.partial! 'article', article: @article
|
||||
end
|
||||
3
app/views/api/v1/accounts/articles/index.json.jbuilder
Normal file
3
app/views/api/v1/accounts/articles/index.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.array! @articles, partial: 'article', as: :article
|
||||
end
|
||||
3
app/views/api/v1/accounts/articles/show.json.jbuilder
Normal file
3
app/views/api/v1/accounts/articles/show.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.partial! 'article', article: @article
|
||||
end
|
||||
3
app/views/api/v1/accounts/articles/update.json.jbuilder
Normal file
3
app/views/api/v1/accounts/articles/update.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.payload do
|
||||
json.partial! 'article', article: @article
|
||||
end
|
||||
@@ -1,5 +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
|
||||
|
||||
Reference in New Issue
Block a user