From e9e339fa50f5773e76c2b0de6db07565bc4ce5cb Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 14 Sep 2015 16:43:32 +0200 Subject: [PATCH] adds responsible name to proposals --- app/controllers/proposals_controller.rb | 2 +- app/models/proposal.rb | 20 ++++++++ app/views/proposals/_form.html.erb | 7 +++ config/locales/en.yml | 1 + config/locales/es.yml | 1 + ...0914113251_add_responsible_to_proposals.rb | 5 ++ db/schema.rb | 6 ++- spec/factories.rb | 12 +++++ spec/features/proposals_spec.rb | 48 +++++++++++++++++++ spec/models/proposal_spec.rb | 33 +++++++++++-- 10 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20150914113251_add_responsible_to_proposals.rb diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 4e6b6bacc..fabb77d28 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -75,7 +75,7 @@ class ProposalsController < ApplicationController private def proposal_params - params.require(:proposal).permit(:title, :question, :description, :external_url, :tag_list, :terms_of_service, :captcha, :captcha_key) + params.require(:proposal).permit(:title, :question, :description, :external_url, :responsible_name, :tag_list, :terms_of_service, :captcha, :captcha_key) end def load_featured_tags diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 913b23fcc..6e0930955 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -14,15 +14,18 @@ class Proposal < ActiveRecord::Base validates :question, presence: true validates :description, presence: true validates :author, presence: true + validates :responsible_name, presence: true validate :validate_title_length validate :validate_question_length validate :validate_description_length + validate :validate_responsible_length validates :terms_of_service, acceptance: { allow_nil: false }, on: :create before_validation :sanitize_description before_validation :sanitize_tag_list + before_validation :set_responsible_name scope :for_render, -> { includes(:tags) } scope :sort_by_hot_score , -> { order(hot_score: :desc) } @@ -96,6 +99,10 @@ class Proposal < ActiveRecord::Base 6000 end + def self.responsible_name_max_length + 60 + end + def self.search(terms) terms.present? ? where("title ILIKE ? OR description ILIKE ? OR question ILIKE ?", "%#{terms}%", "%#{terms}%", "%#{terms}%") : none end @@ -114,6 +121,11 @@ class Proposal < ActiveRecord::Base self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list) end + def set_responsible_name + if author && author.level_two_or_three_verified? + self.responsible_name = author.document_number + end + end private def validate_description_length @@ -140,4 +152,12 @@ class Proposal < ActiveRecord::Base validator.validate(self) end + def validate_responsible_length + validator = ActiveModel::Validations::LengthValidator.new( + attributes: :title, + minimum: 6, + maximum: Proposal.responsible_name_max_length) + validator.validate(self) + end + end diff --git a/app/views/proposals/_form.html.erb b/app/views/proposals/_form.html.erb index ce2714954..f2a2f6362 100644 --- a/app/views/proposals/_form.html.erb +++ b/app/views/proposals/_form.html.erb @@ -33,6 +33,13 @@ <%= f.text_field :tag_list, value: @proposal.tag_list.to_s, label: false, placeholder: t("proposals.form.tags_placeholder"), class: 'js-tag-list' %> + <% if current_user.unverified? %> +
+ <%= f.label :responsible_name, t("proposals.form.proposal_responsible_name") %> + <%= f.text_field :responsible_name, placeholder: t("proposals.form.proposal_responsible_name"), label: false %> +
+ <% end %> +
<% if @proposal.new_record? %> <%= f.label :terms_of_service do %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 8cdfb150e..fea3d74ac 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -174,6 +174,7 @@ en: proposal_question: Proposal question proposal_text: Initial text for proposal proposal_external_url: Link to additional documentation + proposal_responsible_name: "First and last name of the person making this proposal" tags_label: Topics tags_instructions: > Tag this proposal. You can choose among our proposals on the list or add any other topic you want. diff --git a/config/locales/es.yml b/config/locales/es.yml index a7c4f8304..12144cdb6 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -176,6 +176,7 @@ es: proposal_question: Pregunta de la propuesta proposal_text: Texto inicial de la propuesta proposal_external_url: Enlace a documentación adicional + proposal_responsible_name: "Nombre y apellidos de la persona que hace esta propuesta" tags_label: Temas tags_instructions: > Etiqueta esta propuesta. Puedes elegir entre nuestras propuestas o introducir las que desees. diff --git a/db/migrate/20150914113251_add_responsible_to_proposals.rb b/db/migrate/20150914113251_add_responsible_to_proposals.rb new file mode 100644 index 000000000..c565c29df --- /dev/null +++ b/db/migrate/20150914113251_add_responsible_to_proposals.rb @@ -0,0 +1,5 @@ +class AddResponsibleToProposals < ActiveRecord::Migration + def change + add_column :proposals, :responsible_name, :string, limit: 60 + end +end diff --git a/db/schema.rb b/db/schema.rb index 40408573d..b8d4cc424 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,10 +11,11 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150912145218) do +ActiveRecord::Schema.define(version: 20150914113251) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + enable_extension "unaccent" create_table "addresses", force: :cascade do |t| t.integer "user_id" @@ -165,7 +166,7 @@ ActiveRecord::Schema.define(version: 20150912145218) do create_table "locks", force: :cascade do |t| t.integer "user_id" t.integer "tries", default: 0 - t.datetime "locked_until", default: '2015-09-11 17:24:30', null: false + t.datetime "locked_until", default: '2015-09-10 13:46:11', null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end @@ -204,6 +205,7 @@ ActiveRecord::Schema.define(version: 20150912145218) do t.integer "confidence_score", default: 0 t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "responsible_name", limit: 60 end create_table "settings", force: :cascade do |t| diff --git a/spec/factories.rb b/spec/factories.rb index c9047c675..ae6a15cab 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -7,6 +7,17 @@ FactoryGirl.define do terms_of_service '1' confirmed_at { Time.now } + trait :level_two do + residence_verified_at Time.now + confirmed_phone "611111111" + document_number "12345678Z" + end + + trait :level_three do + verified_at Time.now + document_number "12345678Z" + end + trait :hidden do hidden_at Time.now end @@ -106,6 +117,7 @@ FactoryGirl.define do description 'Proposal description' question 'Proposal question' external_url 'http://external_documention.es' + responsible_name 'John Snow' terms_of_service '1' association :author, factory: :user diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index 7d146efaa..fc5f68185 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -61,6 +61,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: 'This is very important because...' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -75,6 +76,45 @@ feature 'Proposals' do expect(page).to have_content I18n.l(Proposal.last.created_at.to_date) end + scenario 'Responsible name is stored for anonymous users' do + author = create(:user) + login_as(author) + + visit new_proposal_path + fill_in 'proposal_title', with: 'Help refugees' + fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' + fill_in 'proposal_description', with: 'This is very important because...' + fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' + fill_in 'proposal_captcha', with: correct_captcha_text + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' + check 'proposal_terms_of_service' + + click_button 'Start a proposal' + + expect(page).to have_content 'Proposal was successfully created.' + expect(Proposal.last.responsible_name).to eq('Isabel Garcia') + end + + scenario 'Responsible name field is not shown for verified users' do + author = create(:user, :level_two) + login_as(author) + + visit new_proposal_path + expect(page).to_not have_selector('#proposal_responsible_name') + + fill_in 'proposal_title', with: 'Help refugees' + fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' + fill_in 'proposal_description', with: 'This is very important because...' + fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_captcha', with: correct_captcha_text + check 'proposal_terms_of_service' + + click_button 'Start a proposal' + + expect(page).to have_content 'Proposal was successfully created.' + end + scenario 'Captcha is required for proposal creation' do login_as(create(:user)) @@ -83,6 +123,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: 'Very important issue...' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: "wrongText!" check 'proposal_terms_of_service' @@ -107,6 +148,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: 'Very important issue...' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -138,6 +180,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: '

