Skip to content

Commit

Permalink
Create traces feed resource
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonKhorev committed Jan 18, 2025
1 parent 2626c76 commit 4f1eef8
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 127 deletions.
2 changes: 1 addition & 1 deletion app/abilities/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize(user)
can [:create, :update], :password
can :read, Redaction
can [:create, :destroy], :session
can [:read, :data, :georss], Trace
can [:read, :data], Trace
can [:read, :create, :suspended, :auth_success, :auth_failure], User
can :read, UserBlock
end
Expand Down
20 changes: 20 additions & 0 deletions app/controllers/traces/feeds_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Traces
class FeedsController < ApplicationController
before_action :authorize_web
before_action :set_locale
before_action :check_database_readable

authorize_resource :class => Trace

def show
@traces = Trace.visible_to_all.visible

@traces = @traces.joins(:user).where(:users => { :display_name => params[:display_name] }) if params[:display_name]

@traces = @traces.tagged(params[:tag]) if params[:tag]
@traces = @traces.order("timestamp DESC")
@traces = @traces.limit(20)
@traces = @traces.includes(:user)
end
end
end
13 changes: 1 addition & 12 deletions app/controllers/traces_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class TracesController < ApplicationController
include UserMethods
include PaginationMethods

layout "site", :except => :georss
layout "site"

before_action :authorize_web
before_action :set_locale
Expand Down Expand Up @@ -192,17 +192,6 @@ def data
head :not_found
end

def georss
@traces = Trace.visible_to_all.visible

@traces = @traces.joins(:user).where(:users => { :display_name => params[:display_name] }) if params[:display_name]

@traces = @traces.tagged(params[:tag]) if params[:tag]
@traces = @traces.order("timestamp DESC")
@traces = @traces.limit(20)
@traces = @traces.includes(:user)
end

private

def do_create(file, tags, description, visibility)
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ xml.rss("version" => "2.0",
xml.channel do
xml.title t(".title")
xml.description t(".title")
xml.link url_for(:controller => :traces, :action => :index, :only_path => false)
xml.link url_for(:controller => "/traces", :action => :index, :only_path => false)

xml.image do
xml.url image_url("mag_map-rss2.0.png")
xml.title t(".title")
xml.width 100
xml.height 100
xml.link url_for(:controller => :traces, :action => :index, :only_path => false)
xml.link url_for(:controller => "/traces", :action => :index, :only_path => false)
end

@traces.each do |trace|
Expand Down
15 changes: 8 additions & 7 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2616,13 +2616,14 @@ en:
offline:
heading: "GPX Storage Offline"
message: "The GPX file storage and upload system is currently unavailable."
georss:
title: "OpenStreetMap GPS Traces"
description:
description_with_count:
one: "GPX file with %{count} point from %{user}"
other: "GPX file with %{count} points from %{user}"
description_without_count: "GPX file from %{user}"
feeds:
show:
title: "OpenStreetMap GPS Traces"
description:
description_with_count:
one: "GPX file with %{count} point from %{user}"
other: "GPX file with %{count} points from %{user}"
description_without_count: "GPX file from %{user}"
application:
permission_denied: You do not have permission to access that action
require_cookies:
Expand Down
10 changes: 5 additions & 5 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,14 @@
get "/user/:display_name/traces/tag/:tag" => "traces#index"
get "/user/:display_name/traces/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/user/%{display_name}/traces")
get "/user/:display_name/traces" => "traces#index"
get "/user/:display_name/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
get "/user/:display_name/traces/rss" => "traces#georss", :defaults => { :format => :rss }
get "/user/:display_name/traces/:id" => "traces#show", :id => /\d+/, :as => "show_trace"
scope "/user/:display_name/traces/:trace_id", :trace_id => /\d+/, :module => :traces do
scope "/user/:display_name/traces/:trace_id", :module => :traces, :trace_id => /\d+/ do
get "picture" => "pictures#show", :as => "trace_picture"
get "icon" => "icons#show", :as => "trace_icon"
end
get "/traces/tag/:tag/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/tag/%{tag}")
get "/traces/tag/:tag" => "traces#index"
get "/traces/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces")
get "/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
get "/traces/rss" => "traces#georss", :defaults => { :format => :rss }
get "/traces/mine/tag/:tag/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/mine/tag/%{tag}")
get "/traces/mine/tag/:tag" => "traces#mine"
get "/traces/mine/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/mine")
Expand All @@ -236,6 +232,10 @@
get "/trace/:id/data" => "traces#data", :id => /\d+/, :as => "trace_data"
get "/trace/:id/edit", :id => /\d+/, :to => redirect(:path => "/traces/%{id}/edit")

namespace :traces, :path => "" do
resource :feed, :path => "(/user/:display_name)/traces(/tag/:tag)/rss", :only => :show, :defaults => { :format => :rss }
end

# diary pages
resources :diary_entries, :path => "diary", :only => [:new, :create, :index] do
collection do
Expand Down
109 changes: 109 additions & 0 deletions test/controllers/traces/feeds_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require "test_helper"

