Introduced published field to podcasts (#3593)
* Published field for podcasts * Add podcasts migration * More specs for podcasts availability * Show published in podcasts internal * Update schema.rb with db:migrate
This commit is contained in:
parent
fc9272fe71
commit
fabaeb5461
18 changed files with 89 additions and 21 deletions
|
|
@ -5,7 +5,7 @@ module Admin
|
|||
authorize_resource(resource)
|
||||
|
||||
if resource.save
|
||||
Podcasts::GetEpisodesJob.perform_later(podcast_id: resource.id)
|
||||
Podcasts::GetEpisodesJob.perform_later(podcast_id: resource.id) if resource.published
|
||||
redirect_to(
|
||||
[namespace, resource],
|
||||
notice: translate_with_resource("create.success"),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module Api
|
|||
@page = params[:page]
|
||||
|
||||
if params[:username]
|
||||
@podcast = Podcast.reachable.find_by!(slug: params[:username])
|
||||
@podcast = Podcast.available.find_by!(slug: params[:username])
|
||||
@podcast_episodes = @podcast.
|
||||
podcast_episodes.reachable.order("published_at desc").
|
||||
page(@page).
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ class PodcastEpisodesController < ApplicationController
|
|||
|
||||
def index
|
||||
@podcast_index = true
|
||||
@podcasts = Podcast.reachable.order("title asc")
|
||||
@podcast_episodes = PodcastEpisode.reachable.order("published_at desc").first(20)
|
||||
@podcasts = Podcast.available.order("title asc")
|
||||
@podcast_episodes = PodcastEpisode.available.order("published_at desc").first(20)
|
||||
if params[:q].blank?
|
||||
set_surrogate_key_header("podcast_episodes_all " + params[:q].to_s,
|
||||
@podcast_episodes.map { |e| e["record_key"] })
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class StoriesController < ApplicationController
|
|||
elsif (@article = Article.find_by(slug: params[:slug])&.decorate)
|
||||
handle_possible_redirect
|
||||
else
|
||||
@podcast = Podcast.reachable.find_by!(slug: params[:username])
|
||||
@episode = PodcastEpisode.reachable.find_by!(slug: params[:slug])
|
||||
@podcast = Podcast.available.find_by!(slug: params[:username])
|
||||
@episode = PodcastEpisode.available.find_by!(slug: params[:slug])
|
||||
handle_podcast_show
|
||||
end
|
||||
end
|
||||
|
|
@ -64,7 +64,7 @@ class StoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def handle_user_or_organization_or_podcast_or_page_index
|
||||
@podcast = Podcast.reachable.find_by(slug: params[:username].downcase)
|
||||
@podcast = Podcast.available.find_by(slug: params[:username].downcase)
|
||||
@organization = Organization.find_by(slug: params[:username].downcase)
|
||||
@page = Page.find_by(slug: params[:username].downcase, is_top_level_path: true)
|
||||
if @podcast
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class PodcastDashboard < Administrate::BaseDashboard
|
|||
pattern_image: CarrierwaveField,
|
||||
slug: Field::String,
|
||||
reachable: Field::Boolean,
|
||||
published: Field::Boolean,
|
||||
status_notice: Field::Text,
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime
|
||||
|
|
@ -38,6 +39,7 @@ class PodcastDashboard < Administrate::BaseDashboard
|
|||
podcast_episodes
|
||||
id
|
||||
reachable
|
||||
published
|
||||
status_notice
|
||||
title
|
||||
description
|
||||
|
|
@ -63,6 +65,7 @@ class PodcastDashboard < Administrate::BaseDashboard
|
|||
pattern_image
|
||||
slug
|
||||
reachable
|
||||
published
|
||||
created_at
|
||||
updated_at
|
||||
].freeze
|
||||
|
|
@ -87,6 +90,7 @@ class PodcastDashboard < Administrate::BaseDashboard
|
|||
image
|
||||
slug
|
||||
reachable
|
||||
published
|
||||
].freeze
|
||||
|
||||
# Overwrite this method to customize how podcasts are displayed
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class Podcast < ApplicationRecord
|
|||
after_save :bust_cache
|
||||
|
||||
scope :reachable, -> { where(id: PodcastEpisode.reachable.select(:podcast_id)) }
|
||||
scope :published, -> { where(published: true) }
|
||||
scope :available, -> { reachable.published }
|
||||
|
||||
alias_attribute :path, :slug
|
||||
alias_attribute :profile_image_url, :image_url
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ class PodcastEpisode < ApplicationRecord
|
|||
before_validation :prefix_all_images
|
||||
|
||||
scope :reachable, -> { where(reachable: true) }
|
||||
scope :published, -> { joins(:podcast).where(podcasts: { published: true }) }
|
||||
scope :available, -> { reachable.published }
|
||||
|
||||
algoliasearch per_environment: true do
|
||||
attribute :id
|
||||
|
|
|
|||
|
|
@ -14,23 +14,25 @@
|
|||
|
||||
<%= paginate @podcasts %>
|
||||
<br>
|
||||
<div class="wrapper-7" style="font-weight: 600; border-bottom: 2px solid black;">
|
||||
<div class="wrapper-8" style="font-weight: 600; border-bottom: 2px solid black;">
|
||||
<div>ID</div>
|
||||
<div>Title</div>
|
||||
<div>Feed URL</div>
|
||||
<div>Episodes</div>
|
||||
<div>Reachable</div>
|
||||
<div>Eps</div>
|
||||
<div>Reach</div>
|
||||
<div>Pub</div>
|
||||
<div>Status Notice</div>
|
||||
<div>Admins</div>
|
||||
</div>
|
||||
|
||||
<% @podcasts.each do |podcast| %>
|
||||
<div class="wrapper-7" style="border-bottom: 1px solid grey; padding: 10px;">
|
||||
<div class="wrapper-8" style="border-bottom: 1px solid grey; padding: 10px;">
|
||||
<div class="grid-item"><%= podcast.id %></div>
|
||||
<div class="grid-item"><a href="<%= edit_internal_podcast_path(podcast) %>"><%= podcast.title %></a></div>
|
||||
<div class="grid-item"><a href="<%= podcast.feed_url %>"><%= podcast.feed_url %></a></div>
|
||||
<div class="grid-item"><%= podcast.podcast_episodes.count %></div>
|
||||
<div class="grid-item"><%= podcast.reachable %></div>
|
||||
<div class="grid-item"><%= podcast.published %></div>
|
||||
<div class="grid-item"><%= podcast.status_notice %></div>
|
||||
<div class="grid-item">
|
||||
<% podcast.admins.pluck(:username).each do |username| %>
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@
|
|||
padding: 2px;
|
||||
}
|
||||
|
||||
.wrapper-7 {
|
||||
.wrapper-8 {
|
||||
display: grid;
|
||||
grid-template-columns: 5% 15% 25% 10% 10% 20% 15%;
|
||||
grid-template-columns: 4% 15% 25% 7% 7% 7% 20% 15%;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
|
|
|
|||
9
db/migrate/20190801083510_add_published_to_podcasts.rb
Normal file
9
db/migrate/20190801083510_add_published_to_podcasts.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
class AddPublishedToPodcasts < ActiveRecord::Migration[5.2]
|
||||
class Podcast < ApplicationRecord; end
|
||||
|
||||
def change
|
||||
add_column :podcasts, :published, :boolean, default: false
|
||||
|
||||
Podcast.update_all(published: true)
|
||||
end
|
||||
end
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2019_07_23_094834) do
|
||||
ActiveRecord::Schema.define(version: 2019_08_01_083510) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
|
|
@ -737,6 +737,7 @@ ActiveRecord::Schema.define(version: 2019_07_23_094834) do
|
|||
t.string "main_color_hex", null: false
|
||||
t.string "overcast_url"
|
||||
t.string "pattern_image"
|
||||
t.boolean "published", default: false
|
||||
t.boolean "reachable", default: true
|
||||
t.string "slug", null: false
|
||||
t.string "soundcloud_url"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
desc "This task is called by the Heroku scheduler add-on"
|
||||
|
||||
task get_podcast_episodes: :environment do
|
||||
Podcast.select(:id).find_each do |podcast|
|
||||
Podcast.published.select(:id).find_each do |podcast|
|
||||
Podcasts::GetEpisodesJob.perform_later(podcast_id: podcast.id, limit: 5)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ FactoryBot.define do
|
|||
slug { "slug-#{rand(10_000)}" }
|
||||
feed_url { Faker::Internet.url }
|
||||
main_color_hex { "ffffff" }
|
||||
published { true }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,6 +33,22 @@ RSpec.describe PodcastEpisode, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#available" do
|
||||
let(:podcast) { create(:podcast) }
|
||||
let(:unpodcast) { create(:podcast, published: false) }
|
||||
let!(:episode) { create(:podcast_episode, podcast: podcast) }
|
||||
|
||||
before do
|
||||
create(:podcast_episode, podcast: unpodcast)
|
||||
create(:podcast_episode, podcast: podcast, reachable: false)
|
||||
end
|
||||
|
||||
it "is available when reachable and published" do
|
||||
available_ids = described_class.available.pluck(:id)
|
||||
expect(available_ids).to eq([episode.id])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#description" do
|
||||
it "strips tags from the body" do
|
||||
podcast_episode.body = "<h1>Body with HTML tags</h1>"
|
||||
|
|
|
|||
|
|
@ -65,16 +65,18 @@ RSpec.describe Podcast, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#reachable" do
|
||||
let(:podcast) { create(:podcast, reachable: false) }
|
||||
let!(:unpodcast) { create(:podcast, reachable: false) }
|
||||
let!(:unpodcast2) { create(:podcast, reachable: false) }
|
||||
let!(:cool_podcast) { create(:podcast, reachable: true) }
|
||||
describe "#reachable and #available" do
|
||||
let(:podcast) { create(:podcast, reachable: false, published: true) }
|
||||
let!(:unpodcast) { create(:podcast, reachable: false, published: true) }
|
||||
let!(:unpodcast2) { create(:podcast, reachable: false, published: true) }
|
||||
let!(:cool_podcast) { create(:podcast, reachable: true, published: false) }
|
||||
let!(:reachable_podcast) { create(:podcast, reachable: true, published: true) }
|
||||
|
||||
before do
|
||||
create(:podcast_episode, reachable: true, podcast: podcast)
|
||||
create(:podcast_episode, reachable: false, podcast: unpodcast2)
|
||||
create(:podcast_episode, reachable: true, podcast: cool_podcast)
|
||||
create(:podcast_episode, reachable: true, podcast: reachable_podcast)
|
||||
end
|
||||
|
||||
it "is reachable when the feed is unreachable but the podcast has reachable podcasts" do
|
||||
|
|
@ -84,6 +86,11 @@ RSpec.describe Podcast, type: :model do
|
|||
expect(reachable_ids).not_to include(unpodcast.id)
|
||||
expect(reachable_ids).not_to include(unpodcast2.id)
|
||||
end
|
||||
|
||||
it "is available only when reachable and published" do
|
||||
available_ids = described_class.available.pluck(:id)
|
||||
expect(available_ids.sort).to eq([podcast.id, reachable_podcast.id].sort)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#existing_episode" do
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ RSpec.describe "Admin::Podcasts", type: :request do
|
|||
description: "Super Podcast",
|
||||
feed_url: "http://feeds.feedburner.com/developertea",
|
||||
slug: "devtea",
|
||||
published: true,
|
||||
main_color_hex: "333333",
|
||||
image: Rack::Test::UploadedFile.new(image_file, "image/jpeg")
|
||||
}
|
||||
|
|
@ -31,5 +32,12 @@ RSpec.describe "Admin::Podcasts", type: :request do
|
|||
post "/admin/podcasts", params: { podcast: valid_attributes }
|
||||
end.to have_enqueued_job(Podcasts::GetEpisodesJob).exactly(:once)
|
||||
end
|
||||
|
||||
it "doesn't enqueue a job when creating an unpublished podcast" do
|
||||
valid_attributes[:published] = false
|
||||
expect do
|
||||
post "/admin/podcasts", params: { podcast: valid_attributes }
|
||||
end.not_to have_enqueued_job(Podcasts::GetEpisodesJob)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,5 +24,13 @@ RSpec.describe "PodcastShow", type: :request do
|
|||
expect(response.body).to include(CGI.escapeHTML("Bats' life"))
|
||||
expect(response.body).not_to include("Really old one")
|
||||
end
|
||||
|
||||
it "renders 404 when podcast is unpublished" do
|
||||
unpodcast = create(:podcast, reachable: true, published: false)
|
||||
create(:podcast_episode, reachable: true)
|
||||
expect do
|
||||
get "/#{unpodcast.slug}"
|
||||
end.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ require "rails_helper"
|
|||
RSpec.describe "User visits /pod page", type: :system do
|
||||
let!(:podcast_episode) { create(:podcast_episode) }
|
||||
let!(:podcast_episode2) { create(:podcast_episode) }
|
||||
let(:podcast) { create(:podcast, reachable: false) }
|
||||
let(:podcast) { create(:podcast, reachable: true, published: false) }
|
||||
let(:unpublished_podcast) { create(:podcast, reachable: false) }
|
||||
let!(:un_podcast_episode) { create(:podcast_episode, podcast: podcast, reachable: false) }
|
||||
let!(:unpublished_episode) { create(:podcast_episode, podcast: podcast) }
|
||||
|
||||
before { visit "/pod" }
|
||||
|
||||
|
|
@ -20,4 +22,10 @@ RSpec.describe "User visits /pod page", type: :system do
|
|||
expect(page).not_to have_link(nil, href: un_podcast_episode.path)
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't dsplay a podcast that is not published" do
|
||||
within "#articles-list" do
|
||||
expect(page).not_to have_link(nil, href: unpublished_episode.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue