From 900563e31c8d73e61a94273998a032c399c7f5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 12:03:48 +0100 Subject: [PATCH 01/11] adds poll_id and stats fields to poll_voters --- app/models/poll/voter.rb | 4 +++- ...542_add_poll_id_and_stats_fields_to_poll_voter.rb | 12 ++++++++++++ db/schema.rb | 8 ++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20170125104542_add_poll_id_and_stats_fields_to_poll_voter.rb diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index 8b0202aee..dd8c85d8f 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -1,11 +1,13 @@ class Poll class Voter < ActiveRecord::Base belongs_to :booth_assignment - delegate :poll, to: :booth_assignment + belongs_to :poll validates :booth_assignment, presence: true validate :in_census validate :has_not_voted + validates :poll, presence: true + validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type] } def in_census errors.add(:document_number, :not_in_census) unless census_api_response.valid? diff --git a/db/migrate/20170125104542_add_poll_id_and_stats_fields_to_poll_voter.rb b/db/migrate/20170125104542_add_poll_id_and_stats_fields_to_poll_voter.rb new file mode 100644 index 000000000..84e7de5d9 --- /dev/null +++ b/db/migrate/20170125104542_add_poll_id_and_stats_fields_to_poll_voter.rb @@ -0,0 +1,12 @@ +class AddPollIdAndStatsFieldsToPollVoter < ActiveRecord::Migration + def change + add_column :poll_voters, :poll_id, :integer, null: false + + remove_column :poll_voters, :booth_assignment_id, :integer, null: false + add_column :poll_voters, :booth_assignment_id, :integer + + add_column :poll_voters, :age, :integer + add_column :poll_voters, :gender, :string + add_column :poll_voters, :geozone_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 8eb3c5ce3..0cdbcad2b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170120164547) do +ActiveRecord::Schema.define(version: 20170125104542) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -449,9 +449,13 @@ ActiveRecord::Schema.define(version: 20170120164547) do create_table "poll_voters", force: :cascade do |t| t.string "document_number" t.string "document_type" - t.integer "booth_assignment_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "poll_id", null: false + t.integer "booth_assignment_id" + t.integer "age" + t.string "gender" + t.integer "geozone_id" end create_table "polls", force: :cascade do |t| From 8f235c25d30895c330e568a3922b0486ff59292f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 12:18:15 +0100 Subject: [PATCH 02/11] poll has_many voters --- app/models/poll.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index 52afaafa5..c5da9dcd0 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,7 +1,7 @@ class Poll < ActiveRecord::Base has_many :booth_assignments, class_name: "Poll::BoothAssignment" has_many :booths, through: :booth_assignments - has_many :voters, through: :booth_assignments + has_many :voters has_many :officer_assignments, through: :booth_assignments has_many :officers, through: :officer_assignments has_many :questions From 6bc4f5b3074719509d8dcb27041a478932d1b839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 12:46:44 +0100 Subject: [PATCH 03/11] adds Poll::Answer model for web users PartialResults is kept for booth results --- app/controllers/polls/questions_controller.rb | 12 +++++------- app/controllers/polls_controller.rb | 8 ++++---- app/models/poll/answer.rb | 13 +++++++++++++ db/migrate/20170125112017_create_poll_answers.rb | 15 +++++++++++++++ db/schema.rb | 14 +++++++++++++- spec/factories.rb | 6 ++++++ spec/features/polls/polls_spec.rb | 2 +- spec/features/polls/questions_spec.rb | 2 +- 8 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 app/models/poll/answer.rb create mode 100644 db/migrate/20170125112017_create_poll_answers.rb diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb index 03e71c15b..e9c7e2bbd 100644 --- a/app/controllers/polls/questions_controller.rb +++ b/app/controllers/polls/questions_controller.rb @@ -1,7 +1,7 @@ class Polls::QuestionsController < ApplicationController load_and_authorize_resource :poll - load_and_authorize_resource :question, class: 'Poll::Question'#, through: :poll + load_and_authorize_resource :question, class: 'Poll::Question' has_orders %w{most_voted newest oldest}, only: :show @@ -10,17 +10,15 @@ class Polls::QuestionsController < ApplicationController @comment_tree = CommentTree.new(@commentable, params[:page], @current_order) set_comment_flags(@comment_tree.comments) - question_answer = @question.partial_results.where(author_id: current_user.try(:id)).first + question_answer = @question.answers.where(author_id: current_user.try(:id)).first @answers_by_question_id = {@question.id => question_answer.try(:answer)} end def answer - partial_result = @question.partial_results.find_or_initialize_by(author: current_user, - amount: 1, - origin: 'web') + answer = @question.answers.find_or_initialize_by(author: current_user) - partial_result.answer = params[:answer] - partial_result.save! + answer.answer = params[:answer] + answer.save! @answers_by_question_id = {@question.id => params[:answer]} end diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index a93c84e9d..ce80f8dcc 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -9,12 +9,12 @@ class PollsController < ApplicationController end def show - @questions = @poll.questions.for_render.sort_for_list + @questions = @poll.questions.for_render.sort_for_list @answers_by_question_id = {} - poll_partial_results = Poll::PartialResult.by_question(@poll.question_ids).by_author(current_user.try(:id)) - poll_partial_results.each do |result| - @answers_by_question_id[result.question_id] = result.answer + poll_answers = Poll::Answer.by_question(@poll.question_ids).by_author(current_user.try(:id)) + poll_answers.each do |answer| + @answers_by_question_id[answer.question_id] = answer.answer end end diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb new file mode 100644 index 000000000..b0f2d4410 --- /dev/null +++ b/app/models/poll/answer.rb @@ -0,0 +1,13 @@ +class Poll::Answer < ActiveRecord::Base + + belongs_to :question, -> { with_hidden } + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + + validates :question, presence: true + validates :author, presence: true + validates :answer, presence: true + validates :answer, inclusion: {in: ->(a) { a.question.valid_answers }} + + scope :by_author, -> (author_id) { where(author_id: author_id) } + scope :by_question, -> (question_id) { where(question_id: question_id) } +end \ No newline at end of file diff --git a/db/migrate/20170125112017_create_poll_answers.rb b/db/migrate/20170125112017_create_poll_answers.rb new file mode 100644 index 000000000..7ea930d0c --- /dev/null +++ b/db/migrate/20170125112017_create_poll_answers.rb @@ -0,0 +1,15 @@ +class CreatePollAnswers < ActiveRecord::Migration + def change + create_table :poll_answers do |t| + t.integer :question_id + t.integer :author_id + t.string :answer + + t.timestamps + end + + add_index :poll_answers, :question_id + add_index :poll_answers, :author_id + add_index :poll_answers, [:question_id, :answer] + end +end diff --git a/db/schema.rb b/db/schema.rb index 0cdbcad2b..932d4e28a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170125104542) do +ActiveRecord::Schema.define(version: 20170125112017) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -374,6 +374,18 @@ ActiveRecord::Schema.define(version: 20170125104542) do add_index "organizations", ["user_id"], name: "index_organizations_on_user_id", using: :btree + create_table "poll_answers", force: :cascade do |t| + t.integer "question_id" + t.integer "author_id" + t.string "answer" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "poll_answers", ["author_id"], name: "index_poll_answers_on_author_id", using: :btree + add_index "poll_answers", ["question_id", "answer"], name: "index_poll_answers_on_question_id_and_answer", using: :btree + add_index "poll_answers", ["question_id"], name: "index_poll_answers_on_question_id", using: :btree + create_table "poll_booth_assignments", force: :cascade do |t| t.integer "booth_id" t.integer "poll_id" diff --git a/spec/factories.rb b/spec/factories.rb index f46362e16..c3e694025 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -434,6 +434,12 @@ FactoryGirl.define do end end + factory :poll_answer, class: 'Poll::Answer' do + association :question, factory: :poll_question + association :author, factory: :user + answer { question.verified_answers.sample } + end + factory :poll_partial_result, class: 'Poll::PartialResult' do association :question, factory: :poll_question association :author, factory: :user diff --git a/spec/features/polls/polls_spec.rb b/spec/features/polls/polls_spec.rb index c4a8f55a2..fe5957181 100644 --- a/spec/features/polls/polls_spec.rb +++ b/spec/features/polls/polls_spec.rb @@ -166,7 +166,7 @@ feature 'Polls' do scenario 'Level 2 users who have already answered' do question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') user = create(:user, :level_two) - create(:poll_partial_result, question: question, author: user, answer: 'Chewbacca') + create(:poll_answer, question: question, author: user, answer: 'Chewbacca') login_as user visit poll_path(poll) diff --git a/spec/features/polls/questions_spec.rb b/spec/features/polls/questions_spec.rb index af4c1058c..e925c8fd6 100644 --- a/spec/features/polls/questions_spec.rb +++ b/spec/features/polls/questions_spec.rb @@ -70,7 +70,7 @@ feature 'Poll Questions' do question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') user = create(:user, :level_two, geozone: geozone) - create(:poll_partial_result, question: question, author: user, answer: 'Chewbacca') + create(:poll_answer, question: question, author: user, answer: 'Chewbacca') login_as user visit question_path(question) From 5806d86e336d7d6b0678553a9ed9c6b9124e0928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 12:57:00 +0100 Subject: [PATCH 04/11] changes poll_voters to optionally reference an answer adds indexes for poll_voters --- .../20170125114952_add_answer_id_to_poll_voters.rb | 9 +++++++++ db/schema.rb | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20170125114952_add_answer_id_to_poll_voters.rb diff --git a/db/migrate/20170125114952_add_answer_id_to_poll_voters.rb b/db/migrate/20170125114952_add_answer_id_to_poll_voters.rb new file mode 100644 index 000000000..34d5bbc54 --- /dev/null +++ b/db/migrate/20170125114952_add_answer_id_to_poll_voters.rb @@ -0,0 +1,9 @@ +class AddAnswerIdToPollVoters < ActiveRecord::Migration + def change + add_column :poll_voters, :answer_id, :integer, default: nil + + add_index :poll_voters, :document_number + add_index :poll_voters, :poll_id + add_index :poll_voters, [:poll_id, :document_number, :document_type], name: 'doc_by_poll' + end +end diff --git a/db/schema.rb b/db/schema.rb index 932d4e28a..290703e9e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170125112017) do +ActiveRecord::Schema.define(version: 20170125114952) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -468,8 +468,13 @@ ActiveRecord::Schema.define(version: 20170125112017) do t.integer "age" t.string "gender" t.integer "geozone_id" + t.integer "answer_id" end + add_index "poll_voters", ["document_number"], name: "index_poll_voters_on_document_number", using: :btree + add_index "poll_voters", ["poll_id", "document_number", "document_type"], name: "doc_by_poll", using: :btree + add_index "poll_voters", ["poll_id"], name: "index_poll_voters_on_poll_id", using: :btree + create_table "polls", force: :cascade do |t| t.string "name" t.datetime "starts_at" From 8d8d822323e896e0c14320740e0a96bf32f0b231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 13:04:26 +0100 Subject: [PATCH 05/11] adds answer spec --- spec/models/poll/answer_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 spec/models/poll/answer_spec.rb diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb new file mode 100644 index 000000000..73707ad80 --- /dev/null +++ b/spec/models/poll/answer_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +describe Poll::Answer do + + describe "validations" do + it "validates that the answers are included in the Poll::Question's list" do + q = create(:poll_question, valid_answers: 'One, Two, Three') + expect(build(:poll_answer, question: q, answer: 'One')).to be_valid + expect(build(:poll_answer, question: q, answer: 'Two')).to be_valid + expect(build(:poll_answer, question: q, answer: 'Three')).to be_valid + + expect(build(:poll_answer, question: q, answer: 'Four')).to_not be_valid + end + end + +end From 0b2454fb97eebdb88ef3e2d3807a255e47d251cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 14:17:49 +0100 Subject: [PATCH 06/11] adds User#age --- app/models/user.rb | 8 ++++++++ spec/models/user_spec.rb | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 8e41a0427..80b0cb621 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -246,6 +246,14 @@ class User < ActiveRecord::Base "#{name} (#{email})" end + def age + if date_of_birth.blank? + nil + else + ((Date.today - date_of_birth.to_date).to_i / 365.25).to_i + end + end + def save_requiring_finish_signup begin self.registering_with_oauth = true diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0f03086ba..789341fe9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -65,6 +65,13 @@ describe User do end end + describe "#age" do + it "is the rounded integer age based on the date_of_birth" do + user = create(:user, date_of_birth: 33.years.ago) + expect(user.age).to eq(33) + end + end + describe 'preferences' do describe 'email_on_comment' do it 'should be false by default' do From 5a72e4fbe8f30b56d57d08cc742cea84ae021b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 14:18:32 +0100 Subject: [PATCH 07/11] fixes factories method call --- spec/factories.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index c3e694025..90a725636 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -437,14 +437,14 @@ FactoryGirl.define do factory :poll_answer, class: 'Poll::Answer' do association :question, factory: :poll_question association :author, factory: :user - answer { question.verified_answers.sample } + answer { question.valid_answers.sample } end factory :poll_partial_result, class: 'Poll::PartialResult' do association :question, factory: :poll_question association :author, factory: :user origin { 'web' } - answer { question.verified_answers.sample } + answer { question.valid_answers.sample } end factory :organization do From 086f4a4170f1448cdf501b7a3ca15d8991451220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 14:19:36 +0100 Subject: [PATCH 08/11] refactors Poll::Voter --- app/models/poll/voter.rb | 57 +++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index dd8c85d8f..a2d46053a 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -1,33 +1,54 @@ class Poll class Voter < ActiveRecord::Base - belongs_to :booth_assignment belongs_to :poll + belongs_to :booth_assignment + belongs_to :answer - validates :booth_assignment, presence: true - validate :in_census - validate :has_not_voted validates :poll, presence: true - validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type] } - - def in_census - errors.add(:document_number, :not_in_census) unless census_api_response.valid? - end - - def has_not_voted - errors.add(:document_number, :has_voted, name: name) if has_voted? - end + validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type], message: :has_voted } def census_api_response - @census ||= CensusApi.new.call(document_type, document_number) + @census_api_response ||= CensusApi.new.call(document_type, document_number) end - def has_voted? - poll.document_has_voted?(document_number, document_type) + def in_census? + census_api_response.valid? end - def name - @census.name + def fill_stats_fields + if in_census? + self.gender = census_api_response.gender + self.geozone_id = Geozone.select(:id).where(census_code: census_api_response.district_code).first.try(:id) + self.age = voter_age(census_api_response.date_of_birth) + end end + def self.create_from_user(user, options = {}) + poll_id = options[:poll_id] + booth_assignment_id = options[:booth_assignment_id] + answer_id = options[:answer_id] + + Voter.create( + document_type: user.document_type, + document_number: user.document_number, + poll_id: poll_id, + booth_assignment_id: booth_assignment_id, + gender: user.gender, + geozone_id: user.geozone_id, + age: user.age, + answer_id: answer_id + ) + end + + private + + def voter_age(date_of_birth) + if date_of_birth.blank? + nil + else + ((Date.today - date_of_birth.to_date).to_i / 365.25).to_i + end + end + end end \ No newline at end of file From b13a76963af73795c5d27b64c2794c06c4e6e95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 14:21:03 +0100 Subject: [PATCH 09/11] records participation of user via web MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit answering a poll question creates a voter with the user data to record participation in question’s poll --- app/controllers/polls/questions_controller.rb | 1 + app/models/poll/answer.rb | 8 ++++ config/locales/activerecord.en.yml | 2 +- spec/factories.rb | 8 +++- spec/features/polls/questions_spec.rb | 16 +++++++ spec/models/poll/answer_spec.rb | 14 +++++++ spec/models/poll/poll_spec.rb | 7 ++-- spec/models/poll/voter_spec.rb | 42 +++++++++++-------- 8 files changed, 73 insertions(+), 25 deletions(-) diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb index e9c7e2bbd..1849dff97 100644 --- a/app/controllers/polls/questions_controller.rb +++ b/app/controllers/polls/questions_controller.rb @@ -19,6 +19,7 @@ class Polls::QuestionsController < ApplicationController answer.answer = params[:answer] answer.save! + answer.record_voter_participation @answers_by_question_id = {@question.id => params[:answer]} end diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb index b0f2d4410..2d08fefa4 100644 --- a/app/models/poll/answer.rb +++ b/app/models/poll/answer.rb @@ -3,6 +3,10 @@ class Poll::Answer < ActiveRecord::Base belongs_to :question, -> { with_hidden } belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + has_one :voter + + delegate :poll, :poll_id, to: :question + validates :question, presence: true validates :author, presence: true validates :answer, presence: true @@ -10,4 +14,8 @@ class Poll::Answer < ActiveRecord::Base scope :by_author, -> (author_id) { where(author_id: author_id) } scope :by_question, -> (question_id) { where(question_id: question_id) } + + def record_voter_participation + Poll::Voter.create_from_user(author, {poll_id: poll_id, answer_id: id}) + end end \ No newline at end of file diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 302b6767a..6a7aebcbd 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -138,7 +138,7 @@ en: attributes: document_number: not_in_census: "Document not in census" - has_voted: "%{name} has already voted" + has_voted: "User has already voted" proposal: attributes: tag_list: diff --git a/spec/factories.rb b/spec/factories.rb index 90a725636..7653f9a3a 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -421,7 +421,11 @@ FactoryGirl.define do end factory :poll_voter, class: 'Poll::Voter' do - association :booth_assignment, factory: :poll_booth_assignment + poll + + trait :from_booth do + association :booth_assignment, factory: :poll_booth_assignment + end trait :valid_document do document_type "1" @@ -436,7 +440,7 @@ FactoryGirl.define do factory :poll_answer, class: 'Poll::Answer' do association :question, factory: :poll_question - association :author, factory: :user + association :author, factory: [:user, :level_three] answer { question.valid_answers.sample } end diff --git a/spec/features/polls/questions_spec.rb b/spec/features/polls/questions_spec.rb index e925c8fd6..d6d02b0cb 100644 --- a/spec/features/polls/questions_spec.rb +++ b/spec/features/polls/questions_spec.rb @@ -93,5 +93,21 @@ feature 'Poll Questions' do expect(page).to have_link('Chewbacca') end + scenario 'Records participarion', :js do + question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + user = create(:user, :level_two, geozone: geozone) + + login_as user + visit question_path(question) + + click_link 'Han Solo' + + expect(page).to_not have_link('Han Solo') + + answer = Poll::Answer.by_question(question.id).by_author(user.id).first + expect(answer.voter.document_number).to eq(user.document_number) + expect(answer.voter.poll_id).to eq(poll.id) + end + end end diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb index 73707ad80..effc28fde 100644 --- a/spec/models/poll/answer_spec.rb +++ b/spec/models/poll/answer_spec.rb @@ -13,4 +13,18 @@ describe Poll::Answer do end end + describe "#record_voter_participation" do + it "creates a poll_voter with user and poll data" do + answer = create(:poll_answer) + expect(answer.voter).to be_nil + + answer.record_voter_participation + voter = answer.reload.voter + + expect(voter.answer).to eq(answer) + expect(voter.document_number).to eq(answer.author.document_number) + expect(voter.poll_id).to eq(answer.poll.id) + end + end + end diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index e410c31ce..b2ec29e5c 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -64,15 +64,14 @@ describe :poll do 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) + voter = create(:poll_voter, :valid_document, poll: poll) 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) + poll_2 = create(:poll) + voter = create(:poll_voter, :valid_document, poll: poll_2) expect(poll.document_has_voted?(voter.document_number, voter.document_type)).to eq(false) end diff --git a/spec/models/poll/voter_spec.rb b/spec/models/poll/voter_spec.rb index 3a1844f4b..88541dc82 100644 --- a/spec/models/poll/voter_spec.rb +++ b/spec/models/poll/voter_spec.rb @@ -8,36 +8,37 @@ describe :voter do describe "validations" do - it "should be valid if in census and has not voted" do - voter = build(:poll_voter, :valid_document, booth_assignment: booth_assignment) + it "should be valid if has not voted" do + voter = build(:poll_voter, :valid_document) expect(voter).to be_valid end - it "should not be valid if the user is not in the census" do - voter = build(:poll_voter, :invalid_document, booth_assignment: booth_assignment) - - expect(voter).to_not be_valid - expect(voter.errors.messages[:document_number]).to eq(["Document not in census"]) - end - - it "should not be valid if the user has already voted in the same booth/poll" do - voter1 = create(:poll_voter, :valid_document, booth_assignment: booth_assignment) - voter2 = build(:poll_voter, :valid_document, booth_assignment: booth_assignment) + it "should not be valid if the user has already voted in the same poll or booth_assignment" do + voter1 = create(:poll_voter, :valid_document, poll: poll) + voter2 = build(:poll_voter, :valid_document, poll: poll) 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(["User has already voted"]) + end + + it "should not be valid if the user has already voted in the same poll/booth" do + voter1 = create(:poll_voter, :valid_document, poll: poll, booth_assignment: booth_assignment) + voter2 = build(:poll_voter, :valid_document, poll: poll, booth_assignment: booth_assignment) + + expect(voter2).to_not be_valid + expect(voter2.errors.messages[:document_number]).to eq(["User has already voted"]) end it "should not be valid if the user has already voted in different booth in the same poll" do booth_assignment1 = create(:poll_booth_assignment, poll: poll) booth_assignment2 = create(:poll_booth_assignment, poll: poll) - voter1 = create(:poll_voter, :valid_document, booth_assignment: booth_assignment1) - voter2 = build(:poll_voter, :valid_document, booth_assignment: booth_assignment2) + voter1 = create(:poll_voter, :valid_document, poll: poll, booth_assignment: booth_assignment1) + voter2 = build(:poll_voter, :valid_document, poll: poll, booth_assignment: booth_assignment2) 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(["User has already voted"]) end it "should be valid if the user has already voted in the same booth in different poll" do @@ -50,8 +51,13 @@ describe :voter do expect(voter2).to be_valid end - xit "should not be valid if the user has voted via web" do - pending "Implementation for voting via web" + it "should not be valid if the user has voted via web" do + answer = create(:poll_answer) + answer.record_voter_participation + + voter = build(:poll_voter, poll: answer.question.poll, document_number: answer.author.document_number, document_type: "1") + expect(voter).to_not be_valid + expect(voter.errors.messages[:document_number]).to eq(["User has already voted"]) end end From 754095f4d0c468a1b838a0503394397b9ac58056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 17:15:38 +0100 Subject: [PATCH 10/11] fixes modified i18n key --- config/locales/activerecord.es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 644207b86..f55e82d1e 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -133,7 +133,7 @@ es: attributes: document_number: not_in_census: "Este documento no aparece en el censo" - has_voted: "%{name} ya ha votado" + has_voted: "Este usuario ya ha votado" proposal: attributes: tag_list: From cc6d841978448f0ae3648a0d2127e0398d396633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 25 Jan 2017 17:16:17 +0100 Subject: [PATCH 11/11] refactors age calculation --- app/models/poll/voter.rb | 7 ++++--- app/models/user.rb | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index a2d46053a..4c9314f12 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -42,11 +42,12 @@ class Poll private - def voter_age(date_of_birth) - if date_of_birth.blank? + def voter_age(dob) + if dob.blank? nil else - ((Date.today - date_of_birth.to_date).to_i / 365.25).to_i + now = Time.now.utc.to_date + now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1) end end diff --git a/app/models/user.rb b/app/models/user.rb index 80b0cb621..7c72ab4b3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -250,7 +250,10 @@ class User < ActiveRecord::Base if date_of_birth.blank? nil else - ((Date.today - date_of_birth.to_date).to_i / 365.25).to_i + now = Time.now.utc.to_date + now.year - date_of_birth.year - ( + (now.month > date_of_birth.month || (now.month == date_of_birth.month && now.day >= date_of_birth.day) + ) ? 0 : 1) end end