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 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 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 diff --git a/README.md b/README.md index 648cefd8d..1df4987c8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # 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) +[![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. ## Estado del proyecto @@ -22,8 +27,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: diff --git a/app/assets/stylesheets/debates.scss b/app/assets/stylesheets/debates.scss index e39290566..de42fa1ce 100644 --- a/app/assets/stylesheets/debates.scss +++ b/app/assets/stylesheets/debates.scss @@ -247,7 +247,7 @@ header { // 05.1. Debates Index // - - - - - - - - - - - - -.debates-featured { +.debate-featured { margin-bottom: rem-calc(34); margin-top: rem-calc(23); @@ -345,8 +345,8 @@ header { margin-bottom: $line-height*2; } -.debates-index { - @extend .debates-featured; +.debate { + @extend .debate-featured; margin-bottom: 0; margin-top: 0; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b64f11bb4..ccf812e34 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,7 +4,26 @@ class ApplicationController < ActionController::Base self.responder = ApplicationResponder respond_to :html + before_action :set_locale + # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + private + + def set_locale + if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym) + session[:locale] = params[:locale] + end + + session[:locale] ||= I18n.default_locale + + I18n.locale = session[:locale] + end + + def verify_captcha?(resource) + return true unless recaptcha_keys? + verify_recaptcha(model: resource) + end end 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 23ab36a32..713e8b97d 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] + before_action :set_debate, only: [:show, :edit, :update, :vote] + before_action :authenticate_user!, except: [:index, :show] before_action :validate_ownership, only: [:edit, :update] def index @@ -9,8 +9,8 @@ class DebatesController < ApplicationController @debates = Debate.tagged_with(params[:tag]).order("created_at DESC") else @debates = Debate.all.order("created_at DESC") + @featured_debates = @debates.to_a.shift(3) end - @featured_debates = @debates.to_a.shift(3) end def show @@ -26,7 +26,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 @@ -38,6 +38,10 @@ class DebatesController < ApplicationController respond_with @debate end + def vote + @debate.vote_by(voter: current_user, vote: params[:value]) + end + private def set_debate @@ -51,10 +55,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 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 diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb deleted file mode 100644 index e93968f35..000000000 --- a/app/controllers/votes_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -class VotesController < ApplicationController - before_action :set_debate - 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_debate - @debate = Debate.find(params[:debate_id]) - end - - def register_vote - @debate.vote_by voter: current_user, vote: params[:value] - end -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 499265f5a..70828c01a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -5,15 +5,21 @@ module ApplicationHelper end def percentage(vote, debate) - return if debate.total_votes == 0 + return "0%" if debate.total_votes == 0 debate.send(vote).percent_of(debate.total_votes).to_s + "%" end def home_page? - request.fullpath == '/' + # Using path because fullpath yields false negatives since it contains + # parameters too + request.path == '/' end def header_css home_page? ? '' : 'results' end + + def available_locales_to_switch + I18n.available_locales - [I18n.locale] + end end 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 diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb index 0d152d928..6e4e02f19 100644 --- a/app/views/comments/_comment.html.erb +++ b/app/views/comments/_comment.html.erb @@ -7,12 +7,19 @@ <%= comment.user.name %> • <%= time_ago_in_words(comment.created_at) %> -

<%= comment.body %>

-

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

- +

<%= comment.body %>

-
- <%= render comment.children %> -
+ + <%= render 'comments/votes', comment: comment %> + + + <% if user_signed_in? %> +

<%= render 'comments/form', {parent: comment, toggeable: true} %>

+ <% end %> + + +
+ <%= render comment.children %> +
\ No newline at end of file diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb index 01661221f..da2b3bb61 100644 --- a/app/views/comments/_form.html.erb +++ b/app/views/comments/_form.html.erb @@ -1,6 +1,6 @@ -<%= link_to comment_link_text(parent), "", class: "js-add-comment-link", data: {'id': dom_id(parent)} %> +<%= link_to(comment_link_text(parent), "", class: "js-add-comment-link", data: {'id': dom_id(parent)}) if toggeable %> -