From 5547c724e86ffd25a55ad3588f871ef56e7a73cf Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Wed, 14 Oct 2015 21:23:35 +0300 Subject: [PATCH 1/3] Setup Rubocop and autocorrect offences --- .ruby-version | 1 - Gemfile | 19 ++++++------ app/controllers/questions_controller.rb | 12 ++++---- app/controllers/votes_controller.rb | 8 ++--- app/models/option.rb | 2 +- bin/rails | 4 +-- bin/rake | 2 +- bin/spring | 12 ++++---- config.ru | 2 +- config/initializers/cookies_serializer.rb | 2 +- config/routes.rb | 1 - db/schema.rb | 36 +++++++++++------------ 12 files changed, 48 insertions(+), 53 deletions(-) delete mode 100644 .ruby-version diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index eca07e4..0000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.1.2 diff --git a/Gemfile b/Gemfile index 2534e5a..24ca9b2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,9 @@ source 'https://rubygems.org' source 'https://rails-assets.org' -ruby '2.1.2' +ruby '2.2.2' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.1.6' +gem 'rails', '4.2.2' # Use SCSS for stylesheets gem 'sass-rails', '~> 4.0.3' # Use Uglifier as compressor for JavaScript assets @@ -20,10 +20,10 @@ gem 'turbolinks' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.0' # bundle exec rake doc:rails generates the API under doc/api. -gem 'sdoc', '~> 0.4.0', group: :doc +gem 'sdoc', '~> 0.4.0', group: :doc # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring -gem 'spring', group: :development +gem 'spring', group: :development # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' @@ -37,8 +37,8 @@ gem 'spring', group: :development # Use debugger # gem 'debugger', group: [:development, :test] -gem "autoprefixer-rails" -gem 'rails-assets-angular', "1.3.0.rc.4" +gem 'autoprefixer-rails' +gem 'rails-assets-angular', '1.3.0.rc.4' gem 'pusher' group :production, :staging do @@ -47,9 +47,10 @@ group :production, :staging do end group :development do - gem "better_errors" - gem "binding_of_caller" + gem 'rubocop' + gem 'better_errors' + gem 'binding_of_caller' gem 'mysql2' end -gem 'dotenv-rails', :groups => [:development, :test] +gem 'dotenv-rails', groups: [:development, :test] diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index f99a709..21b22b5 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -1,5 +1,4 @@ class QuestionsController < ApplicationController - before_filter :set_question, only: [:show, :results] before_filter :check_secret_is_unique, only: [:create] @@ -14,7 +13,7 @@ def create @question.save! params[:options].each do |option| - if option[:title] != "" + if option[:title] != '' new_option = Option.new new_option.title = option[:title] new_option.question_id = @question.id @@ -27,7 +26,7 @@ def create def show vote_id = cookies["vote_#{@question.secret}"] - @vote = Vote.where({secret: vote_id}).first_or_initialize + @vote = Vote.where(secret: vote_id).first_or_initialize end def results @@ -35,13 +34,13 @@ def results end def check_secret_availability - render json: { available: !Question.where({secret: params[:secret]}).exists? } + render json: { available: !Question.where(secret: params[:secret]).exists? } end private def set_question - @question = Question.where({secret: params[:secret]}).first + @question = Question.where(secret: params[:secret]).first end def question_params @@ -50,11 +49,10 @@ def question_params def check_secret_is_unique if defined? params[:question][:secret] - if Question.where({secret: params[:question][:secret]}).exists? + if Question.where({ secret: params[:question][:secret] }).exists? @question = Question.new(question_params) redirect_to :back, notice: 'Sorry that URL is taken' end end end - end diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb index 1e854ff..c26f685 100644 --- a/app/controllers/votes_controller.rb +++ b/app/controllers/votes_controller.rb @@ -4,14 +4,14 @@ class VotesController < ApplicationController def update question_id = params[:vote][:question_id] vote_id = cookies["vote_#{question_id}"] - vote = Vote.where({secret: vote_id}).first_or_initialize + vote = Vote.where(secret: vote_id).first_or_initialize - question = Question.where({secret: question_id}).first + question = Question.where(secret: question_id).first vote.secret = SecureRandom.urlsafe_base64(nil, false) unless vote.secret vote.question_id = question.id unless vote.question_id vote.option_id = Option.find(params[:vote][:option_id]).id - Pusher[question_id].trigger("vote", {}) + Pusher[question_id].trigger('vote', {}) if vote.save! cookies.permanent["vote_#{question.secret}"] = vote.secret @@ -29,7 +29,7 @@ def show private def set_question - @question = Question.where({secret: params[:secret]}).first + @question = Question.where(secret: params[:secret]).first end def question_params diff --git a/app/models/option.rb b/app/models/option.rb index 279495f..a70a925 100644 --- a/app/models/option.rb +++ b/app/models/option.rb @@ -3,6 +3,6 @@ class Option < ActiveRecord::Base belongs_to :question def votes - Vote.where({ option_id: self.id }).count + Vote.where(option_id: id).count end end diff --git a/bin/rails b/bin/rails index 7feb6a3..62687aa 100755 --- a/bin/rails +++ b/bin/rails @@ -1,8 +1,8 @@ #!/usr/bin/env ruby begin - load File.expand_path("../spring", __FILE__) + load File.expand_path('../spring', __FILE__) rescue LoadError end -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../../config/application', __FILE__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index 8017a02..2e9ece4 100755 --- a/bin/rake +++ b/bin/rake @@ -1,6 +1,6 @@ #!/usr/bin/env ruby begin - load File.expand_path("../spring", __FILE__) + load File.expand_path('../spring', __FILE__) rescue LoadError end require_relative '../config/boot' diff --git a/bin/spring b/bin/spring index 253ec37..ec62a65 100755 --- a/bin/spring +++ b/bin/spring @@ -4,15 +4,15 @@ # It gets overwritten when you run the `spring binstub` command unless defined?(Spring) - require "rubygems" - require "bundler" + require 'rubygems' + require 'bundler' if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m) - ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) - ENV["GEM_HOME"] = "" + ENV['GEM_PATH'] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) + ENV['GEM_HOME'] = '' Gem.paths = ENV - gem "spring", match[1] - require "spring/binstub" + gem 'spring', match[1] + require 'spring/binstub' end end diff --git a/config.ru b/config.ru index 5bc2a61..bd83b25 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require ::File.expand_path('../config/environment', __FILE__) run Rails.application diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7a06a89..7f70458 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,3 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of file +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/routes.rb b/config/routes.rb index fdbb079..3704508 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,4 @@ Rails.application.routes.draw do - resources :questions get '/admin' => 'admin#dashboard' put '/votes' => 'votes#update' diff --git a/db/schema.rb b/db/schema.rb index 8dd6251..dce17eb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,28 +11,26 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141004134727) do - - create_table "options", force: true do |t| - t.string "title" - t.integer "question_id" - t.datetime "created_at" - t.datetime "updated_at" +ActiveRecord::Schema.define(version: 20_141_004_134_727) do + create_table 'options', force: true do |t| + t.string 'title' + t.integer 'question_id' + t.datetime 'created_at' + t.datetime 'updated_at' end - create_table "questions", force: true do |t| - t.string "title" - t.string "secret" - t.datetime "created_at" - t.datetime "updated_at" + create_table 'questions', force: true do |t| + t.string 'title' + t.string 'secret' + t.datetime 'created_at' + t.datetime 'updated_at' end - create_table "votes", force: true do |t| - t.string "secret" - t.integer "question_id" - t.integer "option_id" - t.datetime "created_at" - t.datetime "updated_at" + create_table 'votes', force: true do |t| + t.string 'secret' + t.integer 'question_id' + t.integer 'option_id' + t.datetime 'created_at' + t.datetime 'updated_at' end - end From e9d90d38b06536b51034dd43bd5a65fc8834d4cd Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Wed, 14 Oct 2015 23:14:18 +0300 Subject: [PATCH 2/3] Add indices for better performance --- ...4947_add_indices_for_better_performance.rb | 7 +++ db/schema.rb | 44 ++++++++++++------- 2 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 db/migrate/20151014184947_add_indices_for_better_performance.rb diff --git a/db/migrate/20151014184947_add_indices_for_better_performance.rb b/db/migrate/20151014184947_add_indices_for_better_performance.rb new file mode 100644 index 0000000..0b443b0 --- /dev/null +++ b/db/migrate/20151014184947_add_indices_for_better_performance.rb @@ -0,0 +1,7 @@ +class AddIndicesForBetterPerformance < ActiveRecord::Migration + def change + add_index :questions, :secret + add_index :votes, :question_id + add_index :votes, :option_id + end +end diff --git a/db/schema.rb b/db/schema.rb index dce17eb..b5be5fd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,26 +11,36 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20_141_004_134_727) do - create_table 'options', force: true do |t| - t.string 'title' - t.integer 'question_id' - t.datetime 'created_at' - t.datetime 'updated_at' +ActiveRecord::Schema.define(version: 20151014184947) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "options", force: :cascade do |t| + t.string "title" + t.integer "question_id" + t.datetime "created_at" + t.datetime "updated_at" end - create_table 'questions', force: true do |t| - t.string 'title' - t.string 'secret' - t.datetime 'created_at' - t.datetime 'updated_at' + create_table "questions", force: :cascade do |t| + t.string "title" + t.string "secret" + t.datetime "created_at" + t.datetime "updated_at" end - create_table 'votes', force: true do |t| - t.string 'secret' - t.integer 'question_id' - t.integer 'option_id' - t.datetime 'created_at' - t.datetime 'updated_at' + add_index "questions", ["secret"], name: "index_questions_on_secret", using: :btree + + create_table "votes", force: :cascade do |t| + t.string "secret" + t.integer "question_id" + t.integer "option_id" + t.datetime "created_at" + t.datetime "updated_at" end + + add_index "votes", ["option_id"], name: "index_votes_on_option_id", using: :btree + add_index "votes", ["question_id"], name: "index_votes_on_question_id", using: :btree + end From b01d1cd8df14b5bab1ea9879ff51146b1bb5f468 Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Wed, 14 Oct 2015 23:14:58 +0300 Subject: [PATCH 3/3] Return 404 on ActiveRecord not found instead of 500 --- app/controllers/admin_controller.rb | 7 +++---- app/controllers/questions_controller.rb | 21 ++++++++------------- app/controllers/votes_controller.rb | 14 +++++++------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index a8c8b7f..605db95 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -8,10 +8,9 @@ def dashboard private def authenticate - if Rails.env.production? - authenticate_or_request_with_http_basic do |username, password| - username == ENV['ADMIN_USERNAME'] && password == ENV['ADMIN_PASSWORD'] - end + return unless Rails.env.production? + authenticate_or_request_with_http_basic do |username, password| + username == ENV['ADMIN_USERNAME'] && password == ENV['ADMIN_PASSWORD'] end end end diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 21b22b5..2d77dc8 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -13,12 +13,9 @@ def create @question.save! params[:options].each do |option| - if option[:title] != '' - new_option = Option.new - new_option.title = option[:title] - new_option.question_id = @question.id - new_option.save! - end + next unless option[:title] != '' + new_option = Option.new(title: option[:title], question_id: @question.id) + new_option.save! end redirect_to "/#{@question.secret}" @@ -40,7 +37,7 @@ def check_secret_availability private def set_question - @question = Question.where(secret: params[:secret]).first + @question = Question.find_by_secret!(params[:secret]) end def question_params @@ -48,11 +45,9 @@ def question_params end def check_secret_is_unique - if defined? params[:question][:secret] - if Question.where({ secret: params[:question][:secret] }).exists? - @question = Question.new(question_params) - redirect_to :back, notice: 'Sorry that URL is taken' - end - end + return unless defined? params[:question][:secret] + return unless Question.where(secret: params[:question][:secret]).exists? + @question = Question.new(question_params) + redirect_to :back, notice: 'Sorry that URL is taken' end end diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb index c26f685..13945ec 100644 --- a/app/controllers/votes_controller.rb +++ b/app/controllers/votes_controller.rb @@ -6,20 +6,20 @@ def update vote_id = cookies["vote_#{question_id}"] vote = Vote.where(secret: vote_id).first_or_initialize - question = Question.where(secret: question_id).first + question = Question.find_by_secret!(question_id) vote.secret = SecureRandom.urlsafe_base64(nil, false) unless vote.secret vote.question_id = question.id unless vote.question_id vote.option_id = Option.find(params[:vote][:option_id]).id Pusher[question_id].trigger('vote', {}) - if vote.save! - cookies.permanent["vote_#{question.secret}"] = vote.secret + return unless vote.save! - respond_to do |format| - format.html { redirect_to "/#{question.secret}" } - format.json { render json: {}, status: :created } - end + cookies.permanent["vote_#{question.secret}"] = vote.secret + + respond_to do |format| + format.html { redirect_to "/#{question.secret}" } + format.json { render json: {}, status: :created } end end