From 7a50d2064cbf5e36f950a32f81974a7d8dfd6677 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 2 Aug 2015 13:35:48 +0200 Subject: [PATCH 01/21] adds voting methods to comment model [#25] --- app/models/comment.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/comment.rb b/app/models/comment.rb index 91d7447c0..e99ef15e3 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,6 @@ class Comment < ActiveRecord::Base acts_as_nested_set scope: [:commentable_id, :commentable_type] + acts_as_votable validates :body, presence: true validates :user, presence: true From 44ae7078ea95d78b5c9fbc565a38378fc9275819 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 2 Aug 2015 13:36:08 +0200 Subject: [PATCH 02/21] adds routes to votable comments and debates [#25] [#25] --- config/routes.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index f5afd988c..58e23310d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,9 +6,17 @@ Rails.application.routes.draw do # You can have the root of your site routed with "root" root 'debates#index' + + concern :votable do |options| + resources :votes, options.merge(only: :create) + end + resources :debates do - resources :votes, only: :create - resources :comments, only: :create + concerns :votable, votable_type: 'debate' + + resources :comments, only: :create do + concerns :votable, votable_type: 'comment' + end end resource :account, controller: "account", only: [:show, :update] From 2a3086010ec14992bcc0b4fbc92934df90193495 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 2 Aug 2015 13:37:37 +0200 Subject: [PATCH 03/21] adds voting for comments functionality [#25] --- app/controllers/votes_controller.rb | 23 +++++++++++++++++--- app/views/comments/_comment.html.erb | 5 +++++ app/views/comments/_votes.html.erb | 11 ++++++++++ app/views/{votes => debates}/_votes.html.erb | 0 app/views/debates/show.html.erb | 4 ++-- app/views/votes/create.js.erb | 3 ++- 6 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 app/views/comments/_votes.html.erb rename app/views/{votes => debates}/_votes.html.erb (100%) diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb index e93968f35..c42935ddf 100644 --- a/app/controllers/votes_controller.rb +++ b/app/controllers/votes_controller.rb @@ -1,21 +1,38 @@ class VotesController < ApplicationController before_action :set_debate + before_action :set_resource before_action :authenticate_user! respond_to :html, :js - + def create register_vote - notice = @debate.vote_registered? ? I18n.t("votes.notice_thanks") : I18n.t("votes.notice_already_registered") respond_with @debate end private + def set_resource + @resource = resource_model.find(params["#{resource_name + "_id"}"]) + end + + def resource_name + @resource_name ||= params[:votable_type] + end + + def resource_model + resource_name.capitalize.constantize + end + def set_debate @debate = Debate.find(params[:debate_id]) end def register_vote - @debate.vote_by voter: current_user, vote: params[:value] + @resource.vote_by voter: current_user, vote: params[:value] end + + def notice + @resource.vote_registered? ? I18n.t("votes.notice_thanks") : I18n.t("votes.notice_already_registered") + end + end diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb index 0d152d928..50c033670 100644 --- a/app/views/comments/_comment.html.erb +++ b/app/views/comments/_comment.html.erb @@ -8,6 +8,11 @@ <%= comment.user.name %> • <%= time_ago_in_words(comment.created_at) %>

<%= comment.body %>

+ + + <%= render 'comments/votes', comment: comment %> + +

<%= render 'comments/form', parent: comment %>

diff --git a/app/views/comments/_votes.html.erb b/app/views/comments/_votes.html.erb new file mode 100644 index 000000000..24b7dd869 --- /dev/null +++ b/app/views/comments/_votes.html.erb @@ -0,0 +1,11 @@ + + <%= link_to "up", debate_comment_votes_path(@debate, comment, value: 'yes'), + method: "post", remote: true %> + <%= comment.get_likes.size %> + + + + <%= link_to "down", debate_comment_votes_path(@debate, comment, value: 'no'), + method: "post", remote: true %> + <%= comment.get_dislikes.size %> + \ No newline at end of file diff --git a/app/views/votes/_votes.html.erb b/app/views/debates/_votes.html.erb similarity index 100% rename from app/views/votes/_votes.html.erb rename to app/views/debates/_votes.html.erb diff --git a/app/views/debates/show.html.erb b/app/views/debates/show.html.erb index 3ae0cace4..8ea945eee 100644 --- a/app/views/debates/show.html.erb +++ b/app/views/debates/show.html.erb @@ -17,8 +17,8 @@

<%= render 'shared/tags', debate: @debate %>

-
- <%= render 'votes/votes' %> +
+ <%= render 'debates/votes' %>
diff --git a/app/views/votes/create.js.erb b/app/views/votes/create.js.erb index 5e855e40e..2953d8a25 100644 --- a/app/views/votes/create.js.erb +++ b/app/views/votes/create.js.erb @@ -1 +1,2 @@ -$("#votes").html("<%= j render('votes') %>"); \ No newline at end of file +$("#<%= dom_id(@resource) %>_votes"). + html('<%= j render("#{@resource_name.pluralize}/votes", comment: @resource) %>'); \ No newline at end of file From cce6ca2fb9792559a613ae1500c23b27c6de3ec1 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 2 Aug 2015 13:37:50 +0200 Subject: [PATCH 04/21] adds feature specs [#25] --- spec/features/votes_spec.rb | 199 +++++++++++++++++++++++++----------- 1 file changed, 139 insertions(+), 60 deletions(-) diff --git a/spec/features/votes_spec.rb b/spec/features/votes_spec.rb index d1aabd84a..4d20724b2 100644 --- a/spec/features/votes_spec.rb +++ b/spec/features/votes_spec.rb @@ -2,74 +2,153 @@ require 'rails_helper' feature 'Votes' do - background do - @manuela = create(:user) - @pablo = create(:user) - @debate = create(:debate) + feature 'Debates' do + + background do + @manuela = create(:user) + @pablo = create(:user) + @debate = create(:debate) + + login_as(@manuela) + visit debate_path(@debate) + end + + scenario 'Show' do + vote = create(:vote, voter: @manuela, votable: @debate, vote_flag: true) + vote = create(:vote, voter: @pablo, votable: @debate, vote_flag: false) + + visit debate_path(@debate) + + expect(page).to have_content "2 votes" + + within('#in_favor') do + expect(page).to have_content "50%" + end + + within('#against') do + expect(page).to have_content "50%" + end + end + + scenario 'Create', :js do + find('#in_favor a').click + + within('#in_favor') do + expect(page).to have_content "100%" + end + + within('#against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" + end + + scenario 'Update', :js do + find('#in_favor a').click + find('#against a').click + + within('#in_favor') do + expect(page).to have_content "0%" + end + + within('#against') do + expect(page).to have_content "100%" + end + + expect(page).to have_content "1 vote" + end + + scenario 'Trying to vote multiple times', :js do + find('#in_favor a').click + find('#in_favor a').click + + within('#in_favor') do + expect(page).to have_content "100%" + end + + within('#against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" + end - login_as(@manuela) - visit debate_path(@debate) end - scenario 'Show' do - vote = create(:vote, voter: @manuela, votable: @debate, vote_flag: true) - vote = create(:vote, voter: @pablo, votable: @debate, vote_flag: false) - visit debate_path(@debate) + feature 'Comments' do - expect(page).to have_content "2 votes" + background do + @manuela = create(:user) + @pablo = create(:user) + @debate = create(:debate) + @comment = create(:comment, commentable: @debate) - within('#in_favor') do - expect(page).to have_content "50%" + login_as(@manuela) + visit debate_path(@debate) end - within('#against') do - expect(page).to have_content "50%" + scenario 'Show' do + vote = create(:vote, voter: @manuela, votable: @comment, vote_flag: true) + vote = create(:vote, voter: @pablo, votable: @comment, vote_flag: false) + + visit debate_path(@debate) + + within("#comment_#{@comment.id}_votes") do + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "1" + end + end end + + scenario 'Create', :js do + within("#comment_#{@comment.id}_votes") do + find(".in_favor a").click + + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "0" + end + end + end + + scenario 'Update', :js do + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.against a').click + + within('.in_favor') do + expect(page).to have_content "0" + end + + within('.against') do + expect(page).to have_content "1" + end + end + end + + scenario 'Trying to vote multiple times', :js do + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.in_favor a').click + + within('.in_favor') do + expect(page).to have_content "1" + end + + within('.against') do + expect(page).to have_content "0" + end + end + end + end - - scenario 'Create', :js do - find('#in_favor a').click - - within('#in_favor') do - expect(page).to have_content "100%" - end - - within('#against') do - expect(page).to have_content "0%" - end - - expect(page).to have_content "1 vote" - end - - scenario 'Update', :js do - find('#in_favor a').click - find('#against a').click - - within('#in_favor') do - expect(page).to have_content "0%" - end - - within('#against') do - expect(page).to have_content "100%" - end - - expect(page).to have_content "1 vote" - end - - scenario 'Trying to vote multiple times', :js do - find('#in_favor a').click - find('#in_favor a').click - - within('#in_favor') do - expect(page).to have_content "100%" - end - - within('#against') do - expect(page).to have_content "0%" - end - - expect(page).to have_content "1 vote" - end - end \ No newline at end of file From 823426bfded234f80f55580c32efdb9516b935aa Mon Sep 17 00:00:00 2001 From: rgarcia Date: Tue, 4 Aug 2015 12:54:24 +0200 Subject: [PATCH 05/21] verify captcha only when captcha keys present --- app/controllers/application_controller.rb | 5 +++++ app/controllers/debates_controller.rb | 9 ++------- app/controllers/registrations_controller.rb | 7 ++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b64f11bb4..d6cda45be 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,4 +7,9 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + def verify_captcha?(resource) + return true unless recaptcha_keys? + verify_recaptcha(model: resource) + end end diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 672f41d20..e75f9a2fb 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -1,5 +1,5 @@ class DebatesController < ApplicationController - include RecaptchaHelper + include RecaptchaHelper before_action :set_debate, only: [:show, :edit, :update] before_action :authenticate_user!, except: [:show, :index] before_action :validate_ownership, only: [:edit, :update] @@ -25,7 +25,7 @@ class DebatesController < ApplicationController def create @debate = Debate.new(debate_params) @debate.author = current_user - if verify_captcha? and @debate.save + if verify_captcha?(@debate) and @debate.save redirect_to @debate, notice: t('flash.actions.create.notice', resource_name: 'Debate') else render :new @@ -51,9 +51,4 @@ class DebatesController < ApplicationController raise ActiveRecord::RecordNotFound unless @debate.editable_by?(current_user) end - def verify_captcha? - return true unless recaptcha_keys? - verify_recaptcha(model: @debate) - end - end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 07b347cdc..c0113de42 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,15 +1,16 @@ class RegistrationsController < Devise::RegistrationsController + include RecaptchaHelper def create - if verify_recaptcha + if verify_captcha?(resource) super else build_resource(sign_up_params) flash.now[:alert] = t('recaptcha.errors.verification_failed') render :new - end + end end - + private From 16549f90c43be9c388600abc060111470cf75125 Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 4 Aug 2015 17:58:30 +0200 Subject: [PATCH 06/21] Adds badges for travis, code climate and gemnasium --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 648cefd8d..5405cec86 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Aplicación de Participación Ciudadana del Ayuntamiento de Madrid +[![Build Status](https://travis-ci.org/AyuntamientoMadrid/participacion.svg?branch=master)](https://travis-ci.org/AyuntamientoMadrid/participacion) +[![Code Climate](https://codeclimate.com/github/AyuntamientoMadrid/participacion/badges/gpa.svg)](https://codeclimate.com/github/AyuntamientoMadrid/participacion) +[![Dependency Status](https://gemnasium.com/AyuntamientoMadrid/participacion.svg)](https://gemnasium.com/AyuntamientoMadrid/participacion) + Este es el repositorio de código abierto de la Aplicación de Participación Ciudadana del Ayuntamiento de Madrid. ## Estado del proyecto From 90e577c811c154fe900d57a884f8a2eb96a2c329 Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 4 Aug 2015 18:40:58 +0200 Subject: [PATCH 07/21] Adds feature for debate description --- spec/features/debates_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb index 034b1d504..df9a4a92c 100644 --- a/spec/features/debates_spec.rb +++ b/spec/features/debates_spec.rb @@ -45,21 +45,22 @@ feature 'Debates' do expect(page).to have_content I18n.l(Date.today) end - scenario 'JS injection is sanitized' do + scenario 'JS injection is prevented but safe html is respected' do author = create(:user) login_as(author) visit new_debate_path fill_in 'debate_title', with: 'A test' - fill_in 'debate_description', with: 'This is ' + fill_in 'debate_description', with: '

This is

' check 'debate_terms_of_service' click_button 'Create Debate' expect(page).to have_content 'Debate was successfully created.' expect(page).to have_content 'A test' - expect(page).to have_content 'This is alert("an attack");' + expect(page.html).to include '

This is alert("an attack");

' expect(page.html).to_not include '' + expect(page.html).to_not include '<p>This is' end scenario 'tagging using dangerous strings' do From 1fa4087befa0be1138135f04010b5d72375077b5 Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 4 Aug 2015 18:42:05 +0200 Subject: [PATCH 08/21] Removes all the extra sanitisation from debates This makes the feature red --- app/views/debates/_debate.html.erb | 2 +- app/views/debates/show.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/debates/_debate.html.erb b/app/views/debates/_debate.html.erb index 4253143a6..6cc218e7a 100644 --- a/app/views/debates/_debate.html.erb +++ b/app/views/debates/_debate.html.erb @@ -5,7 +5,7 @@

<%= link_to debate.title, debate %>

Por <%= debate.author.name %> el <%= l debate.created_at.to_date %>

-

<%= sanitize(debate.description.html_safe) %>

+

<%= debate.description %>

<%= render 'shared/tags', debate: debate %>

diff --git a/app/views/debates/show.html.erb b/app/views/debates/show.html.erb index c9ce7abf1..21f23cdb7 100644 --- a/app/views/debates/show.html.erb +++ b/app/views/debates/show.html.erb @@ -14,7 +14,7 @@ <%= @debate.author.name %>  •  <%= l @debate.created_at.to_date %>  •  <%= pluralize(@debate.comment_threads.count, t("debates.show.comment"), t("debates.show.comments")) %>
- <%= @debate.description.html_safe %> + <%= @debate.description %>

<%= render 'shared/tags', debate: @debate %>

From 87dd655d70dfd13284ac74d62e00446e16c53184 Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 4 Aug 2015 18:42:49 +0200 Subject: [PATCH 09/21] Make debate.description always html_safe --- app/models/debate.rb | 4 ++++ spec/models/debate_spec.rb | 23 +++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/models/debate.rb b/app/models/debate.rb index d82cfb8ac..836e3bf34 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -35,6 +35,10 @@ class Debate < ActiveRecord::Base editable? && author == user end + def description + super.try :html_safe + end + protected def sanitize_description diff --git a/spec/models/debate_spec.rb b/spec/models/debate_spec.rb index f2af2cf0a..00f6217bd 100644 --- a/spec/models/debate_spec.rb +++ b/spec/models/debate_spec.rb @@ -20,15 +20,22 @@ describe Debate do expect(@debate).to_not be_valid end - it "should not be valid without a description" do - @debate.description = nil - expect(@debate).to_not be_valid - end + describe "#description" do + it "should be mandatory" do + @debate.description = nil + expect(@debate).to_not be_valid + end - it "should sanitize the description" do - @debate.description = "" - @debate.valid? - expect(@debate.description).to eq("alert('danger');") + it "should be sanitized" do + @debate.description = "" + @debate.valid? + expect(@debate.description).to eq("alert('danger');") + end + + it "should be html_safe" do + @debate.description = "" + expect(@debate.description).to be_html_safe + end end it "should sanitize the tag list" do From 7915f9d77cab1d13a0642186048dfb26007c5fb2 Mon Sep 17 00:00:00 2001 From: Juan Ortiz Date: Tue, 4 Aug 2015 18:21:00 -0500 Subject: [PATCH 10/21] rake:schema_load to rake:schema:load --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 648cefd8d..bc16cc385 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ cd participacion bundle install cp config/database.yml.example config/database.yml cp config/secrets.yml.example config/secrets.yml -bundle exec bin/rake db:create db:schema_load -RAILS_ENV=test bundle exec rake db:create db:schema_load +bundle exec bin/rake db:create db:schema:load +RAILS_ENV=test bundle exec rake db:create db:schema:load ``` Para ejecutar la aplicación en local: From 08fdc768b2a514f97b27436cd371f7c5fe2f8105 Mon Sep 17 00:00:00 2001 From: kikito Date: Wed, 5 Aug 2015 12:17:27 +0200 Subject: [PATCH 11/21] fix wrong merge with master --- app/controllers/debates_controller.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index c49241ff8..2e3a07e3e 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -51,10 +51,4 @@ class DebatesController < ApplicationController def validate_ownership raise ActiveRecord::RecordNotFound unless @debate.editable_by?(current_user) end - - def verify_captcha? - return true unless recaptcha_keys? - verify_recaptcha(model: @debate) - end - end From 91b52ad8d2df3c772cf9011d25173095ec5d38e2 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 12:12:56 +0200 Subject: [PATCH 12/21] refactors voting implementation [#25] --- app/controllers/comments_controller.rb | 8 +++++- app/controllers/debates_controller.rb | 10 +++++-- app/controllers/votes_controller.rb | 38 -------------------------- app/views/comments/_votes.html.erb | 4 +-- app/views/comments/vote.js.erb | 1 + app/views/debates/_votes.html.erb | 6 ++-- app/views/debates/vote.js.erb | 1 + app/views/votes/create.js.erb | 2 -- config/routes.rb | 17 ++++++------ 9 files changed, 31 insertions(+), 56 deletions(-) delete mode 100644 app/controllers/votes_controller.rb create mode 100644 app/views/comments/vote.js.erb create mode 100644 app/views/debates/vote.js.erb delete mode 100644 app/views/votes/create.js.erb diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 00fd20653..409bb7c9b 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,6 +1,6 @@ class CommentsController < ApplicationController before_action :authenticate_user! - before_action :set_debate, :set_parent + before_action :set_debate, :set_parent, only: :create respond_to :html, :js def create @@ -10,6 +10,12 @@ class CommentsController < ApplicationController respond_with @comment end + def vote + @comment = Comment.find(params[:id]) + @comment.vote_by(voter: current_user, vote: params[:value]) + respond_with @comment + end + private def comment_params params.require(:comments).permit(:commentable_type, :commentable_id, :body) diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 672f41d20..fe572abe4 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -1,7 +1,7 @@ class DebatesController < ApplicationController - include RecaptchaHelper - before_action :set_debate, only: [:show, :edit, :update] - before_action :authenticate_user!, except: [:show, :index] + include RecaptchaHelper + before_action :set_debate, only: [:show, :edit, :update, :vote] + before_action :authenticate_user!, except: [:index, :show, :vote] before_action :validate_ownership, only: [:edit, :update] def index @@ -37,6 +37,10 @@ class DebatesController < ApplicationController respond_with @debate end + def vote + @debate.vote_by(voter: current_user, vote: params[:value]) + end + private def set_debate diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb deleted file mode 100644 index c42935ddf..000000000 --- a/app/controllers/votes_controller.rb +++ /dev/null @@ -1,38 +0,0 @@ -class VotesController < ApplicationController - before_action :set_debate - before_action :set_resource - before_action :authenticate_user! - respond_to :html, :js - - def create - register_vote - respond_with @debate - end - - private - - def set_resource - @resource = resource_model.find(params["#{resource_name + "_id"}"]) - end - - def resource_name - @resource_name ||= params[:votable_type] - end - - def resource_model - resource_name.capitalize.constantize - end - - def set_debate - @debate = Debate.find(params[:debate_id]) - end - - def register_vote - @resource.vote_by voter: current_user, vote: params[:value] - end - - def notice - @resource.vote_registered? ? I18n.t("votes.notice_thanks") : I18n.t("votes.notice_already_registered") - end - -end diff --git a/app/views/comments/_votes.html.erb b/app/views/comments/_votes.html.erb index 24b7dd869..2f92ff246 100644 --- a/app/views/comments/_votes.html.erb +++ b/app/views/comments/_votes.html.erb @@ -1,11 +1,11 @@ - <%= link_to "up", debate_comment_votes_path(@debate, comment, value: 'yes'), + <%= link_to "up", vote_comment_path(comment, value: 'yes'), method: "post", remote: true %> <%= comment.get_likes.size %> - <%= link_to "down", debate_comment_votes_path(@debate, comment, value: 'no'), + <%= link_to "down", vote_comment_path(comment, value: 'no'), method: "post", remote: true %> <%= comment.get_dislikes.size %> \ No newline at end of file diff --git a/app/views/comments/vote.js.erb b/app/views/comments/vote.js.erb new file mode 100644 index 000000000..11f0ad905 --- /dev/null +++ b/app/views/comments/vote.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id(@comment) %>_votes").html('<%= j render("comments/votes", comment: @comment) %>'); \ No newline at end of file diff --git a/app/views/debates/_votes.html.erb b/app/views/debates/_votes.html.erb index fd2704ed4..1ed675ef1 100644 --- a/app/views/debates/_votes.html.erb +++ b/app/views/debates/_votes.html.erb @@ -1,6 +1,7 @@
- <%= link_to debate_votes_path(@debate, value: 'yes'), class: 'in-favor', method: "post", remote: true do %> + <%= link_to vote_debate_path(@debate, value: 'yes', partial: 'votes'), + class: 'in-favor', method: "post", remote: true do %> <%= percentage('likes', @debate) %> <% end %> @@ -9,7 +10,8 @@
- <%= link_to debate_votes_path(@debate, value: 'no'), class: 'against', method: "post", remote: true do %> + <%= link_to vote_debate_path(@debate, value: 'no', partial: 'votes'), + class: 'against', method: "post", remote: true do %> <%= percentage('dislikes', @debate) %> <% end %> diff --git a/app/views/debates/vote.js.erb b/app/views/debates/vote.js.erb new file mode 100644 index 000000000..e98725bb2 --- /dev/null +++ b/app/views/debates/vote.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id(@debate) %>_votes").html('<%= j render("debates/#{params[:partial]}", debate: @debate) %>'); \ No newline at end of file diff --git a/app/views/votes/create.js.erb b/app/views/votes/create.js.erb deleted file mode 100644 index 2953d8a25..000000000 --- a/app/views/votes/create.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$("#<%= dom_id(@resource) %>_votes"). - html('<%= j render("#{@resource_name.pluralize}/votes", comment: @resource) %>'); \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 58e23310d..ce179d8ac 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,16 +7,17 @@ Rails.application.routes.draw do # You can have the root of your site routed with "root" root 'debates#index' - concern :votable do |options| - resources :votes, options.merge(only: :create) - end - resources :debates do - concerns :votable, votable_type: 'debate' - - resources :comments, only: :create do - concerns :votable, votable_type: 'comment' + member do + post :vote end + + resources :comments, only: :create, shallow: true do + member do + post :vote + end + end + end resource :account, controller: "account", only: [:show, :update] From 5ce8db002bd0e31dd06ddd8512d5941be6cc0681 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 12:13:27 +0200 Subject: [PATCH 13/21] adds vote partial for debate index [#25] --- app/views/debates/_debate.html.erb | 23 +++-------------------- app/views/debates/_votes_min.html.erb | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 app/views/debates/_votes_min.html.erb diff --git a/app/views/debates/_debate.html.erb b/app/views/debates/_debate.html.erb index 4253143a6..e30cb9f90 100644 --- a/app/views/debates/_debate.html.erb +++ b/app/views/debates/_debate.html.erb @@ -9,25 +9,8 @@

<%= render 'shared/tags', debate: debate %>

-
-
- - <%= link_to debate_votes_path(debate, value: 'yes'), class: 'in-favor', method: "post" do %> - - <%= percentage('likes', debate) %> - <% end %> - - - - <%= link_to debate_votes_path(debate, value: 'no'), class: 'against', method: "post" do %> - - <%= percentage('dislikes', debate) %> - <% end %> -
- -
-

<%= pluralize(debate.total_votes, t("debates.debate.vote"), t("debates.debate.votes")) %>

-
-
+
+ <%= render 'debates/votes_min', debate: debate %> +
diff --git a/app/views/debates/_votes_min.html.erb b/app/views/debates/_votes_min.html.erb new file mode 100644 index 000000000..af793a280 --- /dev/null +++ b/app/views/debates/_votes_min.html.erb @@ -0,0 +1,25 @@ +
+
+ <%= link_to vote_debate_path(debate, value: 'yes', partial: 'votes_min'), + class: 'in-favor', method: "post", remote: true do %> + + <%= percentage('likes', debate) %> + <% end %> +
+ + + +
+ <%= link_to vote_debate_path(debate, value: 'no', partial: 'votes_min'), + class: 'against', method: "post", remote: true do %> + + <%= percentage('dislikes', debate) %> + <% end %> +
+
+ +
+

+ <%= pluralize(debate.total_votes, t("debates.debate.vote"), t("debates.debate.votes")) %> +

+
\ No newline at end of file From c2e7ff32b1ebd3a7ace0f61901e24cad12dcf365 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 12:13:49 +0200 Subject: [PATCH 14/21] adds spec for voting from debate index [#25] --- spec/features/votes_spec.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/spec/features/votes_spec.rb b/spec/features/votes_spec.rb index 4d20724b2..a2adbe117 100644 --- a/spec/features/votes_spec.rb +++ b/spec/features/votes_spec.rb @@ -30,7 +30,7 @@ feature 'Votes' do end end - scenario 'Create', :js do + scenario 'Create from debate show', :js do find('#in_favor a').click within('#in_favor') do @@ -44,6 +44,23 @@ feature 'Votes' do expect(page).to have_content "1 vote" end + scenario 'Create from debate index', :js do + visit debates_path + + find('#in_favor a').click + + within('#in_favor') do + expect(page).to have_content "100%" + end + + within('#against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" + expect(URI.parse(current_url).path).to eq(debates_path) + end + scenario 'Update', :js do find('#in_favor a').click find('#against a').click From dda5963641f98b3e309859fbe8c26080c2eec10d Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 13:50:15 +0200 Subject: [PATCH 15/21] adds spec for voting a featured debate [#25] --- spec/features/votes_spec.rb | 40 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/spec/features/votes_spec.rb b/spec/features/votes_spec.rb index a2adbe117..3e44f4f0e 100644 --- a/spec/features/votes_spec.rb +++ b/spec/features/votes_spec.rb @@ -44,20 +44,44 @@ feature 'Votes' do expect(page).to have_content "1 vote" end - scenario 'Create from debate index', :js do + scenario 'Create from debate featured', :js do visit debates_path - find('#in_favor a').click + within("#featured-debates") do + find('#in_favor a').click - within('#in_favor') do - expect(page).to have_content "100%" + within('#in_favor') do + expect(page).to have_content "100%" + end + + within('#against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" end + expect(URI.parse(current_url).path).to eq(debates_path) + end - within('#against') do - expect(page).to have_content "0%" + scenario 'Create from debate index', :js do + 3.times { create(:debate) } + visit debates_path + + within("#debates") do + expect(page).to have_css(".debate", count: 1) + + find('#in_favor a').click + + within('#in_favor') do + expect(page).to have_content "100%" + end + + within('#against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" end - - expect(page).to have_content "1 vote" expect(URI.parse(current_url).path).to eq(debates_path) end From f7de43de10bd46006e9407b74ea440c32068381f Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 14:16:44 +0200 Subject: [PATCH 16/21] adds coveralls gem --- Gemfile | 1 + Gemfile.lock | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Gemfile b/Gemfile index 73325d81d..a0e612360 100644 --- a/Gemfile +++ b/Gemfile @@ -56,5 +56,6 @@ end group :test do gem 'database_cleaner' gem 'poltergeist' + gem 'coveralls', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index 9dad0c3ec..e1390d4ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,6 +75,12 @@ GEM execjs coffee-script-source (1.9.1.1) columnize (0.9.0) + coveralls (0.8.2) + json (~> 1.8) + rest-client (>= 1.6.8, < 2) + simplecov (~> 0.10.0) + term-ansicolor (~> 1.3) + thor (~> 0.19.1) database_cleaner (1.4.1) debug_inspector (0.0.2) devise (3.5.1) @@ -85,6 +91,9 @@ GEM thread_safe (~> 0.1) warden (~> 1.2.3) diff-lcs (1.2.5) + docile (1.1.5) + domain_name (0.5.24) + unf (>= 0.0.5, < 1.0.0) erubis (2.7.0) execjs (2.5.2) factory_girl (4.5.0) @@ -97,6 +106,8 @@ GEM sass (>= 3.3.0, < 3.5) globalid (0.3.5) activesupport (>= 4.1.0) + http-cookie (1.0.2) + domain_name (~> 0.5) i18n (0.7.0) jbuilder (2.3.1) activesupport (>= 3.0.0, < 5) @@ -121,6 +132,7 @@ GEM mini_portile (0.6.2) minitest (5.7.0) multi_json (1.11.2) + netrc (0.10.3) nokogiri (1.6.6.2) mini_portile (~> 0.6.0) orm_adapter (0.5.0) @@ -164,6 +176,10 @@ GEM recaptcha (0.4.0) responders (2.1.0) railties (>= 4.2.0, < 5) + rest-client (1.8.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 3.0) + netrc (~> 0.7) rspec-core (3.3.1) rspec-support (~> 3.3.0) rspec-expectations (3.3.0) @@ -191,6 +207,11 @@ GEM sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) + simplecov (0.10.0) + docile (~> 1.1.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) spring (1.3.6) sprockets (3.2.0) rack (~> 1.0) @@ -198,9 +219,12 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) + term-ansicolor (1.3.2) + tins (~> 1.0) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) + tins (1.5.4) turbolinks (2.5.3) coffee-rails tzinfo (1.2.2) @@ -208,6 +232,9 @@ GEM uglifier (2.7.1) execjs (>= 0.3.0) json (>= 1.8.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.1) warden (1.2.3) rack (>= 1.0) web-console (2.2.1) @@ -232,6 +259,7 @@ DEPENDENCIES capybara ckeditor coffee-rails (~> 4.1.0) + coveralls database_cleaner devise factory_girl_rails From c2091f570c2a4748b2dff0048667248565479d84 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 14:16:58 +0200 Subject: [PATCH 17/21] integrates coveralls in test suite --- spec/rails_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 06687fa9e..d073cc173 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,3 +1,5 @@ +require 'coveralls' +Coveralls.wear!('rails') ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) abort("The Rails environment is running in production mode!") if Rails.env.production? From 2dd0c51f1063eb3e98ca0b4d1f17acbc7a9c5be3 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 14:17:08 +0200 Subject: [PATCH 18/21] integrates coveralls with travis --- .coveralls.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 000000000..6e649991e --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +service_name: travis-ci \ No newline at end of file From 14e48035f641c8f98c2390677c87ff049329efbd Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 14:17:18 +0200 Subject: [PATCH 19/21] ignores local test coverage stats --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 05906bf13..eb917c637 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ /spec/examples.txt /config/database.yml /config/secrets.yml + +/coverage From c854d51c6733e7807b2eb18a751616a703915894 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 5 Aug 2015 14:27:17 +0200 Subject: [PATCH 20/21] adds coveralls badge to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1ae5c25a1..1df4987c8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Build Status](https://travis-ci.org/AyuntamientoMadrid/participacion.svg?branch=master)](https://travis-ci.org/AyuntamientoMadrid/participacion) [![Code Climate](https://codeclimate.com/github/AyuntamientoMadrid/participacion/badges/gpa.svg)](https://codeclimate.com/github/AyuntamientoMadrid/participacion) [![Dependency Status](https://gemnasium.com/AyuntamientoMadrid/participacion.svg)](https://gemnasium.com/AyuntamientoMadrid/participacion) +[![Coverage Status](https://coveralls.io/repos/AyuntamientoMadrid/participacion/badge.svg?branch=master&service=github)](https://coveralls.io/github/AyuntamientoMadrid/participacion?branch=master) Este es el repositorio de código abierto de la Aplicación de Participación Ciudadana del Ayuntamiento de Madrid. From 062ef365adc06ae0784f0efb77d6571f7b7db060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Wed, 5 Aug 2015 14:34:55 +0200 Subject: [PATCH 21/21] vote action not allowed for unauthenticated users --- app/controllers/debates_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 03afc1c8e..8ccf33f6a 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -1,7 +1,7 @@ class DebatesController < ApplicationController include RecaptchaHelper before_action :set_debate, only: [:show, :edit, :update, :vote] - before_action :authenticate_user!, except: [:index, :show, :vote] + before_action :authenticate_user!, except: [:index, :show] before_action :validate_ownership, only: [:edit, :update] def index