diff --git a/app/controllers/places_controller.rb b/app/controllers/places_controller.rb index 7376ff9..9ce1deb 100644 --- a/app/controllers/places_controller.rb +++ b/app/controllers/places_controller.rb @@ -2,6 +2,12 @@ class PlacesController < ApplicationController def index end + def feed + respond_to do |format| + format.atom { @places_items = Place.order('updated_at DESC') } + end + end + def new @place = Place.new 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/app/views/places/feed.atom.builder b/app/views/places/feed.atom.builder new file mode 100644 index 0000000..661560a --- /dev/null +++ b/app/views/places/feed.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/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..104545b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,8 @@ resources :places, only: [:new, :create, :edit, :update] + get '/feed' => 'places#feed', as: 'feed', defaults: { format: 'atom' } + namespace :api, defaults: { format: 'json' } do namespace :v1 do resources :places, only: [:index, :show] diff --git a/spec/features/a_user_can_subscribe_to_the_place_feed.rb b/spec/features/a_user_can_subscribe_to_the_place_feed.rb new file mode 100644 index 0000000..28eb2f3 --- /dev/null +++ b/spec/features/a_user_can_subscribe_to_the_place_feed.rb @@ -0,0 +1,44 @@ +require 'rails_helper' + +feature 'A user subscribe to the place Atom feed' do + scenario 'and consult the complete correct feed page' do + CsvImportService.new('Place', Rails.root.join('spec/fixtures/csv/valid.csv'), state: 'active').save + CsvImportService.new('Place', Rails.root.join('spec/fixtures/csv/valid2.csv'), state: 'active').save + + visit '/feed' + + expect(page).to have_title(t('feed.title')) + + page.assert_selector('entry author name', :count => 2) + all('entry author name').each { |name| expect(name.text).to_not eq('') } + + all('entry content').each { |content| assert content.text.include? t('feed.link_to_map_marker') } + + expect(all('updated').length).to eq(3) + all('updated').each { |updated| expect(updated.text).to_not eq('') } + + expect(Place.first.updated_at).to_not eq(Place.last.updated_at) + end + + scenario 'and the last updated place appears first' do + CsvImportService.new('Place', Rails.root.join('spec/fixtures/csv/valid.csv'), state: 'active').save + CsvImportService.new('Place', Rails.root.join('spec/fixtures/csv/valid2.csv'), state: 'active').save + + visit '/feed' + + top_entry_title = find(:xpath, '//feed/entry[1]/title').text + expect(top_entry_title).to eq('Ecolutis') + + # Updating 'Craftsmen Angers' place to make it come at the top + oldest_updated_place = Place.order('updated_at DESC').last + expect(oldest_updated_place.name).to eq('Craftsmen Angers') + place_update = PlaceUpdate.from_place(oldest_updated_place) + place_update.description = 'New desc' + place_update.accept! + + visit '/feed' + + top_entry_title = find(:xpath, '//feed/entry[1]/title').text + expect(top_entry_title).to eq('Craftsmen Angers') + 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 diff --git a/spec/fixtures/csv/valid2.csv b/spec/fixtures/csv/valid2.csv new file mode 100644 index 0000000..2e0987c --- /dev/null +++ b/spec/fixtures/csv/valid2.csv @@ -0,0 +1,2 @@ +name;kind;street;zip_code;city;url;latitude;longitude;twitter_name;logo_url;description;owner_name;owner_email +Ecolutis;company;25 rue Lenepveu;49100;Angers;http://www.ecolutis.com;47.472041;-0.551269;ecolutis;http://www.ecolutis.com/wp-content/uploads/2013/12/logo.png;Opérateur de covoiturage;Olivier Demaegdt;olivier@ecolutis.com