module Traces
class FeedsControllerTest < ActionDispatch::IntegrationTest
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/traces/rss", :method => :get },
{ :controller => "traces/feeds", :action => "show", :format => :rss }
)
assert_routing(
{ :path => "/traces/tag/tagname/rss", :method => :get },
{ :controller => "traces/feeds", :action => "show", :tag => "tagname", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/rss", :method => :get },
{ :controller => "traces/feeds", :action => "show", :display_name => "username", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/tag/tagname/rss", :method => :get },
{ :controller => "traces/feeds", :action => "show", :display_name => "username", :tag => "tagname", :format => :rss }
)
end

def test_show
user = create(:user)
# The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "Birmingham")
end
create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "Birmingham")
end

# First with the public feed
get traces_feed_path
check_trace_feed [trace_b, trace_a]

# Restrict traces to those with a given tag
get traces_feed_path(:tag => "London")
check_trace_feed [trace_a]
end

def test_show_user
user = create(:user)
second_user = create(:user)
create(:user)
create(:trace)
trace_b = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago, :user => user)
trace_c = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago, :user => user) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
create(:trace, :visibility => "private")

# Test a user with no traces
get traces_feed_path(:display_name => second_user)
check_trace_feed []

# Test the user with the traces - should see only public ones
get traces_feed_path(:display_name => user)
check_trace_feed [trace_c, trace_b]

# Should only see traces with the correct tag when a tag is specified
get traces_feed_path(:display_name => user, :tag => "London")
check_trace_feed [trace_c]

# Should no traces if the user does not exist
get traces_feed_path(:display_name => "UnknownUser")
check_trace_feed []
end

private

def check_trace_feed(traces)
assert_response :success
assert_template "traces/feeds/show"
assert_equal "application/rss+xml", @response.media_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "title"
assert_select "description"
assert_select "link"
assert_select "image"
assert_select "item", :count => traces.length do |items|
traces.zip(items).each do |trace, item|
assert_select item, "title", trace.name
assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
assert_select item, "description" do
assert_dom_encoded do
assert_select "img[src='#{trace_icon_url trace.user, trace}']"
end
end
# assert_select item, "dc:creator", trace.user.display_name
assert_select item, "pubDate", trace.timestamp.rfc822
end
end
end
end
end
end
end
100 changes: 0 additions & 100 deletions test/controllers/traces_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,6 @@ def test_routes
{ :controller => "traces", :action => "mine", :tag => "tagname" }
)

assert_routing(
{ :path => "/traces/rss", :method => :get },
{ :controller => "traces", :action => "georss", :format => :rss }
)
assert_routing(
{ :path => "/traces/tag/tagname/rss", :method => :get },
{ :controller => "traces", :action => "georss", :tag => "tagname", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/rss", :method => :get },
{ :controller => "traces", :action => "georss", :display_name => "username", :format => :rss }
)
assert_routing(
{ :path => "/user/username/traces/tag/tagname/rss", :method => :get },
{ :controller => "traces", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
)

assert_routing(
{ :path => "/user/username/traces/1", :method => :get },
{ :controller => "traces", :action => "show", :display_name => "username", :id => "1" }
Expand Down Expand Up @@ -333,61 +316,6 @@ def test_index_invalid_paged
end
end

# Check the RSS feed
def test_rss
user = create(:user)
# The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "Birmingham")
end
create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
create(:tracetag, :trace => trace, :tag => "Birmingham")
end

# First with the public feed
get traces_rss_path
check_trace_feed [trace_b, trace_a]

# Restrict traces to those with a given tag
get traces_rss_path(:tag => "London")
check_trace_feed [trace_a]
end

# Check the RSS feed for a specific user
def test_rss_user
user = create(:user)
second_user = create(:user)
create(:user)
create(:trace)
trace_b = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago, :user => user)
trace_c = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago, :user => user) do |trace|
create(:tracetag, :trace => trace, :tag => "London")
end
create(:trace, :visibility => "private")

# Test a user with no traces
get traces_rss_path(:display_name => second_user.display_name)
check_trace_feed []

# Test the user with the traces - should see only public ones
get traces_rss_path(:display_name => user.display_name)
check_trace_feed [trace_c, trace_b]

# Should only see traces with the correct tag when a tag is specified
get traces_rss_path(:display_name => user.display_name, :tag => "London")
check_trace_feed [trace_c]

# Should no traces if the user does not exist
get traces_rss_path(:display_name => "UnknownUser")
check_trace_feed []
end

# Test showing a trace
def test_show
public_trace_file = create(:trace, :visibility => "public")
Expand Down Expand Up @@ -721,34 +649,6 @@ def test_destroy

private

def check_trace_feed(traces)
assert_response :success
assert_template "georss"
assert_equal "application/rss+xml", @response.media_type
assert_select "rss", :count => 1 do
assert_select "channel", :count => 1 do
assert_select "title"
assert_select "description"
assert_select "link"
assert_select "image"
assert_select "item", :count => traces.length do |items|
traces.zip(items).each do |trace, item|
assert_select item, "title", trace.name
assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
assert_select item, "description" do
assert_dom_encoded do
assert_select "img[src='#{trace_icon_url trace.user, trace}']"
end
end
# assert_select item, "dc:creator", trace.user.display_name
assert_select item, "pubDate", trace.timestamp.rfc822
end
end
end
end
end

def check_trace_index(traces)
assert_response :success
assert_template "index"
Expand Down

0 comments on commit 4f1eef8

Please sign in to comment.