From fd240c19676ae1ea091a69df365cffd8cc6907a8 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 27 Feb 2013 19:36:12 -0800 Subject: [PATCH] RSS for topics in a category Creates a new route for category RSS --- app/controllers/list_controller.rb | 17 +++++++++++++---- app/models/topic.rb | 2 ++ app/views/list/list.erb | 8 +++++++- app/views/list/list.rss.erb | 23 +++++++++++++++++++++++ app/views/topics/show.html.erb | 2 +- config/locales/server.en.yml | 5 ++++- config/routes.rb | 7 ++++--- lib/topic_query.rb | 4 ++++ spec/components/topic_query_spec.rb | 6 ++++++ spec/controllers/list_controller_spec.rb | 10 ++++++++-- spec/models/topic_spec.rb | 13 +++++++++++++ 11 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 app/views/list/list.rss.erb diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index 428942617..3de4a30ac 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -1,6 +1,6 @@ class ListController < ApplicationController - before_filter :ensure_logged_in, except: [:index, :category] + before_filter :ensure_logged_in, except: [:index, :category, :category_feed] skip_before_filter :check_xhr # Create our filters @@ -38,15 +38,24 @@ class ListController < ApplicationController if params[:category] == Slug.for(SiteSetting.uncategorized_name) or params[:category] == SiteSetting.uncategorized_name list = query.list_uncategorized else - category = Category.where("slug = ? or id = ?", params[:category], params[:category].to_i).includes(:featured_users).first - guardian.ensure_can_see!(category) - list = query.list_category(category) + @category = Category.where("slug = ? or id = ?", params[:category], params[:category].to_i).includes(:featured_users).first + guardian.ensure_can_see!(@category) + list = query.list_category(@category) end list.more_topics_url = url_for(category_path(params[:category], page: next_page, format: "json")) respond(list) end + def category_feed + raise Discourse::InvalidParameters.new('Category RSS of "uncategorized"') if params[:category] == Slug.for(SiteSetting.uncategorized_name) || params[:category] == SiteSetting.uncategorized_name + + @category = Category.where("slug = ?", params[:category]).includes(:featured_users).first + guardian.ensure_can_see!(@category) + @topic_list = TopicQuery.new.list_new_in_category(@category) + render 'list', formats: [:rss] + end + protected diff --git a/app/models/topic.rb b/app/models/topic.rb index 48806770e..53adaad83 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -60,6 +60,8 @@ class Topic < ActiveRecord::Base scope :listable_topics, lambda { where('topics.archetype <> ?', [Archetype.private_message]) } + scope :by_newest, order('created_at desc, id desc') + # Helps us limit how many favorites can be made in a day class FavoriteLimiter < RateLimiter def initialize(user) diff --git a/app/views/list/list.erb b/app/views/list/list.erb index f05621752..e9e9dc96a 100644 --- a/app/views/list/list.erb +++ b/app/views/list/list.erb @@ -8,4 +8,10 @@

<%= t 'next_page'%>

<% end %> -

<%= t 'powered_by' %>

\ No newline at end of file +

<%= t 'powered_by' %>

+ +<% if @category %> + <% content_for :head do %> + <%= auto_discovery_link_tag(@category, {action: :category_feed, format: :rss}, title: t('rss_topics_in_category', category: @category.name), type: 'application/rss+xml') %> + <% end %> +<% end %> diff --git a/app/views/list/list.rss.erb b/app/views/list/list.rss.erb new file mode 100644 index 000000000..f966db9bf --- /dev/null +++ b/app/views/list/list.rss.erb @@ -0,0 +1,23 @@ + + + + <%= @category.name %> + <%= Discourse.base_url %>/category/<%= @category.slug %>.rss + <%= t 'topics_in_category', category: @category.name %><%= @category.description %> + + <% @topic_list.topics.each do |topic| %> + + <%= topic.title %> + <%= pluralize(topic.posts_count, 'post') %>

+

<%= t 'author_wrote', author: topic.posts.first.author_readable %>

