From 5e01b380cda2245176f8d83c31d2baf66ebdad3e Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Tue, 27 Dec 2016 11:02:27 +0100 Subject: [PATCH 1/5] Legislation Answer model --- app/models/legislation/answer.rb | 9 +++++ app/models/legislation/question.rb | 1 + app/models/legislation/question_option.rb | 1 + app/models/user.rb | 1 + ...161222115744_create_legislation_answers.rb | 13 +++++++ db/schema.rb | 14 +++++++ spec/factories.rb | 6 +++ spec/models/legislation/answer_spec.rb | 39 +++++++++++++++++++ 8 files changed, 84 insertions(+) create mode 100644 app/models/legislation/answer.rb create mode 100644 db/migrate/20161222115744_create_legislation_answers.rb create mode 100644 spec/models/legislation/answer_spec.rb diff --git a/app/models/legislation/answer.rb b/app/models/legislation/answer.rb new file mode 100644 index 000000000..fd4bc90ed --- /dev/null +++ b/app/models/legislation/answer.rb @@ -0,0 +1,9 @@ +class Legislation::Answer < ActiveRecord::Base + belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :answers, counter_cache: true + belongs_to :question_option, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_option_id', dependent: :destroy, inverse_of: :answers, counter_cache: true + belongs_to :user, dependent: :destroy, inverse_of: :legislation_answers + + validates :question, presence: true, uniqueness: { scope: :user_id} + validates :question_option, presence: true + validates :user, presence: true +end diff --git a/app/models/legislation/question.rb b/app/models/legislation/question.rb index 2b779d1f8..e80d169ce 100644 --- a/app/models/legislation/question.rb +++ b/app/models/legislation/question.rb @@ -6,6 +6,7 @@ class Legislation::Question < ActiveRecord::Base belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id' has_many :question_options, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question + has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question has_many :comments, as: :commentable accepts_nested_attributes_for :question_options, :reject_if => proc { |attributes| attributes[:value].blank? }, allow_destroy: true diff --git a/app/models/legislation/question_option.rb b/app/models/legislation/question_option.rb index 93bc20320..f7927dd1a 100644 --- a/app/models/legislation/question_option.rb +++ b/app/models/legislation/question_option.rb @@ -3,6 +3,7 @@ class Legislation::QuestionOption < ActiveRecord::Base include ActsAsParanoidAliases belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', inverse_of: :question_options + has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question validates :question, presence: true validates :value, presence: true, uniqueness: { scope: :legislation_question_id } diff --git a/app/models/user.rb b/app/models/user.rb index 03f2db27b..4ded8d99e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,6 +25,7 @@ class User < ActiveRecord::Base has_many :notifications has_many :direct_messages_sent, class_name: 'DirectMessage', foreign_key: :sender_id has_many :direct_messages_received, class_name: 'DirectMessage', foreign_key: :receiver_id + has_many :legislation_answers, class_name: 'Legislation::Answer', dependent: :destroy, inverse_of: :user belongs_to :geozone validates :username, presence: true, if: :username_required? diff --git a/db/migrate/20161222115744_create_legislation_answers.rb b/db/migrate/20161222115744_create_legislation_answers.rb new file mode 100644 index 000000000..0c8170d68 --- /dev/null +++ b/db/migrate/20161222115744_create_legislation_answers.rb @@ -0,0 +1,13 @@ +class CreateLegislationAnswers < ActiveRecord::Migration + def change + create_table :legislation_answers do |t| + t.references :legislation_question, index: true + t.references :legislation_question_option, index: true + t.references :user, index: true + + t.datetime :hidden_at, index: true + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 0438a3328..e9e672e08 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -227,6 +227,20 @@ ActiveRecord::Schema.define(version: 20161222180927) do t.datetime "updated_at", null: false end + create_table "legislation_answers", force: :cascade do |t| + t.integer "legislation_question_id" + t.integer "legislation_question_option_id" + t.integer "user_id" + t.datetime "hidden_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "legislation_answers", ["hidden_at"], name: "index_legislation_answers_on_hidden_at", using: :btree + add_index "legislation_answers", ["legislation_question_id"], name: "index_legislation_answers_on_legislation_question_id", using: :btree + add_index "legislation_answers", ["legislation_question_option_id"], name: "index_legislation_answers_on_legislation_question_option_id", using: :btree + add_index "legislation_answers", ["user_id"], name: "index_legislation_answers_on_user_id", using: :btree + create_table "legislation_draft_versions", force: :cascade do |t| t.integer "legislation_process_id" t.string "title" diff --git a/spec/factories.rb b/spec/factories.rb index f14edf6ea..731e1fef1 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -411,4 +411,10 @@ FactoryGirl.define do question factory: :legislation_question sequence(:value) { |n| "Option #{n}" } end + + factory :legislation_answer, class: 'Legislation::Answer' do + question factory: :legislation_question + question_option factory: :legislation_question_option + user + end end diff --git a/spec/models/legislation/answer_spec.rb b/spec/models/legislation/answer_spec.rb new file mode 100644 index 000000000..9f5037081 --- /dev/null +++ b/spec/models/legislation/answer_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +RSpec.describe Legislation::Answer, type: :model do + let(:legislation_answer) { build(:legislation_answer) } + + it "should be valid" do + expect(legislation_answer).to be_valid + end + + it "counts answers" do + question = create(:legislation_question) + option_1 = create(:legislation_question_option, question: question, value: 'Yes') + option_2 = create(:legislation_question_option, question: question, value: 'No') + + answer = create(:legislation_answer, question: question, question_option: option_2) + + expect(answer).to be_valid + expect(question.answers_count).to eq 1 + expect(option_2.answers_count).to eq 1 + expect(option_1.answers_count).to eq 0 + end + + it "can't answer same question more than once" do + question = create(:legislation_question) + option_1 = create(:legislation_question_option, question: question, value: 'Yes') + option_2 = create(:legislation_question_option, question: question, value: 'No') + user = create(:user) + + answer = create(:legislation_answer, question: question, question_option: option_2, user: user) + expect(answer).to be_valid + + second_answer = build(:legislation_answer, question: question, question_option: option_1, user: user) + expect(second_answer).to be_invalid + + expect(question.answers_count).to eq 1 + expect(option_2.answers_count).to eq 1 + expect(option_1.answers_count).to eq 0 + end +end From a6ceab6d73c53675b9b2093359254fb379c89869 Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Tue, 27 Dec 2016 19:49:03 +0100 Subject: [PATCH 2/5] Answer legislation questions --- .../legislation/answers_controller.rb | 21 ++++++ .../legislation/questions_controller.rb | 1 + app/models/abilities/everyone.rb | 1 + app/models/legislation/process.rb | 4 +- app/models/legislation/question.rb | 6 +- app/views/admin/_menu.html.erb | 2 +- .../legislation/questions/index.html.erb | 4 +- app/views/legislation/questions/show.html.erb | 21 +++--- config/locales/activerecord.en.yml | 13 ++++ config/locales/activerecord.es.yml | 13 ++++ config/locales/en.yml | 1 + config/locales/es.yml | 1 + spec/features/legislation/debate_spec.rb | 69 +++++++++++++++++-- 13 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 app/controllers/legislation/answers_controller.rb diff --git a/app/controllers/legislation/answers_controller.rb b/app/controllers/legislation/answers_controller.rb new file mode 100644 index 000000000..156cbc68b --- /dev/null +++ b/app/controllers/legislation/answers_controller.rb @@ -0,0 +1,21 @@ +class Legislation::AnswersController < Legislation::BaseController + before_action :authenticate_user! + before_action :verify_resident! + + load_and_authorize_resource :process + load_and_authorize_resource :question, through: :process + load_and_authorize_resource :answer, through: :question + + def create + @answer.user = current_user + @answer.save + redirect_to legislation_process_question_path(@process, @question) + end + + private + def answer_params + params.require(:legislation_answer).permit( + :legislation_question_option_id, + ) + end +end diff --git a/app/controllers/legislation/questions_controller.rb b/app/controllers/legislation/questions_controller.rb index 7114c98cb..d50443281 100644 --- a/app/controllers/legislation/questions_controller.rb +++ b/app/controllers/legislation/questions_controller.rb @@ -8,5 +8,6 @@ class Legislation::QuestionsController < Legislation::BaseController @commentable = @question @comment_tree = CommentTree.new(@commentable, params[:page], @current_order) set_comment_flags(@comment_tree.comments) + @answer = @question.answer_for_user(current_user) || Legislation::Answer.new end end diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index e22bcb7e0..466b6a5ba 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -14,6 +14,7 @@ module Abilities can [:read, :draft_publication, :allegations, :final_version_publication], Legislation::Process can [:read], Legislation::DraftVersion can [:read], Legislation::Question + can [:create], Legislation::Answer end end end diff --git a/app/models/legislation/process.rb b/app/models/legislation/process.rb index dbc31c7b3..86b250b18 100644 --- a/app/models/legislation/process.rb +++ b/app/models/legislation/process.rb @@ -2,9 +2,9 @@ class Legislation::Process < ActiveRecord::Base acts_as_paranoid column: :hidden_at include ActsAsParanoidAliases - has_many :draft_versions, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id' + has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id' has_one :final_draft_version, -> { where final_version: true }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id' - has_many :questions, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id' + has_many :questions, -> { order(:id) }, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id' validates :title, presence: true validates :description, presence: true diff --git a/app/models/legislation/question.rb b/app/models/legislation/question.rb index e80d169ce..7df8f67cf 100644 --- a/app/models/legislation/question.rb +++ b/app/models/legislation/question.rb @@ -5,7 +5,7 @@ class Legislation::Question < ActiveRecord::Base belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id' - has_many :question_options, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question + has_many :question_options, -> { order(:id) }, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question has_many :comments, as: :commentable @@ -17,4 +17,8 @@ class Legislation::Question < ActiveRecord::Base def next_question_id @next_question_id ||= process.questions.where("id > ?", id).order('id ASC').limit(1).pluck(:id).first end + + def answer_for_user(user) + answers.where(user: user).first + end end diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 6da3b23fd..8257b3c8a 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -44,7 +44,7 @@ <% end %> <% if feature?(:legislation) %> -
  • > +
  • > <%= link_to admin_legislation_processes_path do %> <%= t("admin.menu.legislation") %> <% end %> diff --git a/app/views/admin/legislation/questions/index.html.erb b/app/views/admin/legislation/questions/index.html.erb index 7d41f1b83..f0a4638ee 100644 --- a/app/views/admin/legislation/questions/index.html.erb +++ b/app/views/admin/legislation/questions/index.html.erb @@ -29,7 +29,9 @@ <%= content_tag :ul do %> <% question.question_options.each do |question_option| %> - <%= content_tag :li, question_option.value %> + <%= content_tag :li do %> + <%= question_option.value %> (<%= question_option.answers_count %>) + <% end %> <% end %> <% end %> diff --git a/app/views/legislation/questions/show.html.erb b/app/views/legislation/questions/show.html.erb index d22289d28..eda42d239 100644 --- a/app/views/legislation/questions/show.html.erb +++ b/app/views/legislation/questions/show.html.erb @@ -23,16 +23,19 @@

    <%= @question.title %>

    -
    - <% @question.question_options.each do |question_option| %> - + <% if @question.question_options.any? %> + <%= form_for @answer, url: legislation_process_question_answers_path(@process, @question, @answer), class: "controls-stacked" do |f| %> + <% @question.question_options.each do |question_option| %> + + <% end %> + <%= f.submit t('.answer_question'), class: "button" unless @answer.persisted? %> <% end %> -
    -
    + <% end %> +