refactors poll::voter

now belongs_to booth_assignment instead of to booth
This commit is contained in:
Juanjo Bazán
2016-12-06 20:20:18 +01:00
parent ad2dd7d267
commit 45d26f6dee
9 changed files with 73 additions and 23 deletions

View File

@@ -1,10 +1,9 @@
class Poll < ActiveRecord::Base class Poll < ActiveRecord::Base
has_many :booth_assignments, class_name: "Poll::BoothAssignment" has_many :booth_assignments, class_name: "Poll::BoothAssignment"
has_many :booths, through: :booth_assignments has_many :booths, through: :booth_assignments
has_many :voters, through: :booth_assignments
has_many :officer_assignments, through: :booth_assignments has_many :officer_assignments, through: :booth_assignments
has_many :officers, through: :officer_assignments has_many :officers, through: :officer_assignments
has_many :voters, through: :booths, class_name: "Poll::Voter"
has_many :questions has_many :questions
validates :name, presence: true validates :name, presence: true
@@ -35,4 +34,8 @@ class Poll < ActiveRecord::Base
return none if user.nil? || user.unverified? return none if user.nil? || user.unverified?
current current
end end
def document_has_voted?(document_number, document_type)
voters.where(document_number: document_number, document_type: document_type).exists?
end
end end

View File

@@ -2,7 +2,6 @@ class Poll
class Booth < ActiveRecord::Base class Booth < ActiveRecord::Base
has_many :booth_assignments, class_name: "Poll::BoothAssignment" has_many :booth_assignments, class_name: "Poll::BoothAssignment"
has_many :polls, through: :booth_assignments has_many :polls, through: :booth_assignments
has_many :voters
validates :name, presence: true, uniqueness: true validates :name, presence: true, uniqueness: true
end end

View File

@@ -5,5 +5,6 @@ class Poll
has_many :officer_assignments, class_name: "Poll::OfficerAssignment", dependent: :destroy has_many :officer_assignments, class_name: "Poll::OfficerAssignment", dependent: :destroy
has_many :officers, through: :officer_assignments has_many :officers, through: :officer_assignments
has_many :voters
end end
end end

View File

@@ -1,11 +1,14 @@
class Poll class Poll
class Voter < ActiveRecord::Base class Voter < ActiveRecord::Base
belongs_to :booth belongs_to :booth_assignment
delegate :poll, to: :booth delegate :poll, to: :booth_assignment
validates :booth_assignment, presence: true
validate :in_census validate :in_census
validate :has_not_voted validate :has_not_voted
before_create :assign_poll
def in_census def in_census
errors.add(:document_number, :not_in_census) unless census_api_response.valid? errors.add(:document_number, :not_in_census) unless census_api_response.valid?
end end
@@ -19,12 +22,16 @@ class Poll
end end
def has_voted? def has_voted?
poll.voters.where(document_number: document_number, document_type: document_type).exists? poll.document_has_voted?(document_number, document_type)
end end
def name def name
@census.name @census.name
end end
def assign_poll
poll_id = booth_assignment.poll_id
end
end end
end end

View File

@@ -0,0 +1,10 @@
class RenameBoothIdToBoothAssignmentId < ActiveRecord::Migration
def change
remove_column :poll_voters, :booth_id, :integer
add_column :poll_voters, :booth_assignment_id, :integer, null: false
add_column :poll_voters, :poll_id, :integer, null: false
add_column :poll_voters, :created_at, :datetime, null: false
add_column :poll_voters, :updated_at, :datetime, null: false
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161206131125) do ActiveRecord::Schema.define(version: 20161206132126) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -337,9 +337,12 @@ ActiveRecord::Schema.define(version: 20161206131125) do
add_index "poll_questions", ["tsv"], name: "index_poll_questions_on_tsv", using: :gin add_index "poll_questions", ["tsv"], name: "index_poll_questions_on_tsv", using: :gin
create_table "poll_voters", force: :cascade do |t| create_table "poll_voters", force: :cascade do |t|
t.integer "booth_id" t.string "document_number"
t.string "document_number" t.string "document_type"
t.string "document_type" t.integer "booth_assignment_id", null: false
t.integer "poll_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end end
create_table "polls", force: :cascade do |t| create_table "polls", force: :cascade do |t|

View File

