Podcasts reachable status #2952 (#3341)

* Podcasts reachable status #2952

* Specs for podcasts statuses
This commit is contained in:
Anna Buianova 2019-07-02 16:18:27 +03:00 committed by Ben Halpern
parent 1923b4230d
commit d6a151703c
17 changed files with 109 additions and 20 deletions

View file

@ -47,6 +47,7 @@ Rails/OutputSafety:
- 'app/models/message.rb'
- 'app/views/api/v0/articles/show.json.jbuilder'
- 'app/views/articles/feed.rss.builder'
- 'app/views/podcast_episodes/show.html.erb'
# Offense count: 17
# Cop supports --auto-correct.

View file

@ -4,8 +4,8 @@ class PodcastEpisodesController < ApplicationController
def index
@podcast_index = true
@podcasts = Podcast.order("title asc")
@podcast_episodes = PodcastEpisode.includes(:podcast).order("published_at desc").first(20)
@podcasts = Podcast.reachable.order("title asc")
@podcast_episodes = PodcastEpisode.includes(:podcast).where(podcasts: { reachable: true }).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"] })

View file

@ -23,7 +23,7 @@ class StoriesController < ApplicationController
elsif (@article = Article.find_by(slug: params[:slug])&.decorate)
handle_possible_redirect
else
@podcast = Podcast.find_by(slug: params[:username]) || not_found
@podcast = Podcast.reachable.find_by(slug: params[:username]) || not_found
@episode = PodcastEpisode.find_by(slug: params[:slug]) || not_found
handle_podcast_show
end
@ -64,7 +64,7 @@ class StoriesController < ApplicationController
end
def handle_user_or_organization_or_podcast_or_page_index
@podcast = Podcast.find_by(slug: params[:username].downcase)
@podcast = Podcast.reachable.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

View file

@ -23,6 +23,7 @@ class PodcastDashboard < Administrate::BaseDashboard
image: CarrierwaveField,
pattern_image: CarrierwaveField,
slug: Field::String,
reachable: Field::Boolean,
status_notice: Field::Text,
created_at: Field::DateTime,
updated_at: Field::DateTime
@ -36,6 +37,8 @@ class PodcastDashboard < Administrate::BaseDashboard
COLLECTION_ATTRIBUTES = %i[
podcast_episodes
id
reachable
status_notice
title
description
].freeze
@ -59,6 +62,7 @@ class PodcastDashboard < Administrate::BaseDashboard
image
pattern_image
slug
reachable
created_at
updated_at
].freeze
@ -82,6 +86,7 @@ class PodcastDashboard < Administrate::BaseDashboard
main_color_hex
image
slug
reachable
].freeze
# Overwrite this method to customize how podcasts are displayed

View file

@ -15,6 +15,8 @@ class Podcast < ApplicationRecord
after_save :bust_cache
scope :reachable, -> { where(reachable: true) }
alias_attribute :path, :slug
alias_attribute :profile_image_url, :image_url
alias_attribute :name, :title

View file

@ -43,7 +43,7 @@ module Podcasts
rescue StandardError
# podcast episode must have a media_url
episode.media_url = item.enclosure.url
episode.podcast.update(status_notice: "This podcast may not be playable in the browser") if episode.podcast.status_notice.empty?
episode.podcast.update(status_notice: I18n.t(:unplayable, scope: "podcasts.statuses")) if episode.podcast.status_notice.empty?
end
end
end

View file

@ -6,13 +6,25 @@ module Podcasts
def get_episodes(podcast, num = 1000)
rss = HTTParty.get(podcast.feed_url).body
feed = RSS::Parser.parse(rss, false)
set_unreachable(podcast, :unparsable) && return unless feed
get_episode = Podcasts::GetEpisode.new(podcast)
feed.items.first(num).each do |item|
get_episode.call(item)
end
podcast.update_columns(reachable: true, status_notice: "")
feed.items.size
rescue StandardError => e
Rails.logger.error(e)
rescue Net::OpenTimeout, Errno::ECONNREFUSED => _e
set_unreachable(podcast, :unreachable)
rescue RSS::NotWellFormedError => _e
set_unreachable(podcast, :unparsable)
end
private
def set_unreachable(podcast, status = :unreachable)
podcast.update_columns(reachable: false, status_notice: I18n.t(status, scope: "podcasts.statuses"))
end
end
end

View file

@ -72,7 +72,8 @@
</div>
</div>
</div>
<% if !@episode.podcast.status_notice.empty? %>
<%# temp, until podcast_episode statuses are introduced %>
<% if @episode.podcast.status_notice.to_s.include?("may not be playable") %>
<center>
<h1 style="color: #e05252;">
<%= @episode.podcast.status_notice %>

