Skip to content
Snippets Groups Projects
post.rb 6.65 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
pabois's avatar
pabois committed
#  meta_description         :text
Arnaud Levy's avatar
Arnaud Levy committed
#  migration_identifier     :string
pabois's avatar
pabois committed
#  pinned                   :boolean          default(FALSE)
Arnaud Levy's avatar
Arnaud Levy committed
#  published                :boolean          default(FALSE)
#  published_at             :datetime
pabois's avatar
pabois committed
#  slug                     :string           indexed
#  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
Sébastien Gaya's avatar
Sébastien Gaya committed
#  language_id              :uuid             not null, indexed
#  original_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)
Sébastien Gaya's avatar
Sébastien Gaya committed
#  index_communication_website_posts_on_original_id               (original_id)
pabois's avatar
pabois committed
#  index_communication_website_posts_on_slug                      (slug)
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)
Sébastien Gaya's avatar
Sébastien Gaya committed
#  fk_rails_bbbef3b1e9  (original_id => communication_website_posts.id)
pabois's avatar
pabois committed
#  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
Arnaud Levy's avatar
Arnaud Levy committed
  include AsDirectObject
Arnaud Levy's avatar
Arnaud Levy committed
  include Contentful
  include Permalinkable
pabois's avatar
pabois committed
  include Sanitizable
Arnaud Levy's avatar
Arnaud Levy committed
  include Shareable
Arnaud Levy's avatar
Arnaud Levy committed
  include Sluggable # We override slug_unavailable? method
  include Translatable
Arnaud Levy's avatar
Arnaud Levy committed
  include WithAccessibility
  include WithBlobs
Arnaud Levy's avatar
Arnaud Levy committed
  include WithDuplication
  include WithFeaturedImage
pabois's avatar
pabois committed
  include WithMenuItemTarget
Arnaud Levy's avatar
Arnaud Levy committed
  include WithPublication
Arnaud Levy's avatar
Arnaud Levy committed
  include WithUniversity
pabois's avatar
pabois committed

  has_summernote :text # TODO: Remove text attribute

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
  has_and_belongs_to_many :categories,
Arnaud Levy's avatar
Arnaud Levy committed
                          class_name: 'Communication::Website::Post::Category',
Arnaud Levy's avatar
Arnaud Levy committed
                          join_table: :communication_website_categories_posts,
Arnaud Levy's avatar
Arnaud Levy committed
                          foreign_key: :communication_website_post_id,
                          association_foreign_key: :communication_website_category_id
Arnaud Levy's avatar
Arnaud Levy committed

  validates :title, presence: true

Arnaud Levy's avatar
Arnaud Levy committed
  before_validation :set_published_at
  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()
    ")
  }
Sébastien Gaya's avatar
Sébastien Gaya committed
  scope :ordered, -> { order(pinned: :desc, published_at: :desc, created_at: :desc) }
  scope :latest, -> { published.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_post_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
  def git_path(website)
    return unless website.id == communication_website_id && published && published_at
    git_path_content_prefix(website) + git_path_relative
  end

  def git_path_relative
    "posts/#{static_path}.html"
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

Arnaud Levy's avatar
Arnaud Levy committed
  def dependencies
Arnaud Levy's avatar
Arnaud Levy committed
    active_storage_blobs +
Arnaud Levy's avatar
Arnaud Levy committed
    contents_dependencies +
Sébastien Gaya's avatar
Sébastien Gaya committed
    categories +
    [author&.author] +
    [website.config_default_content_security_policy]
Arnaud Levy's avatar
Arnaud Levy committed
  end

  def references
Sébastien Gaya's avatar
Sébastien Gaya committed
    menus +
Arnaud Levy's avatar
Arnaud Levy committed
    abouts_with_post_block
Arnaud Levy's avatar
Arnaud Levy committed
  end

Sébastien Gaya's avatar
Sébastien Gaya committed
  def translated_author
    @translated_author ||= author.find_or_translate!(language)
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def to_s
    "#{title}"
  end
Arnaud Levy's avatar
Arnaud Levy committed
  def check_accessibility
    accessibility_merge_array blocks
  end

  def slug_unavailable?(slug)
Arnaud Levy's avatar
Arnaud Levy committed
    self.class.unscoped
Sébastien Gaya's avatar
Sébastien Gaya committed
              .where(communication_website_id: self.communication_website_id, language_id: language_id, slug: slug)
Arnaud Levy's avatar
Arnaud Levy committed
              .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
Arnaud Levy's avatar
Arnaud Levy committed
    super.concat [
      featured_image&.blob_id,
      shared_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?
Sébastien Gaya's avatar
Sébastien Gaya committed
      old_author.update(is_author: false)
Sébastien Gaya's avatar
Sébastien Gaya committed
    author.update(is_author: true) if author_id
Sébastien Gaya's avatar
Sébastien Gaya committed

  def translate_additional_data!(translation)
    categories.each do |category|
Sébastien Gaya's avatar
Sébastien Gaya committed
      translated_category = category.find_or_translate!(translation.language)
      translation.categories << translated_category
    end
Sébastien Gaya's avatar
Sébastien Gaya committed
    translation.update(author_id: author.find_or_translate!(translation.language).id) if author_id.present?
Sébastien Gaya's avatar
Sébastien Gaya committed
  end
Arnaud Levy's avatar
Arnaud Levy committed

  def abouts_with_post_block
    website.blocks.posts.collect(&:about)
Arnaud Levy's avatar
Arnaud Levy committed
    # Potentiel gain de performance (25%)
    # Méthode collect : X abouts = X requêtes
    # Méthode ci-dessous : X abouts = 6 requêtes
Arnaud Levy's avatar
Arnaud Levy committed
    # website.post_categories.where(id: website.blocks.posts.where(about_type: "Communication::Website::Post::Category").distinct.pluck(:about_id)) +
Arnaud Levy's avatar
Arnaud Levy committed
    # website.pages.where(id: website.blocks.posts.where(about_type: "Communication::Website::Page").distinct.pluck(:about_id)) +
    # website.posts.where(id: website.blocks.posts.where(about_type: "Communication::Website::Post").distinct.pluck(:about_id))
Arnaud Levy's avatar
Arnaud Levy committed
  end
Arnaud Levy's avatar
Arnaud Levy committed
end