@@ -309,11 +309,11 @@ FactoryGirl.define do
factory :poll_officer_assignment, class: 'Poll::OfficerAssignment' do factory :poll_officer_assignment, class: 'Poll::OfficerAssignment' do
association :officer, factory: :poll_officer association :officer, factory: :poll_officer
association :booth_assignment, factory: :poll_booth_assignment association :booth_assignment, factory: :poll_booth_assignment
end end
factory :poll_voter, class: 'Poll::Voter' do factory :poll_voter, class: 'Poll::Voter' do
association :booth, factory: :budget_booth association :booth_assignment, factory: :poll_booth_assignment
trait :valid_document do trait :valid_document do
document_type "1" document_type "1"

View File

@@ -38,4 +38,20 @@ describe :poll do
expect(create(:poll)).to_not be_expired expect(create(:poll)).to_not be_expired
end end
end end
describe "#document_has_voted?" do
it "returns true if Poll::Voter with document exists" do
booth_assignment = create(:poll_booth_assignment, poll: poll)
voter = create(:poll_voter, :valid_document, booth_assignment: booth_assignment)
expect(poll.document_has_voted?(voter.document_number, voter.document_type)).to eq(true)
end
it "returns false if Poll::Voter with document does not exists" do
booth_assignment = create(:poll_booth_assignment)
voter = create(:poll_voter, :valid_document, booth_assignment: booth_assignment)
expect(poll.document_has_voted?(voter.document_number, voter.document_type)).to eq(false)
end
end
end end

View File

@@ -3,42 +3,53 @@ require 'rails_helper'
describe :voter do describe :voter do
let(:poll) { create(:poll) } let(:poll) { create(:poll) }
let(:booth) { create(:poll_booth, poll: poll) } let(:booth) { create(:poll_booth) }
let(:booth_assignment) { create(:poll_booth_assignment, poll: poll, booth: booth) }
describe "validations" do describe "validations" do
it "should be valid if in census and has not voted" do it "should be valid if in census and has not voted" do
voter = build(:poll_voter, :valid_document, booth: booth) voter = build(:poll_voter, :valid_document, booth_assignment: booth_assignment)
expect(voter).to be_valid expect(voter).to be_valid
end end
it "should not be valid if the user is not in the census" do it "should not be valid if the user is not in the census" do
voter = build(:poll_voter, :invalid_document, booth: booth) voter = build(:poll_voter, :invalid_document, booth_assignment: booth_assignment)
expect(voter).to_not be_valid expect(voter).to_not be_valid
expect(voter.errors.messages[:document_number]).to eq(["Document not in census"]) expect(voter.errors.messages[:document_number]).to eq(["Document not in census"])
end end
it "should not be valid if the user has already voted in the same booth" do it "should not be valid if the user has already voted in the same booth/poll" do
voter1 = create(:poll_voter, :valid_document, booth: booth) voter1 = create(:poll_voter, :valid_document, booth_assignment: booth_assignment)
voter2 = build(:poll_voter, :valid_document, booth: booth) voter2 = build(:poll_voter, :valid_document, booth_assignment: booth_assignment)
expect(voter2).to_not be_valid expect(voter2).to_not be_valid
expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"]) expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"])
end end
it "should not be valid if the user has already voted in another booth" do it "should not be valid if the user has already voted in different booth in the same poll" do
booth1 = create(:poll_booth, poll: poll) booth_assignment1 = create(:poll_booth_assignment, poll: poll)
booth2 = create(:poll_booth, poll: poll) booth_assignment2 = create(:poll_booth_assignment, poll: poll)
voter1 = create(:poll_voter, :valid_document, booth: booth1) voter1 = create(:poll_voter, :valid_document, booth_assignment: booth_assignment1)
voter2 = build(:poll_voter, :valid_document, booth: booth2) voter2 = build(:poll_voter, :valid_document, booth_assignment: booth_assignment2)
expect(voter2).to_not be_valid expect(voter2).to_not be_valid
expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"]) expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"])
end end
it "should be valid if the user has already voted in the same booth in different poll" do
booth_assignment1 = create(:poll_booth_assignment, booth: booth)
booth_assignment2 = create(:poll_booth_assignment, booth: booth, poll: poll)
voter1 = create(:poll_voter, :valid_document, booth_assignment: booth_assignment1)
voter2 = build(:poll_voter, :valid_document, booth_assignment: booth_assignment2)
expect(voter2).to be_valid
end
xit "should not be valid if the user has voted via web" do xit "should not be valid if the user has voted via web" do
pending "Implementation for voting via web" pending "Implementation for voting via web"
end end