Skip to content
Snippets Groups Projects
post.rb 5.1 KiB
Newer Older
Arnaud Levy's avatar
Arnaud Levy committed
# == Schema Information
#
# Table name: communication_website_posts
#
#  id                       :uuid             not null, primary key
Arnaud Levy's avatar
Arnaud Levy committed
#  migration_identifier     :string
Arnaud Levy's avatar
Arnaud Levy committed
#  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
#  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)
#  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
Arnaud Levy's avatar
Arnaud Levy committed
  include AsDirectObject
  include Duplicable
  include Filterable
pabois's avatar
pabois committed
  include Sanitizable
  include Localizable
pabois's avatar
pabois committed
  include WithMenuItemTarget
Arnaud Levy's avatar
Arnaud Levy committed
  include WithUniversity
pabois's avatar
pabois committed

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

  after_save_commit :update_authors_statuses!, if: :saved_change_to_author_id?
  scope :ordered, -> (language) {
    localization_published_at_select = <<-SQL
      COALESCE(
        MAX(CASE WHEN localizations.language_id = '#{language.id}' THEN localizations.published_at END),
        '1970-01-01'
      ) AS localization_published_at
    SQL
    localization_pinned_select = <<-SQL
      COALESCE(
        BOOL_OR(CASE WHEN localizations.language_id = '#{language.id}' THEN localizations.pinned END),
        FALSE
      ) AS localization_pinned
    SQL

    joins(sanitize_sql_array([<<-SQL
      LEFT JOIN (
        SELECT
          localizations.*,
          ROW_NUMBER() OVER(PARTITION BY localizations.about_id ORDER BY localizations.created_at ASC) as rank
        FROM
          communication_website_post_localizations as localizations
      ) localizations ON communication_website_posts.id = localizations.about_id
    SQL
    ]))
    .select("communication_website_posts.*", localization_pinned_select, localization_published_at_select)
    .group("communication_website_posts.id")
    .order("localization_pinned DESC, localization_published_at DESC, communication_website_posts.created_at DESC")
pabois's avatar
pabois committed
  }
Arnaud Levy's avatar
Arnaud Levy committed

  scope :latest_in, -> (language) { published_now_in(language).order("communication_website_post_localizations.published_at DESC").limit(5) }
  scope :for_author, -> (author_id, language = nil) { where(author_id: author_id) }
  scope :for_category, -> (category_id, language = nil) { joins(:categories).where(communication_website_post_categories: { id: category_id }).distinct }
  scope :for_search_term, -> (term, language) {
     joins(:localizations)
      .where(communication_website_post_localizations: { language_id: language.id })
      .where("
        unaccent(communication_website_post_localizations.meta_description) ILIKE unaccent(:term) OR
        unaccent(communication_website_post_localizations.summary) ILIKE unaccent(:term) OR
        unaccent(communication_website_post_localizations.text) ILIKE unaccent(:term) OR
        unaccent(communication_website_post_localizations.title) ILIKE unaccent(:term)
      ", term: "%#{sanitize_sql_like(term)}%")
  }
Arnaud Levy's avatar
Arnaud Levy committed

Arnaud Levy's avatar
Arnaud Levy committed
  def dependencies
    [website.config_default_content_security_policy] +
    [website.config_default_languages] +
    localizations.in_languages(website.active_language_ids) +
Sébastien Gaya's avatar
Sébastien Gaya committed
    categories +
    (author.present? ? author.author_facets : [])
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

  def pinned_in?(language)
    localization_for(language).try(:pinned)
Sébastien Gaya's avatar
Sébastien Gaya committed
  end

  def published_at_in(language)
    localization_for(language).try(:published_at)
Arnaud Levy's avatar
Arnaud Levy committed
  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
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