Skip to content
Snippets Groups Projects
post.rb 5.99 KiB
Newer Older
Arnaud Levy's avatar
Arnaud Levy committed
# == Schema Information
#
# Table name: communication_website_posts
#
#  id                       :uuid             not null, primary key
Sébastien Gaya's avatar
Sébastien Gaya committed
#  featured_image_alt       :string
Arnaud Levy's avatar
Arnaud Levy committed
#  featured_image_credit    :text
Arnaud Levy's avatar
Arnaud Levy committed
#  github_path              :text
pabois's avatar
pabois committed
#  meta_description         :text
pabois's avatar
pabois committed
#  pinned                   :boolean          default(FALSE)
Arnaud Levy's avatar
Arnaud Levy committed
#  published                :boolean          default(FALSE)
#  published_at             :datetime
Arnaud Levy's avatar
Arnaud Levy committed
#  slug                     :text
#  summary                  :text
Sébastien Gaya's avatar
Sébastien Gaya committed
#  text                     :text
Arnaud Levy's avatar
Arnaud Levy committed
#  title                    :string
#  created_at               :datetime         not null
#  updated_at               :datetime         not null
pabois's avatar
pabois committed
#  author_id                :uuid             indexed
#  communication_website_id :uuid             not null, indexed
pabois's avatar
pabois committed
#  language_id              :uuid             indexed
pabois's avatar
pabois committed
#  university_id            :uuid             not null, indexed
Arnaud Levy's avatar
Arnaud Levy committed
#
# Indexes
#
pabois's avatar
pabois committed
#  index_communication_website_posts_on_author_id                 (author_id)
Arnaud Levy's avatar
Arnaud Levy committed
#  index_communication_website_posts_on_communication_website_id  (communication_website_id)
pabois's avatar
pabois committed
#  index_communication_website_posts_on_language_id               (language_id)
Arnaud Levy's avatar
Arnaud Levy committed
#  index_communication_website_posts_on_university_id             (university_id)
#
# Foreign Keys
#
pabois's avatar
pabois committed
#  fk_rails_1e0d058a25  (university_id => universities.id)
#  fk_rails_d1c1a10946  (communication_website_id => communication_websites.id)
#  fk_rails_e0eec447b0  (author_id => university_people.id)
Arnaud Levy's avatar
Arnaud Levy committed
#
class Communication::Website::Post < ApplicationRecord
pabois's avatar
pabois committed
  include Sanitizable
Arnaud Levy's avatar
Arnaud Levy committed
  include WithUniversity
Arnaud Levy's avatar
Arnaud Levy committed
  include WithGit
  include WithFeaturedImage
  include WithBlobs
Arnaud Levy's avatar
Arnaud Levy committed
  include WithBlocks
pabois's avatar
pabois committed
  include WithMenuItemTarget
Arnaud Levy's avatar
Arnaud Levy committed
  include WithPermalink
Sébastien Gaya's avatar
Sébastien Gaya committed
  include WithSlug # We override slug_unavailable? method
pabois's avatar
pabois committed

Sébastien Gaya's avatar
Sébastien Gaya committed
  has_summernote :text
pabois's avatar
pabois committed
  has_one :imported_post,
          class_name: 'Communication::Website::Imported::Post',
          dependent: :destroy
Arnaud Levy's avatar
Arnaud Levy committed
  belongs_to :website,
pabois's avatar
pabois committed
             class_name: 'Communication::Website',
Arnaud Levy's avatar
Arnaud Levy committed
             foreign_key: :communication_website_id
pabois's avatar
pabois committed
  belongs_to :author,
Sébastien Gaya's avatar
Sébastien Gaya committed
             class_name: 'University::Person',
pabois's avatar
pabois committed
             optional: true
pabois's avatar
pabois committed
  belongs_to :language, optional: true
pabois's avatar
pabois committed
  has_and_belongs_to_many :categories,
                          class_name: 'Communication::Website::Category',
                          join_table: 'communication_website_categories_posts',
                          foreign_key: 'communication_website_post_id',
                          association_foreign_key: 'communication_website_category_id'