This is

' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -158,6 +201,7 @@ feature 'Proposals' do fill_in 'proposal_title', with: 'Testing auto link' fill_in 'proposal_question', with: 'Should I stay or should I go?' fill_in 'proposal_description', with: '

This is a link www.example.org

' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -176,6 +220,7 @@ feature 'Proposals' do fill_in 'proposal_title', with: 'Testing auto link' fill_in 'proposal_question', with: 'Should I stay or should I go?' fill_in 'proposal_description', with: " click me http://example.org" + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -212,6 +257,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in_ckeditor 'proposal_description', with: 'A description with enough characters' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -234,6 +280,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: 'A description suitable for this test' fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text check 'proposal_terms_of_service' @@ -284,6 +331,7 @@ feature 'Proposals' do fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?' fill_in 'proposal_description', with: "Let's do something to end child poverty" fill_in 'proposal_external_url', with: 'http://rescue.org/refugees' + fill_in 'proposal_responsible_name', with: 'Isabel Garcia' fill_in 'proposal_captcha', with: correct_captcha_text click_button "Save changes" diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb index 62505ed08..6c835bee8 100644 --- a/spec/models/proposal_spec.rb +++ b/spec/models/proposal_spec.rb @@ -12,13 +12,13 @@ describe Proposal do expect(proposal).to_not be_valid end - it "should not be valid without a question" do - proposal.question = nil + it "should not be valid without a title" do + proposal.title = nil expect(proposal).to_not be_valid end - it "should not be valid without a title" do - proposal.title = nil + it "should not be valid without a question" do + proposal.question = nil expect(proposal).to_not be_valid end @@ -35,6 +35,31 @@ describe Proposal do end end + describe "#responsible" do + it "should be mandatory" do + proposal.responsible_name = nil + expect(proposal).to_not be_valid + end + + it "should be the document_number if level two user" do + author = create(:user, :level_two, document_number: "12345678Z") + proposal.author = author + proposal.responsible_name = nil + + expect(proposal).to be_valid + proposal.responsible_name = "12345678Z" + end + + it "should be the document_number if level two user" do + author = create(:user, :level_three, document_number: "12345678Z") + proposal.author = author + proposal.responsible_name = nil + + expect(proposal).to be_valid + proposal.responsible_name = "12345678Z" + end + end + it "should sanitize the tag list" do proposal.tag_list = "user_id=1" proposal.valid?