View file

@ -45,3 +45,8 @@ en:
administrate:
actions:
new: 'New'
podcasts:
statuses:
unreachable: Podcast's feed_url is not reachable
unparsable: Podcast's rss couldn't be parsed
unplayable: This podcast may not be playable in the browser

View file

@ -0,0 +1,5 @@
class AddReachableToPodcasts < ActiveRecord::Migration[5.2]
def change
add_column :podcasts, :reachable, :boolean, default: true
end
end

View file

@ -12,7 +12,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_06_26_022355) do
ActiveRecord::Schema.define(version: 2019_06_28_123548) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -667,6 +667,7 @@ ActiveRecord::Schema.define(version: 2019_06_26_022355) do
t.string "main_color_hex", null: false
t.string "overcast_url"
t.string "pattern_image"
t.boolean "reachable", default: true
t.string "slug", null: false
t.string "soundcloud_url"
t.text "status_notice", default: ""

View file

@ -0,0 +1,19 @@
require "rails_helper"
RSpec.describe "PodcastShow", type: :request do
describe "GET podcast show" do
it "renders 404 for an unreachable podcast" do
podcast = create(:podcast, reachable: false)
expect do
get "/#{podcast.slug}"
end.to raise_error(ActiveRecord::RecordNotFound)
end
it "renders ok" do
podcast = create(:podcast)
create(:podcast_episode, podcast: podcast)
get "/#{podcast.slug}"
expect(response).to have_http_status(:ok)
end
end
end

View file

@ -13,6 +13,27 @@ RSpec.describe Podcasts::Feed, vcr: vcr_option do
podcast
end
context "when unreachable" do
let(:un_feed_url) { "http://podcast.example.com/podcast" }
let(:unpodcast) { create(:podcast, feed_url: un_feed_url) }
it "sets reachable and status" do
stub_request(:get, "http://podcast.example.com/podcast").to_return(status: 200, body: "blah")
described_class.new.get_episodes(unpodcast, 2)
unpodcast.reload
expect(unpodcast.reachable).to be false
expect(unpodcast.status_notice).to include("rss couldn't be parsed")
end
it "sets reachable" do
allow(HTTParty).to receive(:get).with("http://podcast.example.com/podcast").and_raise(Errno::ECONNREFUSED)
described_class.new.get_episodes(unpodcast, 2)
unpodcast.reload
expect(unpodcast.reachable).to be false
expect(unpodcast.status_notice).to include("is not reachable")
end
end
context "when creating" do
before do
stub_request(:head, "https://traffic.libsyn.com/sedaily/AnalyseAsia.mp3").to_return(status: 200)

View file

@ -17,6 +17,26 @@ RSpec.describe "User visits podcast show page", type: :system do
expect(find("#comment_commentable_id", visible: false).value).to eq(podcast_episode.id.to_s)
end
context "when podcast has a status_notice" do
let(:podcast) { create(:podcast, status_notice: "This podcast may not be playable in the browser") }
let!(:podcast_episode) { create(:podcast_episode, podcast_id: podcast.id) }
it "displays the status_notice" do
visit podcast_episode.path.to_s
expect(page).to have_text(podcast.status_notice)
end
end
context "when podcast has another status_notice (just in case)" do
let(:podcast) { create(:podcast, status_notice: "Random status notice") }
let!(:podcast_episode) { create(:podcast_episode, podcast_id: podcast.id) }
it "doesn't display status_notice" do
visit podcast_episode.path.to_s
expect(page).not_to have_text("Random status notice")
end
end
context "when there're existing comments" do
let(:user) { create(:user) }
let(:comment) { create(:comment, user_id: user.id, commentable: podcast_episode) }

View file

@ -1,11 +0,0 @@
# require 'rails_helper'
#
# feature 'User visits podcast index page' do
# scenario 'they see the foobar on the page' do
# visit "/pod"
#
# fill_in 'Name', with: 'My foobar'
# click_button 'Create Foobar'
# expect(page).to have_css '.foobar-name', 'My foobar'
# end
# end

View file

@ -3,6 +3,8 @@ 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!(:un_podcast_episode) { create(:podcast_episode, podcast: podcast) }
before { visit "/pod" }
@ -12,4 +14,10 @@ RSpec.describe "User visits /pod page", type: :system do
expect(page).to have_link(nil, href: podcast_episode2.path)
end
end
it "doesn't display an unreachable podcast" do
within "#articles-list" do
expect(page).not_to have_link(nil, href: un_podcast_episode.path)
end
end
end