+ <%= topic.posts.first.cooked.html_safe %> + ]]>
+ <%= Discourse.base_url %><%= topic.relative_url %> + <%= topic.created_at.rfc2822 %> + <%= Discourse.base_url %><%= topic.relative_url %> + <%= topic.title %> +
+ <% end %> +
+
diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb index 124d818d1..9339a92bb 100644 --- a/app/views/topics/show.html.erb +++ b/app/views/topics/show.html.erb @@ -23,5 +23,5 @@

<%= t 'powered_by' %>

<% content_for :head do %> - <%= auto_discovery_link_tag(@topic_view, {action: :feed, format: :rss}, title: t('rss_feed', topic: @topic_view.title), type: 'application/rss+xml') %> + <%= auto_discovery_link_tag(@topic_view, {action: :feed, format: :rss}, title: t('rss_posts_in_topic', topic: @topic_view.title), type: 'application/rss+xml') %> <% end %> diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 9c2433324..baa576f8b 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -15,7 +15,10 @@ en: is_invalid: "is invalid; try to be a little more descriptive" next_page: "next page →" by: "By" - rss_feed: "RSS feed of %{topic}" + topics_in_category: "Topics in the '%{category}' category" + rss_posts_in_topic: "RSS feed of '%{topic}'" + rss_topics_in_category: "RSS feed of topics in the '%{category}' category" + author_wrote: "%{author} wrote:" education: until_posts: diff --git a/config/routes.rb b/config/routes.rb index c78878ed1..3693bf644 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -137,10 +137,13 @@ Discourse::Application.routes.draw do resources :user_actions resources :education + get 'category/:category.rss' => 'list#category_feed', format: :rss, as: 'category_feed' get 'category/:category' => 'list#category' + get 'category/:category' => 'list#category', as: 'category' + get 'category/:category/more' => 'list#category', as: 'category' + get 'categories' => 'categories#index' get 'popular' => 'list#index' get 'popular/more' => 'list#index' - get 'categories' => 'categories#index' get 'favorited' => 'list#favorited' get 'favorited/more' => 'list#favorited' get 'read' => 'list#read' @@ -151,8 +154,6 @@ Discourse::Application.routes.draw do get 'new/more' => 'list#new' get 'posted' => 'list#posted' get 'posted/more' => 'list#posted' - get 'category/:category' => 'list#category', as: 'category' - get 'category/:category/more' => 'list#category', as: 'category' get 'search' => 'search#query' diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 8f2280ba1..468f975ee 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -114,6 +114,10 @@ class TopicQuery new_results(limit: false).count end + def list_new_in_category(category) + return_list {|l| l.where(category_id: category.id).by_newest.first(25)} + end + protected def return_list(list_opts={}) diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 5661a69a5..2f5ea43e1 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -51,6 +51,12 @@ describe TopicQuery do it "returns nothing when filtering by another category" do topic_query.list_category(Fabricate(:category, name: 'new cat')).topics.should be_blank end + + describe '#list_new_in_category' do + it 'returns only the categorized topic' do + topic_query.list_new_in_category(category).topics.should == [topic_in_cat] + end + end end context 'unread / read topics' do diff --git a/spec/controllers/list_controller_spec.rb b/spec/controllers/list_controller_spec.rb index d349e006d..ab711016b 100644 --- a/spec/controllers/list_controller_spec.rb +++ b/spec/controllers/list_controller_spec.rb @@ -43,6 +43,14 @@ describe ListController do it { should respond_with(:success) } end + describe 'feed' do + it 'renders RSS' do + get :category_feed, category: category.slug, format: :rss + response.should be_success + response.content_type.should == 'application/rss+xml' + end + end + end context 'uncategorized' do @@ -59,8 +67,6 @@ describe ListController do end - - end context 'favorited' do diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index 962d2873d..38782aca0 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -1033,4 +1033,17 @@ describe Topic do end + describe 'scopes' do + describe '#by_most_recently_created' do + it 'returns topics ordered by created_at desc, id desc' do + now = Time.now + a = Fabricate(:topic, created_at: now - 2.minutes) + b = Fabricate(:topic, created_at: now) + c = Fabricate(:topic, created_at: now) + d = Fabricate(:topic, created_at: now - 2.minutes) + Topic.by_newest.should == [c,b,d,a] + end + end + end + end