From 2ef6f8b8cd344ba668e44cd1bf70fc12e542a761 Mon Sep 17 00:00:00 2001 From: Lucas Cimon Date: Sat, 21 Feb 2015 13:36:36 +0100 Subject: [PATCH] Adding Atom feed --- app/controllers/api/v1/places_controller.rb | 5 ++- app/views/api/v1/places/index.atom.builder | 37 +++++++++++++++++++ app/views/layouts/application.html.erb | 1 + config/locales/app.en.yml | 3 ++ config/locales/app.fr.yml | 3 ++ config/routes.rb | 1 + spec/factories/places.rb | 2 +- ...er_can_subscribe_to_the_place_feed_spec.rb | 32 ++++++++++++++++ spec/fixtures/csv/valid.csv | 2 +- 9 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 app/views/api/v1/places/index.atom.builder create mode 100644 spec/features/a_user_can_subscribe_to_the_place_feed_spec.rb diff --git a/app/controllers/api/v1/places_controller.rb b/app/controllers/api/v1/places_controller.rb index ada321d..2872ce8 100644 --- a/app/controllers/api/v1/places_controller.rb +++ b/app/controllers/api/v1/places_controller.rb @@ -1,6 +1,9 @@ class Api::V1::PlacesController < Api::V1::BaseController def index - render json: Place.displayable + respond_to do |format| + format.json { render json: Place.displayable } + format.atom { @places_items = Place.displayable.order('updated_at DESC') } + end end def show diff --git a/app/views/api/v1/places/index.atom.builder b/app/views/api/v1/places/index.atom.builder new file mode 100644 index 0000000..661560a --- /dev/null +++ b/app/views/api/v1/places/index.atom.builder @@ -0,0 +1,37 @@ +def place_to_html_description(place) + def format_entry(name, value) + i18n_name = I18n.t("simple_form.labels.place.#{name}") + displayed_value = (name == 'kind' ? I18n.t("kinds.codes.#{value}") : value) + "#{i18n_name} : #{displayed_value}" + end + text_entries = place.attributes + .slice('kind', 'street', 'zip_code', 'city', 'description', 'owner_name') + .reject { |k, v| v.nil? } + .map { |name, value| format_entry(name, value) } + twitname = place.twitter_name + twitter_entry = format_entry('twitter_name', "@#{twitname}") unless !twitname + url_entry = format_entry('url', "#{place.url}") unless !place.url + logo_img = "#{place.name} logo" unless !place.logo_url + direct_link = "#{I18n.t 'feed.link_to_map_marker'}" + [ + logo_img, + *text_entries, + url_entry, + twitter_entry, + direct_link, + ].compact.join '
' +end + +atom_feed language: (I18n.locale == :fr ? 'fr-FR' : 'en-US') do |feed| + feed.title I18n.t 'feed.title' + feed.updated @places_items.first.updated_at unless @places_items.empty? + @places_items.each do |place_item| + feed.entry( place_item ) do |entry| + entry.title place_item.name + entry.content place_to_html_description(place_item), type: 'html' + entry.author do |author| + author.name place_item.owner_name + end + end + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index fe0cf56..2f9e53c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -35,6 +35,7 @@ places_count = Place.displayable.count <%= stylesheet_link_tag 'application' %> <%= csrf_meta_tags %> + <%= auto_discovery_link_tag :atom, "/feed" %> diff --git a/config/locales/app.en.yml b/config/locales/app.en.yml index 60b7b61..fae8c93 100644 --- a/config/locales/app.en.yml +++ b/config/locales/app.en.yml @@ -62,3 +62,6 @@ en: owner_email: Your email place_update: <<: *place + feed: + title: Last added places + link_to_map_marker: Link to map marker diff --git a/config/locales/app.fr.yml b/config/locales/app.fr.yml index 818d6d0..cbb20d8 100644 --- a/config/locales/app.fr.yml +++ b/config/locales/app.fr.yml @@ -60,3 +60,6 @@ fr: owner_email: Votre adresse email place_update: <<: *place + feed: + title: Derniers lieux ajoutés + link_to_map_marker: Lien vers le marqueur sur la carte diff --git a/config/routes.rb b/config/routes.rb index 3d60fa9..269ae7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,5 +14,6 @@ end end + get '/feed', to: 'api/v1/places#index', defaults: { format: 'atom' } get '*path', to: 'places#index' end diff --git a/spec/factories/places.rb b/spec/factories/places.rb index ea79657..e5d5e67 100644 --- a/spec/factories/places.rb +++ b/spec/factories/places.rb @@ -1,6 +1,6 @@ FactoryGirl.define do factory :place do - name 'Craftsmen Angers' + sequence(:name) { |n| 'Craftsmen Angers #{n}' } kind Kind.codes.first state :pending url 'http://craftsmen.io' diff --git a/spec/features/a_user_can_subscribe_to_the_place_feed_spec.rb b/spec/features/a_user_can_subscribe_to_the_place_feed_spec.rb new file mode 100644 index 0000000..e923875 --- /dev/null +++ b/spec/features/a_user_can_subscribe_to_the_place_feed_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +feature 'A user view the places Atom feed' do + scenario 'there is a link to the map marker in the feed item description' do + create(:place, :active) + + visit '/feed' + + expect(find(:xpath, '//feed/entry[1]/content').text).to include(t('feed.link_to_map_marker')) + end + + scenario 'when several places exist, they have different "updated" times' do + create(:place, :active, updated_at: 3.days.ago) + create(:place, :active) + + visit '/feed' + + expect(find(:xpath, '//feed/entry[1]/updated').text).to_not eq(find(:xpath, '//feed/entry[2]/updated').text) + end + + scenario 'when several places exist, they are ordered chronologically' do + create(:place, :active, name: 'Newest place') + create(:place, :active, name: 'Another place', updated_at: 3.days.ago) + create(:place, :active, name: 'Oldest place', updated_at: 3.months.ago) + + visit '/feed' + + expect(find(:xpath, '//feed/entry[1]/title').text).to eq('Newest place') + expect(find(:xpath, '//feed/entry[2]/title').text).to eq('Another place') + expect(find(:xpath, '//feed/entry[3]/title').text).to eq('Oldest place') + end +end diff --git a/spec/fixtures/csv/valid.csv b/spec/fixtures/csv/valid.csv index a97d211..9ce7a26 100644 --- a/spec/fixtures/csv/valid.csv +++ b/spec/fixtures/csv/valid.csv @@ -1,2 +1,2 @@ name;kind;street;zip_code;city;url;latitude;longitude;twitter_name;logo_url;description;owner_name;owner_email -Craftsmen;company;25 rue Lenepveu;49000;Angers;http://craftsmen.io;47.472041;-0.551269;craftsmenhq;;;; +Craftsmen Angers;company;25 rue Lenepveu;49100;Angers;http://craftsmen.io;47.472041;-0.551269;craftsmenhq;https://pbs.twimg.com/profile_images/425256684244566016/N0wcdLyQ_400x400.jpeg;Webdesign studio;Sébastien Charrier;sebastien@craftsmen.io