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