Arnaud Levy's avatar
Arnaud Levy committed

  validates :title, presence: true

  before_validation :set_published_at, if: :published_changed?
  after_save_commit :update_authors_statuses!, if: :saved_change_to_author_id?
  scope :published, -> {
    where("
      communication_website_posts.published = true AND
      DATE(communication_website_posts.published_at) <= now()
    ")
  }
  scope :published_in_the_future, -> {
    where("
      communication_website_posts.published = true AND
      DATE(communication_website_posts.published_at) > now()
    ")
  }
  scope :ordered, -> { order(published_at: :desc, created_at: :desc) }
  scope :recent, -> { order(published_at: :desc).limit(5) }
pabois's avatar
pabois committed
  scope :for_author, -> (author_id) { where(author_id: author_id) }
Sébastien Gaya's avatar
Sébastien Gaya committed
  scope :for_category, -> (category_id) { joins(:categories).where(communication_website_categories: { id: category_id }).distinct }
Sébastien Gaya's avatar
Sébastien Gaya committed
  scope :for_pinned, -> (pinned) { where(pinned: pinned == 'true') }
pabois's avatar
pabois committed
  scope :for_search_term, -> (term) {
    where("
pabois's avatar
pabois committed
      unaccent(communication_website_posts.meta_description) ILIKE unaccent(:term) OR
      unaccent(communication_website_posts.summary) ILIKE unaccent(:term) OR
pabois's avatar
pabois committed
      unaccent(communication_website_posts.text) ILIKE unaccent(:term) OR
      unaccent(communication_website_posts.title) ILIKE unaccent(:term)
    ", term: "%#{sanitize_sql_like(term)}%")
  }
Arnaud Levy's avatar
Arnaud Levy committed

Arnaud Levy's avatar
Arnaud Levy committed
    published && published_at && published_at.to_date <= Date.today
Arnaud Levy's avatar
Arnaud Levy committed
  # Is it used?
pabois's avatar
pabois committed
  def path
Arnaud Levy's avatar
Arnaud Levy committed
    # used in menu_item#static_target
Sébastien Gaya's avatar
Sébastien Gaya committed
    "/#{published_at.strftime "%Y/%m/%d"}/#{slug}"
pabois's avatar
pabois committed
  end

  def git_path(website)
    "#{git_path_content_prefix(website)}posts/#{static_path}.html" if website.id == communication_website_id && published && published_at
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def static_path
Arnaud Levy's avatar
Arnaud Levy committed
    "#{published_at.year}/#{published_at.strftime "%Y-%m-%d"}-#{slug}"
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def template_static
    "admin/communication/websites/posts/static"
  end

  def git_dependencies(website)
pabois's avatar
pabois committed
    dependencies = [self] + website.menus
Sébastien Gaya's avatar
Sébastien Gaya committed
    dependencies += categories
    dependencies += active_storage_blobs
    dependencies += git_block_dependencies
Sébastien Gaya's avatar
Sébastien Gaya committed
    dependencies += university.communication_blocks.where(template_kind: :posts).includes(:about).map(&:about).uniq
Sébastien Gaya's avatar
Sébastien Gaya committed
    if author.present?
      dependencies += [author, author.author]
      dependencies += author.active_storage_blobs
    end
    dependencies
Arnaud Levy's avatar
Arnaud Levy committed
  end

pabois's avatar
pabois committed
  def git_destroy_dependencies(website)
    [self] + explicit_active_storage_blobs
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def url
    return unless published
    return if website.url.blank?
Arnaud Levy's avatar
Arnaud Levy committed
    return if website.special_page(Communication::Website::Page::CommunicationPost)&.path.blank?
    return if current_permalink_in_website(website).blank?
Sébastien Gaya's avatar
Sébastien Gaya committed
    "#{Static.remove_trailing_slash website.url}#{Static.clean_path current_permalink_in_website(website).path}"
Arnaud Levy's avatar
Arnaud Levy committed
  def to_s
    "#{title}"
  end

  protected

  def slug_unavailable?(slug)
Arnaud Levy's avatar
Arnaud Levy committed
    self.class.unscoped
              .where(communication_website_id: self.communication_website_id, slug: slug)
              .where.not(id: self.id)
              .exists?
Arnaud Levy's avatar
Arnaud Levy committed
    self.published_at = Time.zone.now if published && published_at.nil?

  def explicit_blob_ids
Sébastien Gaya's avatar
Sébastien Gaya committed
    super.concat [featured_image&.blob_id]
  end

  def inherited_blob_ids
    [best_featured_image&.blob_id]
  end

  def update_authors_statuses!
    old_author = University::Person.find_by(id: author_id_before_last_save)
    if old_author && old_author.communication_website_posts.none?
      old_author.update_and_sync(is_author: false)
    end
    author.update_and_sync(is_author: true) if author_id
  end
Arnaud Levy's avatar
Arnaud Levy committed
end