refinerycms-podcast 0.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/app/controllers/refinery/podcasts/admin/podcasts_controller.rb +24 -0
- data/app/controllers/refinery/podcasts/podcasts_controller.rb +39 -0
- data/app/models/refinery/podcasts/podcast.rb +41 -0
- data/app/views/refinery/podcasts/admin/podcasts/_actions.html.erb +23 -0
- data/app/views/refinery/podcasts/admin/podcasts/_form.html.erb +98 -0
- data/app/views/refinery/podcasts/admin/podcasts/_podcast.html.erb +22 -0
- data/app/views/refinery/podcasts/admin/podcasts/_podcasts.html.erb +2 -0
- data/app/views/refinery/podcasts/admin/podcasts/_records.html.erb +18 -0
- data/app/views/refinery/podcasts/admin/podcasts/_sortable_list.html.erb +5 -0
- data/app/views/refinery/podcasts/admin/podcasts/edit.html.erb +1 -0
- data/app/views/refinery/podcasts/admin/podcasts/index.html.erb +7 -0
- data/app/views/refinery/podcasts/admin/podcasts/new.html.erb +1 -0
- data/app/views/refinery/podcasts/podcasts/index.html.erb +11 -0
- data/app/views/refinery/podcasts/podcasts/index.rss.builder +71 -0
- data/app/views/refinery/podcasts/podcasts/show.html.erb +59 -0
- data/config/locales/cs.yml +34 -0
- data/config/locales/en.yml +32 -14
- data/config/locales/es.yml +35 -0
- data/config/locales/fr.yml +34 -0
- data/config/locales/nb.yml +34 -0
- data/config/locales/nl.yml +32 -14
- data/config/routes.rb +15 -6
- data/db/migrate/1_create_refinery_podcasts.rb +33 -0
- data/db/migrate/2_add_slug_to_refinery_podcasts.rb +8 -0
- data/db/migrate/3_add_image_id_to_refinery_podcasts.rb +8 -0
- data/db/seeds.rb +25 -0
- data/lib/generators/refinery/podcasts/podcasts_generator.rb +24 -0
- data/lib/generators/refinery/podcasts/templates/config/initializers/refinery/podcasts.rb.erb +47 -0
- data/lib/refinery/podcasts.rb +22 -0
- data/lib/refinery/podcasts/configuration.rb +20 -0
- data/lib/refinery/podcasts/engine.rb +22 -0
- data/lib/refinerycms-podcast.rb +1 -0
- data/lib/tasks/refinery/podcasts.rake +13 -0
- data/readme.md +10 -44
- metadata +125 -62
- data/app/controllers/admin/podcasts_controller.rb +0 -5
- data/app/controllers/podcasts_controller.rb +0 -12
- data/app/models/podcast.rb +0 -24
- data/app/views/admin/podcasts/_form.html.erb +0 -59
- data/app/views/admin/podcasts/_podcast.html.erb +0 -16
- data/app/views/admin/podcasts/edit.html.erb +0 -1
- data/app/views/admin/podcasts/index.html.erb +0 -34
- data/app/views/admin/podcasts/new.html.erb +0 -1
- data/app/views/podcasts/index.rss.builder +0 -56
- data/generators/podcast/podcast_generator.rb +0 -23
- data/generators/podcast/templates/migration.rb +0 -32
- data/lib/gemspec.rb +0 -30
- data/lib/refinery/podcast.rb +0 -15
- data/lib/tasks/podcast.rake +0 -35
- data/license.md +0 -21
- data/rails/init.rb +0 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4774257307552821fe14e0c6e1932c4ec1cdedd4
|
4
|
+
data.tar.gz: 15ea1c7a5502498c0139b6af0546d052a5e87696
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 14f58bcf61a371122544f1d9430aef8666feed39a6dc71cb2cb70ff07a36d57f66cf5f32b7369658fab226d90a09432026cba764cf1a614f22581ca61193301a
|
7
|
+
data.tar.gz: 5c81491cbbc2db8a672ed4cc72d3ff1ae3bb2c1203a0c202ae0cf87e41232e40671fef0803d5946bf02f6e205af1062253babdb44b31a659b496dd2c224d4f71
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Podcasts
|
3
|
+
module Admin
|
4
|
+
class PodcastsController < ::Refinery::AdminController
|
5
|
+
|
6
|
+
crudify :'refinery/podcasts/podcast', order: 'published_at DESC'
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def podcast_params
|
11
|
+
params.require(:podcast).permit(permitted_podcast_params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def permitted_podcast_params
|
15
|
+
[
|
16
|
+
:title, :author, :subtitle, :file_id, :image_id,
|
17
|
+
:published_at, :duration, :keywords, :summary, :position
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Podcasts
|
3
|
+
class PodcastsController < ::ApplicationController
|
4
|
+
|
5
|
+
before_filter :find_all_podcasts
|
6
|
+
before_filter :find_page
|
7
|
+
|
8
|
+
def index
|
9
|
+
respond_to do |format|
|
10
|
+
format.rss do
|
11
|
+
render :layout => false
|
12
|
+
end
|
13
|
+
format.html {
|
14
|
+
present @page
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
@podcast = Podcast.find params[:id]
|
21
|
+
|
22
|
+
# you can use meta fields from your model instead (e.g. browser_title)
|
23
|
+
# by swapping @page for @podcast in the line below:
|
24
|
+
present @page
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def find_all_podcasts
|
30
|
+
@podcasts = Podcast.order 'published_at DESC'
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_page
|
34
|
+
@page = ::Refinery::Page.where(:link_url => "/podcasts").first
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'acts_as_indexed'
|
2
|
+
require 'friendly_id'
|
3
|
+
|
4
|
+
module Refinery
|
5
|
+
module Podcasts
|
6
|
+
class Podcast < Refinery::Core::BaseModel
|
7
|
+
self.table_name = 'refinery_podcasts'
|
8
|
+
|
9
|
+
acts_as_indexed :fields => [:title, :author, :subtitle, :duration, :keywords, :summary]
|
10
|
+
|
11
|
+
validates :title, :presence => true, :uniqueness => true
|
12
|
+
|
13
|
+
belongs_to :file, :class_name => '::Refinery::Resource'
|
14
|
+
belongs_to :image, :class_name => '::Refinery::Image'
|
15
|
+
|
16
|
+
extend FriendlyId
|
17
|
+
|
18
|
+
friendly_id :title, :use => :slugged
|
19
|
+
|
20
|
+
def episode_number
|
21
|
+
self.class.order('published_at DESC').
|
22
|
+
where(self.class.arel_table[:id].lteq(self.id)).
|
23
|
+
count
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def default_scope
|
28
|
+
order "published_at DESC"
|
29
|
+
end
|
30
|
+
|
31
|
+
def published
|
32
|
+
where arel_table[:published_at].lteq(Date.today)
|
33
|
+
end
|
34
|
+
|
35
|
+
def latest(limit = 10)
|
36
|
+
published.limit limit
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<ul>
|
2
|
+
<% if ::Refinery::Podcasts::Admin::PodcastsController.searchable? %>
|
3
|
+
<li><%= render '/refinery/admin/search', url: refinery.admin_pages_path -%></li>
|
4
|
+
<% end %>
|
5
|
+
<li>
|
6
|
+
<%= link_to t('.create_new'), refinery.new_podcasts_admin_podcast_path,
|
7
|
+
:class => "add_icon" %>
|
8
|
+
</li>
|
9
|
+
<% if !searching? && ::Refinery::Podcasts::Admin::PodcastsController.sortable? && ::Refinery::Podcasts::Podcast.any? %>
|
10
|
+
<li>
|
11
|
+
<%= link_to t('.reorder', :what => "Podcasts"),
|
12
|
+
refinery.podcasts_admin_podcasts_path,
|
13
|
+
:id => "reorder_action",
|
14
|
+
:class => "reorder_icon" %>
|
15
|
+
|
16
|
+
<%= link_to t('.reorder_done', :what => "Podcasts"),
|
17
|
+
refinery.podcasts_admin_podcasts_path,
|
18
|
+
:id => "reorder_action_done",
|
19
|
+
:style => "display: none;",
|
20
|
+
:class => "reorder_icon" %>
|
21
|
+
</li>
|
22
|
+
<% end %>
|
23
|
+
</ul>
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<%= form_for [refinery, :podcasts_admin, @podcast] do |f| -%>
|
2
|
+
<%= render '/refinery/admin/error_messages',
|
3
|
+
:object => @podcast,
|
4
|
+
:include_object_name => true %>
|
5
|
+
|
6
|
+
<div class='field'>
|
7
|
+
<%= f.label :title -%>
|
8
|
+
<%= f.text_field :title, :class => 'larger widest' -%>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class='field'>
|
12
|
+
<%= f.label :subtitle -%>
|
13
|
+
<%= f.text_field :subtitle, :size => 100 -%>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class='field'>
|
17
|
+
<%= f.label :author -%>
|
18
|
+
<%= f.text_field :author -%>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class='field'>
|
22
|
+
<span class='label_with_help'>
|
23
|
+
<%= f.label :file_id, 'Podcast episode file' -%>
|
24
|
+
<%= refinery_help_tag "Supported file formats include .m4a, .mp3, .mov, .mp4, .m4v, and .pdf" %>
|
25
|
+
</span>
|
26
|
+
<%= render '/refinery/admin/resource_picker',
|
27
|
+
:f => f,
|
28
|
+
:field => :file_id,
|
29
|
+
:resource => @podcast.file,
|
30
|
+
:description => 'podcast' %>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div class="field">
|
34
|
+
<span class="label_with_help">
|
35
|
+
<%= f.label :image_id, "Podcast episode image" -%>
|
36
|
+
<%= refinery_help_tag "iTunes prefers square .jpg or .png images that are between 1400 x 1400 pixels and 3000 x 3000 pixels" %>
|
37
|
+
</span>
|
38
|
+
<%= render :partial => "/refinery/admin/image_picker", :locals => {
|
39
|
+
:f => f,
|
40
|
+
:field => :image_id,
|
41
|
+
:image => @podcast.image,
|
42
|
+
:toggle_image_display => false
|
43
|
+
} %>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div class='field'>
|
47
|
+
<%= f.label :published_at -%>
|
48
|
+
<%= f.date_select :published_at -%>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div class='field'>
|
52
|
+
<span class='label_with_help'>
|
53
|
+
<%= f.label :duration -%>
|
54
|
+
<%= refinery_help_tag "In HH:MM:SS format. E.g. \"10:22\" for 10 minutes 22 seconds" %>
|
55
|
+
</span>
|
56
|
+
<%= f.text_field :duration, :size => 6 -%>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<div class='field'>
|
60
|
+
<span class='label_with_help'>
|
61
|
+
<%= f.label :keywords -%>
|
62
|
+
<%= refinery_help_tag "Up to 12 keywords separated by commas. <br/><br/>E.g. rails, ruby on rails, refinerycms, refinery. <br/><br/>According to iTunes, the best use for keywords is to include common misspellings of your name or title, to ensure your podcast is still searchable despite a misspelling. To prevent keyword abuse, iTunes indexes only the first 12 keywords found in this tag." %>
|
63
|
+
</span>
|
64
|
+
<%= f.text_field :keywords, :size => 100 -%><br/>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div class='field'>
|
68
|
+
<div id='page-tabs' class='clearfix ui-tabs ui-widget ui-widget-content ui-corner-all'>
|
69
|
+
<ul id='page_parts'>
|
70
|
+
<% [:summary].each_with_index do |part, part_index| %>
|
71
|
+
<li class='ui-state-default<%= ' ui-state-active' if part_index == 0 %>'>
|
72
|
+
<%= link_to t("#{part}", :scope => "activerecord.attributes.refinery/podcasts/podcast", :default => part.to_s.titleize), "##{part}" %>
|
73
|
+
</li>
|
74
|
+
<% end %>
|
75
|
+
</ul>
|
76
|
+
<div id='page_part_editors'>
|
77
|
+
<% [:summary].each do |part| %>
|
78
|
+
<div class='page_part' id='<%= part %>'>
|
79
|
+
<%= f.text_area part, :rows => 20, :class => 'wymeditor widest' -%>
|
80
|
+
</div>
|
81
|
+
<% end %>
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<%= render '/refinery/admin/form_actions', :f => f,
|
88
|
+
:continue_editing => false,
|
89
|
+
:delete_title => t('delete', :scope => 'refinery.podcasts.admin.podcasts.podcast'),
|
90
|
+
:delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @podcast.title) %>
|
91
|
+
<% end -%>
|
92
|
+
<% content_for :javascripts do %>
|
93
|
+
<script>
|
94
|
+
$(document).ready(function(){
|
95
|
+
page_options.init(false, '', '');
|
96
|
+
});
|
97
|
+
</script>
|
98
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<li class='clearfix record <%= cycle("on", "on-hover") %>' id="<%= dom_id(podcast) -%>">
|
2
|
+
<span class='title'>
|
3
|
+
#<%= podcast.episode_number %> <%= podcast.title %>
|
4
|
+
<span class="preview">- <%= truncate(podcast.subtitle, :length => 50) %></span>
|
5
|
+
</span>
|
6
|
+
<span class='actions'>
|
7
|
+
|
8
|
+
<%= link_to refinery_icon_tag("application_go.png"), refinery.podcasts_podcast_path(podcast),
|
9
|
+
:title => t('.view_live_html'),
|
10
|
+
:target => "_blank" %>
|
11
|
+
|
12
|
+
<%= link_to refinery_icon_tag("application_edit.png"), refinery.edit_podcasts_admin_podcast_path(podcast),
|
13
|
+
:title => t('.edit') %>
|
14
|
+
<%= link_to refinery_icon_tag("delete.png"), refinery.podcasts_admin_podcast_path(podcast),
|
15
|
+
:class => "cancel confirm-delete",
|
16
|
+
:title => t('.delete'),
|
17
|
+
:data => {
|
18
|
+
:confirm => t('message', :scope => 'refinery.admin.delete', :title => podcast.title)
|
19
|
+
},
|
20
|
+
:method => :delete %>
|
21
|
+
</span>
|
22
|
+
</li>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% if searching? %>
|
2
|
+
<h2><%= t('results_for', :scope => 'refinery.admin.search', :query => params[:search]) %></h2>
|
3
|
+
<% end %>
|
4
|
+
<div class='pagination_container'>
|
5
|
+
<% if @podcasts.any? %>
|
6
|
+
<%= render 'podcasts' %>
|
7
|
+
<% else %>
|
8
|
+
<p>
|
9
|
+
<% unless searching? %>
|
10
|
+
<strong>
|
11
|
+
<%= t('.no_items_yet') %>
|
12
|
+
</strong>
|
13
|
+
<% else %>
|
14
|
+
<%= t('no_results', :scope => 'refinery.admin.search') %>
|
15
|
+
<% end %>
|
16
|
+
</p>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'form' %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<section id='records'>
|
2
|
+
<%= render 'records' %>
|
3
|
+
</section>
|
4
|
+
<aside id='actions'>
|
5
|
+
<%= render 'actions' %>
|
6
|
+
</aside>
|
7
|
+
<%= render '/refinery/admin/make_sortable', :tree => false if !searching? and ::Refinery::Podcasts::Admin::PodcastsController.sortable? and ::Refinery::Podcasts::Podcast.count > 1 %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'form' %>
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'uri' # used for URI.encode
|
2
|
+
xml.instruct!
|
3
|
+
|
4
|
+
xml.rss 'xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd', :version => '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom' do
|
5
|
+
xml.channel do
|
6
|
+
# Points to your website (e.g. http://yoursite.com/)
|
7
|
+
base_url = request.protocol + request.host_with_port
|
8
|
+
|
9
|
+
# NOTE: Fill in everything with your own data down to the categories.
|
10
|
+
xml.title Refinery::Podcasts.title
|
11
|
+
|
12
|
+
# Points to your website (e.g. http://yoursite.com/)
|
13
|
+
xml.link base_url
|
14
|
+
|
15
|
+
# Points to your podcast feed (e.g. http://yoursite.com/podcasts.rss)
|
16
|
+
xml.tag!('atom:link', :href => refinery.podcasts_podcasts_url(format: :rss), :rel => 'self', :type => 'application/rss+xml')
|
17
|
+
|
18
|
+
# Accepted values are those in the ISO 639-1 Alpha-2 list (two-letter language codes, some with possible modifiers, such as 'en-us').
|
19
|
+
xml.language Refinery::Podcasts.language
|
20
|
+
|
21
|
+
xml.copyright "© #{Time.now.year} #{Refinery::Core.site_name}"
|
22
|
+
xml.tag!('itunes:subtitle', Refinery::Podcasts.subtitle)
|
23
|
+
|
24
|
+
# The content of this tag is shown in the Artist column in iTunes.
|
25
|
+
xml.tag!('itunes:author', Refinery::Podcasts.author)
|
26
|
+
|
27
|
+
# This tag should be used to indicate whether or not your podcast contains
|
28
|
+
# explicit material. The three values for this tag are "yes", "no", and "clean".
|
29
|
+
xml.tag!('itunes:explicit', Refinery::Podcasts.explicit_content)
|
30
|
+
|
31
|
+
# The contents of this tag are shown in a separate window that appears when the
|
32
|
+
# "circled i" in the Description column is clicked. It also appears on the iTunes
|
33
|
+
# page for your podcast. This field can be up to 4000 characters.
|
34
|
+
xml.tag!('itunes:summary', Refinery::Podcasts.description)
|
35
|
+
xml.description Refinery::Podcasts.description
|
36
|
+
|
37
|
+
# This tag contains information that will be used to contact the owner of the podcast
|
38
|
+
# for communication specifically about their podcast. It will not be publicly displayed.
|
39
|
+
xml.tag!('itunes:owner') do |owner|
|
40
|
+
xml.tag!('itunes:name', Refinery::Podcasts.owner_name)
|
41
|
+
xml.tag!('itunes:email', Refinery::Podcasts.owner_email)
|
42
|
+
end
|
43
|
+
|
44
|
+
# upload an image to your resources tab and link it in here
|
45
|
+
# iTunes prefers square .jpg or .png images that are between
|
46
|
+
# 1400 x 1400 pixels and 3000 x 3000 pixels
|
47
|
+
xml.tag!('itunes:image', :href => Refinery::Podcasts.image_url)
|
48
|
+
|
49
|
+
# select from the list of categories here:
|
50
|
+
# https://help.apple.com/itc/podcasts_connect/?lang=en#/itc9267a2f12
|
51
|
+
xml.tag!('itunes:category', :text => Refinery::Podcasts.category) do |node|
|
52
|
+
xml.tag!('itunes:category', :text => Refinery::Podcasts.subcategory)
|
53
|
+
end
|
54
|
+
|
55
|
+
@podcasts.each do |item|
|
56
|
+
item_url = request.protocol + request.host_with_port + item.file.url
|
57
|
+
xml.item do
|
58
|
+
xml.title item.title
|
59
|
+
xml.tag!('itunes:author', item.author)
|
60
|
+
xml.tag!('itunes:subtitle', item.subtitle)
|
61
|
+
xml.tag!('itunes:summary', strip_tags(item.summary))
|
62
|
+
xml.enclosure :url => item_url, :length => item.file.size, :type => item.file.file_mime_type
|
63
|
+
xml.guid item_url
|
64
|
+
xml.tag!('pubDate', item.published_at.to_time.rfc2822)
|
65
|
+
xml.tag!('itunes:duration', item.duration)
|
66
|
+
xml.tag!('itunes:keywords', item.keywords)
|
67
|
+
xml.tag!('itunes:explicit', Refinery::Podcasts.explicit_content)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<% content_for :body_content_title do %>
|
2
|
+
<%= @podcast.title %>: <%= @podcast.subtitle %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :body do %>
|
6
|
+
<section>
|
7
|
+
<h1>Author</h1>
|
8
|
+
<p>
|
9
|
+
<%=raw @podcast.author %>
|
10
|
+
</p>
|
11
|
+
</section>
|
12
|
+
<% if @podcast.file.present? %>
|
13
|
+
<section>
|
14
|
+
<h1>Listen Now</h1>
|
15
|
+
<p>
|
16
|
+
<%= link_to 'listen now', @podcast.file.url %>
|
17
|
+
</p>
|
18
|
+
</section>
|
19
|
+
<% end %>
|
20
|
+
<section>
|
21
|
+
<h1>Published At</h1>
|
22
|
+
<p>
|
23
|
+
<%=raw @podcast.published_at %>
|
24
|
+
</p>
|
25
|
+
</section>
|
26
|
+
<section>
|
27
|
+
<h1>Duration</h1>
|
28
|
+
<p>
|
29
|
+
<%=raw @podcast.duration %>
|
30
|
+
</p>
|
31
|
+
</section>
|
32
|
+
<section>
|
33
|
+
<h1>Keywords</h1>
|
34
|
+
<p>
|
35
|
+
<%=raw @podcast.keywords %>
|
36
|
+
</p>
|
37
|
+
</section>
|
38
|
+
<section>
|
39
|
+
<h1>Summary</h1>
|
40
|
+
<p>
|
41
|
+
<%=raw @podcast.summary %>
|
42
|
+
</p>
|
43
|
+
</section>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<% content_for :side_body do %>
|
47
|
+
<aside>
|
48
|
+
<h2><%= t('.other') %></h2>
|
49
|
+
<ul id="podcasts">
|
50
|
+
<% @podcasts.each do |podcast| %>
|
51
|
+
<li>
|
52
|
+
<%= link_to podcast.title, refinery.podcasts_podcast_path(podcast) %>
|
53
|
+
</li>
|
54
|
+
<% end %>
|
55
|
+
</ul>
|
56
|
+
</aside>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<%= render '/refinery/content_page' %>
|