# frozen_string_literal: true class Site # Abstrae todo el comportamiento de publicación del sitio en un # módulo. module Deployment extend ActiveSupport::Concern included do # TODO: Hacer que los diferentes tipos de deploy se auto registren # @see app/services/site_service.rb DEPLOYS = %i[local private www zip hidden_service].freeze validates :name, format: { with: /\A[0-9a-z\-]+\z/, message: I18n.t('activerecord.errors.models.site.attributes.name.no_subdomains') } validates :name, hostname: true validates_presence_of :canonical_deploy validate :deploy_local_presence validate :name_changed_is_unique_hostname, if: :name_changed? has_one :canonical_deploy, class_name: 'Deploy' has_many :deploys, dependent: :destroy has_many :access_logs, through: :deploys has_many :build_stats, through: :deploys before_validation :deploy_local_is_default_canonical_deploy!, unless: :canonical_deploy_id? before_update :update_deploy_local_hostname!, if: :name_changed? accepts_nested_attributes_for :deploys, allow_destroy: true # El primer deploy del sitio, si no existe en la base de datos es # porque recién estamos creando el sitio y todavía no se guardó. # # @return [DeployLocal] def deploy_local @deploy_local ||= deploys.order(created_at: :asc).find_by(type: 'DeployLocal') || deploys.find do |d| d.type == 'DeployLocal' end end # Obtiene la URL principal # # @param :slash [Boolean] # @return [String] def canonical_url(slash: true) canonical_deploy.url.dup.tap do |url| url << '/' if slash end end alias_method :url, :canonical_url # Devuelve todas las URLs posibles # # @param :slash [Boolean] # @return [Array] def urls(slash: true) deploys.map(&:url).map do |url| slash ? "#{url}/" : url end end # Obtiene el hostname principal # # @return [String] def hostname canonical_deploy.hostname end private # Validar que al cambiar el nombre no estemos utilizando un # hostname reservado por otro sitio. # # Al cambiar el nombre del DeployLocal se va a validar que el # hostname nuevo sea único. def name_changed_is_unique_hostname deploy_local.hostname = nil return if deploy_local.valid? errors.add :name, I18n.t('activerecord.errors.models.site.attributes.name.duplicated_hostname') end # Si cambia el nombre queremos actualizarlo en el DeployLocal y # recargar el deploy canónico para tomar el nombre que # corresponda. def update_deploy_local_hostname! deploy_local.update(hostname: name) canonical_deploy.reload if canonical_deploy == deploy_local end # Si no asignamos un deploy canónico en el momento le asignamos el # deploy local def deploy_local_is_default_canonical_deploy! self.canonical_deploy ||= deploy_local end # Valida si el sitio tiene al menos una forma de alojamiento asociada # y es la local # # TODO: Volver opcional el alojamiento local, pero ahora mismo está # atado a la generación del sitio así que no puede faltar def deploy_local_presence # Usamos size porque queremos saber la cantidad de deploys sin # guardar también return if deploys.size.positive? && deploys.map(&:type).include?('DeployLocal') errors.add(:deploys, I18n.t('activerecord.errors.models.site.attributes.deploys.deploy_local_presence')) end end end end