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 = "" 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..23b7d24
--- /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