diff --git a/plugins/poll/lib/poll.rb b/plugins/poll/lib/poll.rb index fceefc090b407a..0e9c28ef3fee28 100644 --- a/plugins/poll/lib/poll.rb +++ b/plugins/poll/lib/poll.rb @@ -38,7 +38,10 @@ def self.vote(user, post_id, poll_name, options) # Ensure consistency here as we do not have a unique index to limit the # number of votes per the poll's configuration. - DB.query(<<~SQL, poll_id: poll_id, user_id: user.id, offset: serialized_poll[:type] == "multiple" ? serialized_poll[:max] : 1) + is_multiple = serialized_poll[:type] == "multiple" + offset = is_multiple ? (serialized_poll[:max] || serialized_poll[:options].length) : 1 + + DB.query(<<~SQL, poll_id: poll_id, user_id: user.id, offset: offset) DELETE FROM poll_votes USING ( SELECT @@ -315,12 +318,12 @@ def self.validate_votes!(poll, options) num_of_options = options.length if poll.multiple? - if num_of_options < poll.min + if poll.min && (num_of_options < poll.min) raise DiscoursePoll::Error.new(I18n.t( "poll.min_vote_per_user", count: poll.min )) - elsif num_of_options > poll.max + elsif poll.max && (num_of_options > poll.max) raise DiscoursePoll::Error.new(I18n.t( "poll.max_vote_per_user", count: poll.max diff --git a/plugins/poll/spec/lib/poll_spec.rb b/plugins/poll/spec/lib/poll_spec.rb index 139a82dd7cd985..16c224be929143 100644 --- a/plugins/poll/spec/lib/poll_spec.rb +++ b/plugins/poll/spec/lib/poll_spec.rb @@ -127,6 +127,54 @@ I18n.t("poll.min_vote_per_user", count: poll.min) ) end + + it 'should allow user to vote on a multiple poll even if min option is not configured' do + post_with_multiple_poll = Fabricate(:post, raw: <<~RAW) + [poll type=multiple max=3] + * 1 + * 2 + * 3 + * 4 + * 5 + [/poll] + RAW + + poll = post_with_multiple_poll.polls.first + + DiscoursePoll::Poll.vote( + user, + post_with_multiple_poll.id, + "poll", + [poll.poll_options.first.digest] + ) + + expect(PollVote.where(poll: poll, user: user).pluck(:poll_option_id)) + .to contain_exactly(poll.poll_options.first.id) + end + + it 'should allow user to vote on a multiple poll even if max option is not configured' do + post_with_multiple_poll = Fabricate(:post, raw: <<~RAW) + [poll type=multiple min=1] + * 1 + * 2 + * 3 + * 4 + * 5 + [/poll] + RAW + + poll = post_with_multiple_poll.polls.first + + DiscoursePoll::Poll.vote( + user, + post_with_multiple_poll.id, + "poll", + [poll.poll_options.first.digest, poll.poll_options.second.digest] + ) + + expect(PollVote.where(poll: poll, user: user).pluck(:poll_option_id)) + .to contain_exactly(poll.poll_options.first.id, poll.poll_options.second.id) + end end describe "post_created" do