diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 89999ac78..790045b0f 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -1,6 +1,7 @@
class PollsController < ApplicationController
include PollsHelper
+ before_action :load_poll, except: [:index]
before_action :load_active_poll, only: :index
load_and_authorize_resource
@@ -40,6 +41,10 @@ class PollsController < ApplicationController
private
+ def load_poll
+ @poll = Poll.where(slug: params[:id]).first || Poll.where(id: params[:id]).first
+ end
+
def load_active_poll
@active_poll = ActivePoll.first
end
diff --git a/app/models/poll.rb b/app/models/poll.rb
index 9d48c0abf..6c70dd126 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -5,6 +5,7 @@ class Poll < ApplicationRecord
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
include Notifiable
+ include Sluggable
translates :name, touch: true
translates :summary, touch: true
@@ -129,6 +130,10 @@ class Poll < ApplicationRecord
end
end
+ def generate_slug?
+ slug.nil?
+ end
+
def only_one_active
return unless starts_at.present?
return unless ends_at.present?
diff --git a/app/views/polls/_poll_group.html.erb b/app/views/polls/_poll_group.html.erb
index 711271509..8bd388b10 100644
--- a/app/views/polls/_poll_group.html.erb
+++ b/app/views/polls/_poll_group.html.erb
@@ -49,7 +49,7 @@
<% elsif poll.stats_enabled? %>
<%= link_to poll.name, stats_poll_path(poll) %>
<% else %>
- <%= link_to poll.name, poll %>
+ <%= link_to poll.name, poll_path(id: poll.slug || poll.id) %>
<% end %>
<%= poll_dates(poll) %>
@@ -72,7 +72,7 @@
- <%= link_to poll, class: "button hollow expanded" do %>
+ <%= link_to poll_path(id: poll.slug || poll.id), class: "button hollow expanded" do %>
<% if poll.expired? %>
<%= t("polls.index.participate_button_expired") %>
<% else %>
diff --git a/app/views/polls/_poll_subnav.html.erb b/app/views/polls/_poll_subnav.html.erb
index ec4f7590e..e50d64e0a 100644
--- a/app/views/polls/_poll_subnav.html.erb
+++ b/app/views/polls/_poll_subnav.html.erb
@@ -8,7 +8,7 @@
<%= t("polls.show.results_menu") %>
<% else %>
- <%= link_to t("polls.show.results_menu"), results_poll_path(@poll) %>
+ <%= link_to t("polls.show.results_menu"), results_poll_path(id: @poll.slug || @poll.id) %>
<% end %>
<% end %>
@@ -18,7 +18,7 @@
<%= t("polls.show.stats_menu") %>
<% else %>
- <%= link_to t("polls.show.stats_menu"), stats_poll_path(@poll) %>
+ <%= link_to t("polls.show.stats_menu"), stats_poll_path(id: @poll.slug || @poll.id) %>
<% end %>
<% end %>
@@ -27,7 +27,7 @@
<%= t("polls.show.info_menu") %>
<% else %>
- <%= link_to t("polls.show.info_menu"), poll_path(@poll) %>
+ <%= link_to t("polls.show.info_menu"), poll_path(id: @poll.slug || @poll.id) %>
<% end %>
diff --git a/db/dev_seeds/polls.rb b/db/dev_seeds/polls.rb
index 1ba8a6f05..75ee07871 100644
--- a/db/dev_seeds/polls.rb
+++ b/db/dev_seeds/polls.rb
@@ -4,25 +4,31 @@ require_dependency "poll/question/answer"
section "Creating polls" do
Poll.create(name: I18n.t("seeds.polls.current_poll"),
+ slug: I18n.t("seeds.polls.current_poll").parameterize,
starts_at: 7.days.ago,
ends_at: 7.days.from_now,
geozone_restricted: false)
Poll.create(name: I18n.t("seeds.polls.current_poll_geozone_restricted"),
+ slug: I18n.t("seeds.polls.current_poll_geozone_restricted").parameterize,
starts_at: 5.days.ago,
ends_at: 5.days.from_now,
geozone_restricted: true,
geozones: Geozone.reorder("RANDOM()").limit(3))
Poll.create(name: I18n.t("seeds.polls.recounting_poll"),
+ slug: I18n.t("seeds.polls.recounting_poll").parameterize,
starts_at: 15.days.ago,
ends_at: 2.days.ago)
Poll.create(name: I18n.t("seeds.polls.expired_poll_without_stats"),
+ slug: I18n.t("seeds.polls.expired_poll_without_stats").parameterize,
+
starts_at: 2.months.ago,
ends_at: 1.month.ago)
Poll.create(name: I18n.t("seeds.polls.expired_poll_with_stats"),
+ slug: I18n.t("seeds.polls.expired_poll_with_stats").parameterize,
starts_at: 2.months.ago,
ends_at: 1.month.ago,
results_enabled: true,
diff --git a/db/migrate/20171008154106_add_slug_to_polls.rb b/db/migrate/20171008154106_add_slug_to_polls.rb
new file mode 100644
index 000000000..f9f3d752f
--- /dev/null
+++ b/db/migrate/20171008154106_add_slug_to_polls.rb
@@ -0,0 +1,5 @@
+class AddSlugToPolls < ActiveRecord::Migration
+ def change
+ add_column :polls, :slug, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 158d9876b..409978b43 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1125,6 +1125,7 @@ ActiveRecord::Schema.define(version: 20190411090023) do
t.integer "comments_count", default: 0
t.integer "author_id"
t.datetime "hidden_at"
+ t.string "slug"
t.boolean "results_enabled", default: false
t.boolean "stats_enabled", default: false
t.datetime "created_at"
diff --git a/lib/tasks/polls.rake b/lib/tasks/polls.rake
new file mode 100644
index 000000000..0e689e00c
--- /dev/null
+++ b/lib/tasks/polls.rake
@@ -0,0 +1,8 @@
+namespace :poll do
+ desc "Generate slugs polls"
+ task generate_slugs: :environment do
+ Poll.find_each do |poll|
+ poll.update_columns(slug: poll.generate_slug, updated_at: Time.current) if poll.generate_slug?
+ end
+ end
+end
diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb
index 17119ad10..5a23e2630 100644
--- a/spec/factories/polls.rb
+++ b/spec/factories/polls.rb
@@ -2,6 +2,8 @@ FactoryBot.define do
factory :poll do
sequence(:name) { |n| "Poll #{SecureRandom.hex}" }
+ slug "this-is-a-slug"
+
starts_at { 1.month.ago }
ends_at { 1.month.from_now }
diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb
index b493d7be6..f48e6eb37 100644
--- a/spec/features/admin/poll/polls_spec.rb
+++ b/spec/features/admin/poll/polls_spec.rb
@@ -75,6 +75,7 @@ feature "Admin polls" do
expect(page).to have_content "Upcoming poll"
expect(page).to have_content I18n.l(start_date.to_date)
expect(page).to have_content I18n.l(end_date.to_date)
+ expect(Poll.last.slug).to eq "#{Poll.last.name.to_s.parameterize}"
end
scenario "Edit" do
diff --git a/spec/features/polls/polls_spec.rb b/spec/features/polls/polls_spec.rb
index 5b970324d..f9c420076 100644
--- a/spec/features/polls/polls_spec.rb
+++ b/spec/features/polls/polls_spec.rb
@@ -130,6 +130,16 @@ feature "Polls" do
let(:geozone) { create(:geozone) }
let(:poll) { create(:poll, summary: "Summary", description: "Description") }
+ scenario "Visit path with id" do
+ visit poll_path(poll.id)
+ expect(page).to have_current_path(poll_path(poll.id))
+ end
+
+ scenario "Visit path with slug" do
+ visit poll_path(poll.slug)
+ expect(page).to have_current_path(poll_path(poll.slug))
+ end
+
scenario "Show answers with videos" do
question = create(:poll_question, poll: poll)
answer = create(:poll_question_answer, question: question, title: "Chewbacca")
@@ -482,5 +492,20 @@ feature "Polls" do
expect(page).not_to have_content("Poll results")
expect(page).not_to have_content("Participation statistics")
end
+
+ scenario "Generates navigation links for polls without a slug" do
+ poll = create(:poll, :expired, results_enabled: true, stats_enabled: true)
+ poll.update_column(:slug, nil)
+
+ visit poll_path(poll)
+
+ expect(page).to have_link "Participation statistics"
+ expect(page).to have_link "Poll results"
+
+ click_link "Poll results"
+
+ expect(page).to have_link "Information"
+ end
+
end
end