From b94de9fe8c30210469953bbd9880e9cbcc7a3ef5 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 27 Jun 2026 23:19:22 +0200 Subject: rss: add per-tag Atom feed at /rss/tags/:tag/updates.xml - rss#tag_updates action: filters Page.heads by tag name, default locale, 20 items, same caching as updates feed - tag_updates.xml.builder: Atom feed with CGI.escapeHTML on title and summary, consistent with updates.xml.builder - tags/show.html.erb: add subscription link above article list - routes: two routes per existing pattern (format-less + .:format constrained to /xml/) --- app/controllers/rss_controller.rb | 18 ++++++++++++++++++ app/views/rss/tag_updates.xml.builder | 27 +++++++++++++++++++++++++++ app/views/tags/show.html.erb | 6 ++++++ 3 files changed, 51 insertions(+) create mode 100644 app/views/rss/tag_updates.xml.builder (limited to 'app') diff --git a/app/controllers/rss_controller.rb b/app/controllers/rss_controller.rb index 4b47218..489a732 100644 --- a/app/controllers/rss_controller.rb +++ b/app/controllers/rss_controller.rb @@ -22,6 +22,24 @@ class RssController < ApplicationController end end + def tag_updates + expires_in 31.minutes, :public => true + + I18n.locale = I18n.default_locale + @tag = params[:tag] + @items = Page.heads + .joins("JOIN taggings ON taggings.taggable_id = pages.id + AND taggings.taggable_type = 'Page' + AND taggings.context = 'tags'") + .joins("JOIN tags ON tags.id = taggings.tag_id") + .where("LOWER(tags.name) = ?", @tag.downcase) + .order("published_at DESC").limit(20) + + respond_to do |format| + format.xml {} + end + end + def recent_changes @items = Page.where( "updated_at < ? AND updated_at > ?", Time.now, Time.now - 14.days diff --git a/app/views/rss/tag_updates.xml.builder b/app/views/rss/tag_updates.xml.builder new file mode 100644 index 0000000..6491cfc --- /dev/null +++ b/app/views/rss/tag_updates.xml.builder @@ -0,0 +1,27 @@ +xml.instruct! + +xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do + xml.title("Chaos Computer Club: #{@tag}") + xml.link(:href => "#{@host}/") + xml.link(:rel => "self", :href => "#{@host}/rss/tags/#{@tag}/updates.xml") + xml.updated(@items.first.published_at.xmlschema) unless @items.empty? + xml.author do + xml.name("Chaos Computer Club e. V.") + end + xml.id("#{@host}/rss/tags/#{@tag}/updates") + + @items.each do |item| + xml.entry do + xml.title(CGI.escapeHTML(item.title.to_s)) + xml.link( + :href => content_url(:page_path => item.node.unique_path), + :rel => "alternate", + :type => "text/html" + ) + xml.id(content_url(:page_path => item.node.feed_id)) + xml.updated(item.updated_at.xmlschema) + xml.published(item.published_at.xmlschema) + xml.summary(CGI.escapeHTML(item.abstract.to_s)) + end + end +end diff --git a/app/views/tags/show.html.erb b/app/views/tags/show.html.erb index b09cc15..3a23522 100644 --- a/app/views/tags/show.html.erb +++ b/app/views/tags/show.html.erb @@ -1,5 +1,11 @@

<%= t(:show_tag_headline) %> »<%=h @tag %>«

+ + <%= render( :partial => 'custom/partials/no_date_and_author', -- cgit v1.3