diff --git a/Changelog.md b/Changelog.md index 204cbc645..145a6e5a6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ # 0.7.6.0 ## Refactor +* Add unique index to poll participations on `poll_id` and `author_id` [#7798](https://github.com/diaspora/diaspora/pull/7798) ## Bug fixes diff --git a/db/migrate/20180425125409_add_poll_participations_unique_index_on_author_and_poll.rb b/db/migrate/20180425125409_add_poll_participations_unique_index_on_author_and_poll.rb new file mode 100644 index 000000000..2f7376f91 --- /dev/null +++ b/db/migrate/20180425125409_add_poll_participations_unique_index_on_author_and_poll.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddPollParticipationsUniqueIndexOnAuthorAndPoll < ActiveRecord::Migration[5.1] + def change + reversible do |change| + change.up do + duplicate_query = "WHERE a1.poll_id = a2.poll_id AND a1.author_id = a2.author_id AND a1.id > a2.id" + if AppConfig.postgres? + execute("DELETE FROM poll_participations AS a1 USING poll_participations AS a2 #{duplicate_query}") + else + execute("DELETE a1 FROM poll_participations a1, poll_participations a2 #{duplicate_query}") + end + end + end + + add_index :poll_participations, %i[poll_id author_id], unique: true + remove_index :poll_participations, :poll_id + end +end diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb index 581be0663..bf3d54537 100644 --- a/spec/models/poll_participation_spec.rb +++ b/spec/models/poll_participation_spec.rb @@ -24,6 +24,16 @@ describe PollParticipation, type: :model do bob.participate_in_poll!(status, poll.poll_answers.first) }.to_not raise_error end + + it "has unique DB index for author-person" do + pp = FactoryGirl.create(:poll_participation) + pp2 = FactoryGirl.create(:poll_participation, author: pp.author) + expect { + # rubocop:disable Rails/SkipsModelValidations + pp2.update_attribute(:poll_id, pp.poll_id) + # rubocop:enable Rails/SkipsModelValidations + }.to raise_error ActiveRecord::RecordNotUnique + end end it_behaves_like "it is relayable" do