adds responsible name to proposals
This commit is contained in:
@@ -75,7 +75,7 @@ class ProposalsController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def proposal_params
|
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
|
end
|
||||||
|
|
||||||
def load_featured_tags
|
def load_featured_tags
|
||||||
|
|||||||
@@ -14,15 +14,18 @@ class Proposal < ActiveRecord::Base
|
|||||||
validates :question, presence: true
|
validates :question, presence: true
|
||||||
validates :description, presence: true
|
validates :description, presence: true
|
||||||
validates :author, presence: true
|
validates :author, presence: true
|
||||||
|
validates :responsible_name, presence: true
|
||||||
|
|
||||||
validate :validate_title_length
|
validate :validate_title_length
|
||||||
validate :validate_question_length
|
validate :validate_question_length
|
||||||
validate :validate_description_length
|
validate :validate_description_length
|
||||||
|
validate :validate_responsible_length
|
||||||
|
|
||||||
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
|
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
|
||||||
|
|
||||||
before_validation :sanitize_description
|
before_validation :sanitize_description
|
||||||
before_validation :sanitize_tag_list
|
before_validation :sanitize_tag_list
|
||||||
|
before_validation :set_responsible_name
|
||||||
|
|
||||||
scope :for_render, -> { includes(:tags) }
|
scope :for_render, -> { includes(:tags) }
|
||||||
scope :sort_by_hot_score , -> { order(hot_score: :desc) }
|
scope :sort_by_hot_score , -> { order(hot_score: :desc) }
|
||||||
@@ -96,6 +99,10 @@ class Proposal < ActiveRecord::Base
|
|||||||
6000
|
6000
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.responsible_name_max_length
|
||||||
|
60
|
||||||
|
end
|
||||||
|
|
||||||
def self.search(terms)
|
def self.search(terms)
|
||||||
terms.present? ? where("title ILIKE ? OR description ILIKE ? OR question ILIKE ?", "%#{terms}%", "%#{terms}%", "%#{terms}%") : none
|
terms.present? ? where("title ILIKE ? OR description ILIKE ? OR question ILIKE ?", "%#{terms}%", "%#{terms}%", "%#{terms}%") : none
|
||||||
end
|
end
|
||||||
@@ -114,6 +121,11 @@ class Proposal < ActiveRecord::Base
|
|||||||
self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list)
|
self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_responsible_name
|
||||||
|
if author && author.level_two_or_three_verified?
|
||||||
|
self.responsible_name = author.document_number
|
||||||
|
end
|
||||||
|
end
|
||||||
private
|
private
|
||||||
|
|
||||||
def validate_description_length
|
def validate_description_length
|
||||||
@@ -140,4 +152,12 @@ class Proposal < ActiveRecord::Base
|
|||||||
validator.validate(self)
|
validator.validate(self)
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@@ -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' %>
|
<%= f.text_field :tag_list, value: @proposal.tag_list.to_s, label: false, placeholder: t("proposals.form.tags_placeholder"), class: 'js-tag-list' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% if current_user.unverified? %>
|
||||||
|
<div class="small-12 column">
|
||||||
|
<%= f.label :responsible_name, t("proposals.form.proposal_responsible_name") %>
|
||||||
|
<%= f.text_field :responsible_name, placeholder: t("proposals.form.proposal_responsible_name"), label: false %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div class="small-12 column">
|
<div class="small-12 column">
|
||||||
<% if @proposal.new_record? %>
|
<% if @proposal.new_record? %>
|
||||||
<%= f.label :terms_of_service do %>
|
<%= f.label :terms_of_service do %>
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ en:
|
|||||||
proposal_question: Proposal question
|
proposal_question: Proposal question
|
||||||
proposal_text: Initial text for proposal
|
proposal_text: Initial text for proposal
|
||||||
proposal_external_url: Link to additional documentation
|
proposal_external_url: Link to additional documentation
|
||||||
|
proposal_responsible_name: "First and last name of the person making this proposal"
|
||||||
tags_label: Topics
|
tags_label: Topics
|
||||||
tags_instructions: >
|
tags_instructions: >
|
||||||
Tag this proposal. You can choose among our proposals on the list or add any other topic you want.
|
Tag this proposal. You can choose among our proposals on the list or add any other topic you want.
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ es:
|
|||||||
proposal_question: Pregunta de la propuesta
|
proposal_question: Pregunta de la propuesta
|
||||||
proposal_text: Texto inicial de la propuesta
|
proposal_text: Texto inicial de la propuesta
|
||||||
proposal_external_url: Enlace a documentación adicional
|
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_label: Temas
|
||||||
tags_instructions: >
|
tags_instructions: >
|
||||||
Etiqueta esta propuesta. Puedes elegir entre nuestras propuestas o introducir las que desees.
|
Etiqueta esta propuesta. Puedes elegir entre nuestras propuestas o introducir las que desees.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddResponsibleToProposals < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :proposals, :responsible_name, :string, limit: 60
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,10 +11,11 @@
|
|||||||
#
|
#
|
||||||
# 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: 20150912145218) do
|
ActiveRecord::Schema.define(version: 20150914113251) 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"
|
||||||
|
enable_extension "unaccent"
|
||||||
|
|
||||||
create_table "addresses", force: :cascade do |t|
|
create_table "addresses", force: :cascade do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
@@ -165,7 +166,7 @@ ActiveRecord::Schema.define(version: 20150912145218) do
|
|||||||
create_table "locks", force: :cascade do |t|
|
create_table "locks", force: :cascade do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.integer "tries", default: 0
|
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 "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
end
|
end
|
||||||
@@ -204,6 +205,7 @@ ActiveRecord::Schema.define(version: 20150912145218) do
|
|||||||
t.integer "confidence_score", default: 0
|
t.integer "confidence_score", default: 0
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.string "responsible_name", limit: 60
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "settings", force: :cascade do |t|
|
create_table "settings", force: :cascade do |t|
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ FactoryGirl.define do
|
|||||||
terms_of_service '1'
|
terms_of_service '1'
|
||||||
confirmed_at { Time.now }
|
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
|
trait :hidden do
|
||||||
hidden_at Time.now
|
hidden_at Time.now
|
||||||
end
|
end
|
||||||
@@ -106,6 +117,7 @@ FactoryGirl.define do
|
|||||||
description 'Proposal description'
|
description 'Proposal description'
|
||||||
question 'Proposal question'
|
question 'Proposal question'
|
||||||
external_url 'http://external_documention.es'
|
external_url 'http://external_documention.es'
|
||||||
|
responsible_name 'John Snow'
|
||||||
terms_of_service '1'
|
terms_of_service '1'
|
||||||
association :author, factory: :user
|
association :author, factory: :user
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ feature 'Proposals' do
|
|||||||
fill_in 'proposal_question', with: '¿Would you like to give assistance to war 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_description', with: 'This is very important because...'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
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)
|
expect(page).to have_content I18n.l(Proposal.last.created_at.to_date)
|
||||||
end
|
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
|
scenario 'Captcha is required for proposal creation' do
|
||||||
login_as(create(:user))
|
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_question', with: '¿Would you like to give assistance to war refugees?'
|
||||||
fill_in 'proposal_description', with: 'Very important issue...'
|
fill_in 'proposal_description', with: 'Very important issue...'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
||||||
|
fill_in 'proposal_responsible_name', with: 'Isabel Garcia'
|
||||||
fill_in 'proposal_captcha', with: "wrongText!"
|
fill_in 'proposal_captcha', with: "wrongText!"
|
||||||
check 'proposal_terms_of_service'
|
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_question', with: '¿Would you like to give assistance to war refugees?'
|
||||||
fill_in 'proposal_description', with: 'Very important issue...'
|
fill_in 'proposal_description', with: 'Very important issue...'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
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_question', with: '¿Would you like to give assistance to war refugees?'
|
||||||
fill_in 'proposal_description', with: '<p>This is <script>alert("an attack");</script></p>'
|
fill_in 'proposal_description', with: '<p>This is <script>alert("an attack");</script></p>'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
check 'proposal_terms_of_service'
|
||||||
|
|
||||||
@@ -158,6 +201,7 @@ feature 'Proposals' do
|
|||||||
fill_in 'proposal_title', with: 'Testing auto link'
|
fill_in 'proposal_title', with: 'Testing auto link'
|
||||||
fill_in 'proposal_question', with: 'Should I stay or should I go?'
|
fill_in 'proposal_question', with: 'Should I stay or should I go?'
|
||||||
fill_in 'proposal_description', with: '<p>This is a link www.example.org</p>'
|
fill_in 'proposal_description', with: '<p>This is a link www.example.org</p>'
|
||||||
|
fill_in 'proposal_responsible_name', with: 'Isabel Garcia'
|
||||||
fill_in 'proposal_captcha', with: correct_captcha_text
|
fill_in 'proposal_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
check 'proposal_terms_of_service'
|
||||||
|
|
||||||
@@ -176,6 +220,7 @@ feature 'Proposals' do
|
|||||||
fill_in 'proposal_title', with: 'Testing auto link'
|
fill_in 'proposal_title', with: 'Testing auto link'
|
||||||
fill_in 'proposal_question', with: 'Should I stay or should I go?'
|
fill_in 'proposal_question', with: 'Should I stay or should I go?'
|
||||||
fill_in 'proposal_description', with: "<script>alert('hey')</script> <a href=\"javascript:alert('surprise!')\">click me<a/> http://example.org"
|
fill_in 'proposal_description', with: "<script>alert('hey')</script> <a href=\"javascript:alert('surprise!')\">click me<a/> http://example.org"
|
||||||
|
fill_in 'proposal_responsible_name', with: 'Isabel Garcia'
|
||||||
fill_in 'proposal_captcha', with: correct_captcha_text
|
fill_in 'proposal_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
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 '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_ckeditor 'proposal_description', with: 'A description with enough characters'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
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_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_description', with: 'A description suitable for this test'
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
check 'proposal_terms_of_service'
|
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_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_description', with: "Let's do something to end child poverty"
|
||||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
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_captcha', with: correct_captcha_text
|
||||||
|
|
||||||
click_button "Save changes"
|
click_button "Save changes"
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ describe Proposal do
|
|||||||
expect(proposal).to_not be_valid
|
expect(proposal).to_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not be valid without a question" do
|
it "should not be valid without a title" do
|
||||||
proposal.question = nil
|
proposal.title = nil
|
||||||
expect(proposal).to_not be_valid
|
expect(proposal).to_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not be valid without a title" do
|
it "should not be valid without a question" do
|
||||||
proposal.title = nil
|
proposal.question = nil
|
||||||
expect(proposal).to_not be_valid
|
expect(proposal).to_not be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -35,6 +35,31 @@ describe Proposal do
|
|||||||
end
|
end
|
||||||
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
|
it "should sanitize the tag list" do
|
||||||
proposal.tag_list = "user_id=1"
|
proposal.tag_list = "user_id=1"
|
||||||
proposal.valid?
|
proposal.valid?
|
||||||
|
|||||||
Reference in New Issue
Block a user