* Extracting cross-model uniqueness validator Prior to this commit, we had somewhat duplicated logic across four models. In adding this validator we're consolidating the logic and tidying up each of the other models; letting the validator know which models are part of the "uniqueness gang." * Adding conditional test for validator * Bump for travis * Apply suggestions from code review Co-authored-by: Michael Kohl <citizen428@forem.com> Co-authored-by: Michael Kohl <citizen428@forem.com>
63 lines
2.2 KiB
Ruby
63 lines
2.2 KiB
Ruby
class Podcast < ApplicationRecord
|
|
resourcify
|
|
|
|
belongs_to :creator, class_name: "User", inverse_of: :created_podcasts, optional: true
|
|
|
|
has_many :podcast_episodes, dependent: :destroy
|
|
|
|
# order here is important, the :through association has to be defined after the m2m
|
|
has_many :podcast_ownerships, dependent: :destroy
|
|
has_many :owners, through: :podcast_ownerships
|
|
|
|
mount_uploader :image, ProfileImageUploader
|
|
mount_uploader :pattern_image, ProfileImageUploader
|
|
|
|
validates :main_color_hex, :title, :feed_url, :image, presence: true
|
|
validates :main_color_hex, format: /\A([a-fA-F]|[0-9]){6}\Z/
|
|
validates :feed_url, uniqueness: true, url: { schemes: %w[https http] }
|
|
validates :slug,
|
|
presence: true,
|
|
uniqueness: true,
|
|
format: { with: /\A[a-zA-Z0-9\-_]+\Z/ },
|
|
exclusion: { in: ReservedWords.all, message: "slug is reserved" }
|
|
|
|
validates :slug, unique_cross_model_slug: true, if: :slug_changed?
|
|
|
|
after_save :bust_cache
|
|
|
|
scope :reachable, -> { where(id: PodcastEpisode.reachable.select(:podcast_id)) }
|
|
scope :featured, -> { where(featured: true) }
|
|
scope :published, -> { where(published: true) }
|
|
scope :available, -> { reachable.published }
|
|
scope :eager_load_serialized_data, -> { includes(:user, :podcast, :tags) }
|
|
|
|
alias_attribute :path, :slug
|
|
alias_attribute :profile_image_url, :image_url
|
|
alias_attribute :name, :title
|
|
|
|
def existing_episode(item)
|
|
episode = PodcastEpisode.where(media_url: item.enclosure_url)
|
|
.or(PodcastEpisode.where(title: item.title))
|
|
.or(PodcastEpisode.where(guid: item.guid.to_s)).presence
|
|
# if unique_website_url? is set to true (the default value), we try to find an episode by website_url as well
|
|
# if unique_website_url? is set to false it usually means that website_url is the same for different episodes
|
|
episode ||= PodcastEpisode.where(website_url: item.link).presence if item.link.present? && unique_website_url?
|
|
episode.to_a.first
|
|
end
|
|
|
|
def admins
|
|
User.with_role(:podcast_admin, self)
|
|
end
|
|
|
|
def image_90
|
|
Images::Profile.call(profile_image_url, length: 90)
|
|
end
|
|
|
|
private
|
|
|
|
def bust_cache
|
|
return unless path
|
|
|
|
Podcasts::BustCacheWorker.perform_async(path)
|
|
end
|
|
end
|