mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			122 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # == Schema Information
 | |
| #
 | |
| # Table name: articles
 | |
| #
 | |
| #  id                    :bigint           not null, primary key
 | |
| #  content               :text
 | |
| #  description           :text
 | |
| #  meta                  :jsonb
 | |
| #  slug                  :string           not null
 | |
| #  status                :integer
 | |
| #  title                 :string
 | |
| #  views                 :integer
 | |
| #  created_at            :datetime         not null
 | |
| #  updated_at            :datetime         not null
 | |
| #  account_id            :integer          not null
 | |
| #  associated_article_id :bigint
 | |
| #  author_id             :bigint
 | |
| #  category_id           :integer
 | |
| #  folder_id             :integer
 | |
| #  portal_id             :integer          not null
 | |
| #
 | |
| # Indexes
 | |
| #
 | |
| #  index_articles_on_associated_article_id  (associated_article_id)
 | |
| #  index_articles_on_author_id              (author_id)
 | |
| #  index_articles_on_slug                   (slug) UNIQUE
 | |
| #
 | |
| class Article < ApplicationRecord
 | |
|   include PgSearch::Model
 | |
| 
 | |
|   has_many :associated_articles,
 | |
|            class_name: :Article,
 | |
|            foreign_key: :associated_article_id,
 | |
|            dependent: :nullify,
 | |
|            inverse_of: 'root_article'
 | |
| 
 | |
|   belongs_to :root_article,
 | |
|              class_name: :Article,
 | |
|              foreign_key: :associated_article_id,
 | |
|              inverse_of: :associated_articles,
 | |
|              optional: true
 | |
|   belongs_to :account
 | |
|   belongs_to :category
 | |
|   belongs_to :portal
 | |
|   belongs_to :author, class_name: 'User'
 | |
| 
 | |
|   before_validation :ensure_account_id
 | |
|   before_validation :ensure_article_slug
 | |
| 
 | |
|   validates :account_id, presence: true
 | |
|   validates :category_id, presence: true
 | |
|   validates :author_id, presence: true
 | |
|   validates :title, presence: true
 | |
|   validates :content, presence: true
 | |
| 
 | |
|   enum status: { draft: 0, published: 1, archived: 2 }
 | |
| 
 | |
|   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? }
 | |
|   scope :search_by_author, ->(author_id) { where(author_id: author_id) if author_id.present? }
 | |
|   scope :search_by_status, ->(status) { where(status: status) if status.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]).search_by_author(params[:author_id]).search_by_status(params[:status])
 | |
| 
 | |
|     records = records.text_search(params[:query]) if params[:query].present?
 | |
|     records.page(current_page(params))
 | |
|   end
 | |
| 
 | |
|   def self.current_page(params)
 | |
|     params[:page] || 1
 | |
|   end
 | |
| 
 | |
|   def associate_root_article(associated_article_id)
 | |
|     article = portal.articles.find(associated_article_id) if associated_article_id.present?
 | |
| 
 | |
|     return if article.nil?
 | |
| 
 | |
|     root_article_id = self.class.find_root_article_id(article)
 | |
| 
 | |
|     update(associated_article_id: root_article_id) if root_article_id.present?
 | |
|   end
 | |
| 
 | |
|   # Make sure we always associate the parent's associated id to avoid the deeper associations od articles.
 | |
|   def self.find_root_article_id(article)
 | |
|     article.associated_article_id || article.id
 | |
|   end
 | |
| 
 | |
|   def draft!
 | |
|     update(status: :draft)
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def ensure_account_id
 | |
|     self.account_id = portal&.account_id
 | |
|   end
 | |
| 
 | |
|   def ensure_article_slug
 | |
|     self.slug ||= "#{Time.now.utc.to_i}-#{title.underscore.parameterize(separator: '-')}" if title.present?
 | |
|   end
 | |
| end
 | 
