diff --git a/.travis.yml b/.travis.yml index 68dd3c9..bc7dd1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: ruby rvm: - - 2.1.1 + - 2.1.2 deploy: provider: heroku api_key: diff --git a/Gemfile b/Gemfile index 827daf8..e35c167 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,9 @@ -ruby '2.1.1' +ruby '2.1.2' source 'https://rubygems.org' source 'https://rails-assets.org' -gem 'rails', '4.1.0' +gem 'rails', '4.1.1' gem 'sass-rails', '~> 4.0.0' gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.0.0' @@ -26,14 +26,14 @@ group :development, :test do gem 'pry-byebug' gem "binding_of_caller" gem 'meta_request' - gem 'rspec-rails', '~> 3.0.0.beta', github: 'rspec/rspec-rails' - gem 'rspec-core', '~> 3.0.0.beta', github: 'rspec/rspec-core' - gem 'rspec-expectations', '~> 3.0.0.beta', github: 'rspec/rspec-expectations' - gem 'rspec-mocks', '~> 3.0.0.beta', github: 'rspec/rspec-mocks' - gem 'rspec-support', '~> 3.0.0.beta', github: 'rspec/rspec-support' + gem 'rspec-rails', '~> 3.0.0.rc1' gem 'factory_girl_rails', '~> 4.4.1' end +group :development do + gem 'quiet_assets' +end + group :test do gem 'shoulda-matchers', '~> 2.6.0' gem 'capybara' diff --git a/Gemfile.lock b/Gemfile.lock index 4e81c56..6971b1b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,71 +1,28 @@ -GIT - remote: git://github.com/rspec/rspec-core.git - revision: 6b67068d1ae0525d15c02f3a1b00218e5b36b4db - specs: - rspec-core (3.0.0.beta2) - rspec-support (= 3.0.0.beta2) - -GIT - remote: git://github.com/rspec/rspec-expectations.git - revision: 1603a39f45d6683b562ed91a5c766d83e2f3cb20 - specs: - rspec-expectations (3.0.0.beta2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (= 3.0.0.beta2) - -GIT - remote: git://github.com/rspec/rspec-mocks.git - revision: d2be1035a098b89d591d4573becae086452baf8c - specs: - rspec-mocks (3.0.0.beta2) - rspec-support (= 3.0.0.beta2) - -GIT - remote: git://github.com/rspec/rspec-rails.git - revision: 3d63b16bc6d8f8cf6d605e1d62e940f8441d0cd7 - specs: - rspec-rails (3.0.0.beta2) - actionpack (>= 3.0) - activemodel (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-collection_matchers - rspec-core (= 3.0.0.beta2) - rspec-expectations (= 3.0.0.beta2) - rspec-mocks (= 3.0.0.beta2) - rspec-support (= 3.0.0.beta2) - -GIT - remote: git://github.com/rspec/rspec-support.git - revision: 2d12b1e2368054cf9997fa2b2e41329769aa812d - specs: - rspec-support (3.0.0.beta2) - GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: - actionmailer (4.1.0) - actionpack (= 4.1.0) - actionview (= 4.1.0) + actionmailer (4.1.1) + actionpack (= 4.1.1) + actionview (= 4.1.1) mail (~> 2.5.4) - actionpack (4.1.0) - actionview (= 4.1.0) - activesupport (= 4.1.0) + actionpack (4.1.1) + actionview (= 4.1.1) + activesupport (= 4.1.1) rack (~> 1.5.2) rack-test (~> 0.6.2) - actionview (4.1.0) - activesupport (= 4.1.0) + actionview (4.1.1) + activesupport (= 4.1.1) builder (~> 3.1) erubis (~> 2.7.0) - activemodel (4.1.0) - activesupport (= 4.1.0) + activemodel (4.1.1) + activesupport (= 4.1.1) builder (~> 3.1) - activerecord (4.1.0) - activemodel (= 4.1.0) - activesupport (= 4.1.0) + activerecord (4.1.1) + activemodel (= 4.1.1) + activesupport (= 4.1.1) arel (~> 5.0.0) - activesupport (4.1.0) + activesupport (4.1.1) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) @@ -148,8 +105,8 @@ GEM method_source (0.8.2) mime-types (1.25.1) mini_portile (0.5.3) - minitest (5.3.3) - multi_json (1.9.2) + minitest (5.3.4) + multi_json (1.10.1) newrelic_rpm (3.8.0.218) nokogiri (1.6.1) mini_portile (~> 0.5.0) @@ -180,20 +137,22 @@ GEM pry-remote (0.1.8) pry (~> 0.9) slop (~> 3.0) + quiet_assets (1.0.2) + railties (>= 3.1, < 5.0) rack (1.5.2) rack-contrib (1.1.0) rack (>= 0.9.1) rack-test (0.6.2) rack (>= 1.0) - rails (4.1.0) - actionmailer (= 4.1.0) - actionpack (= 4.1.0) - actionview (= 4.1.0) - activemodel (= 4.1.0) - activerecord (= 4.1.0) - activesupport (= 4.1.0) + rails (4.1.1) + actionmailer (= 4.1.1) + actionpack (= 4.1.1) + actionview (= 4.1.1) + activemodel (= 4.1.1) + activerecord (= 4.1.1) + activesupport (= 4.1.1) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.0) + railties (= 4.1.1) sprockets-rails (~> 2.0) rails-assets-bootstrap (3.1.1) rails-assets-jquery (>= 1.9.0) @@ -203,15 +162,29 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.2) rails_stdout_logging (0.0.3) - railties (4.1.0) - actionpack (= 4.1.0) - activesupport (= 4.1.0) + railties (4.1.1) + actionpack (= 4.1.1) + activesupport (= 4.1.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (10.3.1) + rake (10.3.2) ref (1.0.5) - rspec-collection_matchers (0.0.3) - rspec-expectations (>= 2.99.0.beta1) + rspec-core (3.0.0.rc1) + rspec-support (= 3.0.0.rc1) + rspec-expectations (3.0.0.rc1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (= 3.0.0.rc1) + rspec-mocks (3.0.0.rc1) + rspec-support (= 3.0.0.rc1) + rspec-rails (3.0.0.rc1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (= 3.0.0.rc1) + rspec-expectations (= 3.0.0.rc1) + rspec-mocks (= 3.0.0.rc1) + rspec-support (= 3.0.0.rc1) + rspec-support (3.0.0.rc1) ruby_parser (3.1.3) sexp_processor (~> 4.1) sass (3.2.19) @@ -278,14 +251,11 @@ DEPENDENCIES pry pry-byebug pry-remote - rails (= 4.1.0) + quiet_assets + rails (= 4.1.1) rails-assets-bootstrap rails_12factor - rspec-core (~> 3.0.0.beta)! - rspec-expectations (~> 3.0.0.beta)! - rspec-mocks (~> 3.0.0.beta)! - rspec-rails (~> 3.0.0.beta)! - rspec-support (~> 3.0.0.beta)! + rspec-rails (~> 3.0.0.rc1) sass-rails (~> 4.0.0) shoulda-matchers (~> 2.6.0) sqlite3 diff --git a/README.md b/README.md index cc5eeab..e6bb314 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # デザインビギナーズのアイデア帳 [![Build Status](https://travis-ci.org/design-beginners/debeg-idea.svg?branch=master)](https://travis-ci.org/design-beginners/debeg-idea) +[![Code Climate](https://codeclimate.com/github/design-beginners/debeg-idea.png)](https://codeclimate.com/github/design-beginners/debeg-idea) ## Setup for development diff --git a/app/assets/javascripts/ideas.js.coffee b/app/assets/javascripts/ideas.js.coffee index 24f83d1..1b86163 100644 --- a/app/assets/javascripts/ideas.js.coffee +++ b/app/assets/javascripts/ideas.js.coffee @@ -1,3 +1,8 @@ # Place all the behaviors and hooks related to the matching controller here. # All this logic will automatically be available in application.js. # You can use CoffeeScript in this file: http://coffeescript.org/ +# + +$(document).on 'ajax:success', '.js-like', (xhr, data, status) -> + location.reload() + diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 63be4c0..b4c7ffc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -21,7 +21,7 @@ def authenticate redirect_to root_path, alert: 'ログインしてください' end - def error404(e) + def error404 render 'error404', status: 404, formats: [:html] end diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb new file mode 100644 index 0000000..161c176 --- /dev/null +++ b/app/controllers/likes_controller.rb @@ -0,0 +1,17 @@ +class LikesController < ApplicationController + before_action :authenticate + + def create + idea = Idea.find(params[:idea_id]) + comment_id = params[:comment_id] + + likable = if comment_id + idea.comments.find(comment_id) + else + idea + end + likable.likes.create!(user: current_user) + + head 201 + end +end diff --git a/app/helpers/likes_helper.rb b/app/helpers/likes_helper.rb new file mode 100644 index 0000000..a78a759 --- /dev/null +++ b/app/helpers/likes_helper.rb @@ -0,0 +1,2 @@ +module LikesHelper +end diff --git a/app/models/comment.rb b/app/models/comment.rb index a3d82d4..ffeb03e 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,5 @@ class Comment < ActiveRecord::Base + has_many :likes, as: :likable belongs_to :idea belongs_to :user diff --git a/app/models/idea.rb b/app/models/idea.rb index bfdf8f2..55b8d4c 100644 --- a/app/models/idea.rb +++ b/app/models/idea.rb @@ -1,4 +1,5 @@ class Idea < ActiveRecord::Base + has_many :likes, as: :likable has_many :comments belongs_to :user diff --git a/app/models/like.rb b/app/models/like.rb new file mode 100644 index 0000000..7ee0d62 --- /dev/null +++ b/app/models/like.rb @@ -0,0 +1,4 @@ +class Like < ActiveRecord::Base + belongs_to :user + belongs_to :likable, polymorphic: true +end diff --git a/app/views/ideas/show.html.haml b/app/views/ideas/show.html.haml index 60f04d9..f680dcb 100644 --- a/app/views/ideas/show.html.haml +++ b/app/views/ideas/show.html.haml @@ -12,6 +12,13 @@ = comment.body - else = comment.body + .pull-right + イイネ!: #{comment.likes.count} + - if logged_in? && comment.likes.exists?(user: current_user) + = link_to 'イイネ!済み', '#', class: 'btn btn-primary btn-sm disabled' + - elsif logged_in? + = link_to 'イイネ!', idea_comment_likes_path(@idea, comment), method: :post, remote: true, class: 'btn btn-primary btn-sm js-like' + - if logged_in? = form_for [@idea, @comment] do |f| - if @comment.errors.any? diff --git a/app/views/welcome/index.html.haml b/app/views/welcome/index.html.haml index 2d0fc84..1d00455 100644 --- a/app/views/welcome/index.html.haml +++ b/app/views/welcome/index.html.haml @@ -29,3 +29,9 @@ = idea.title - else = idea.title + .pull-right + イイネ!: #{idea.likes.count} + - if logged_in? && idea.likes.exists?(user: current_user) + = link_to 'イイネ!済み', '#', class: 'btn btn-primary btn-sm disabled' + - elsif logged_in? + = link_to 'イイネ!', idea_likes_path(idea), method: :post, remote: true, class: 'btn btn-primary btn-sm js-like' diff --git a/config/routes.rb b/config/routes.rb index 8c94f3a..7d19ec9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,8 +4,12 @@ get '/auth/failure' => 'sessions#failure' get '/logout' => 'sessions#destroy', as: :logout - resources :ideas, only: [:show, :create] do - resources :comments, only: :create + concern :likable do + resources :likes, only: :create + end + + resources :ideas, concerns: :likable, only: [:show, :create] do + resources :comments, concerns: :likable, only: :create end match '*path' => 'application#error404', via: :all diff --git a/db/migrate/20140507063631_create_likes.rb b/db/migrate/20140507063631_create_likes.rb new file mode 100644 index 0000000..77d46b7 --- /dev/null +++ b/db/migrate/20140507063631_create_likes.rb @@ -0,0 +1,13 @@ +class CreateLikes < ActiveRecord::Migration + def change + create_table :likes do |t| + t.integer :user_id, null: false + t.integer :likable_id, null: false + t.string :likable_type, null: false + t.timestamps + end + + add_index :likes, [:likable_id, :likable_type] + add_index :likes, [:user_id, :likable_id, :likable_type], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 58b5f42..f6b3339 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140427143623) do +ActiveRecord::Schema.define(version: 20140507063631) do create_table "comments", force: true do |t| t.integer "idea_id" @@ -33,6 +33,17 @@ add_index "ideas", ["user_id"], name: "index_ideas_on_user_id" + create_table "likes", force: true do |t| + t.integer "user_id", null: false + t.integer "likable_id", null: false + t.string "likable_type", null: false + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "likes", ["likable_id", "likable_type"], name: "index_likes_on_likable_id_and_likable_type" + add_index "likes", ["user_id", "likable_id", "likable_type"], name: "index_likes_on_user_id_and_likable_id_and_likable_type", unique: true + create_table "users", force: true do |t| t.string "provider", null: false t.string "uid", null: false diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb new file mode 100644 index 0000000..dd39280 --- /dev/null +++ b/spec/controllers/likes_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe LikesController do + +end diff --git a/spec/features/create_like_to_comment_spec.rb b/spec/features/create_like_to_comment_spec.rb new file mode 100644 index 0000000..a98a486 --- /dev/null +++ b/spec/features/create_like_to_comment_spec.rb @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +require 'spec_helper' + +describe 'よいコメントに"イイネ!"をする' do + let(:comment) { create :comment } + + context '未ログイン状態でアイデアページにアクセスしたとき' do + before { visit idea_path(comment.idea) } + + it 'イイネ!ボタンが表示されていないこと' do + expect(page).to have_no_css '.btn.js-like' + end + end + + context 'ログイン状態でアイデアページにアクセスしたとき' do + before do + login + visit idea_path(comment.idea) + end + + it 'イイネ!ボタンが表示されていること' do + expect(find('.btn.js-like')).to have_content 'イイネ!' + end + + context 'かつ、イイネ!をクリックしたとき', js: true do + before { click_link 'イイネ!' } + + it '"イイネ!" が "イイネ!済み" になり、disabled になっていること' do + expect(page).to have_no_css '.btn.js-like' + expect(find('.btn.disabled')).to have_content 'イイネ!済み' + end + end + end +end diff --git a/spec/features/create_like_to_idea_spec.rb b/spec/features/create_like_to_idea_spec.rb new file mode 100644 index 0000000..28c34c9 --- /dev/null +++ b/spec/features/create_like_to_idea_spec.rb @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +require 'spec_helper' + +describe 'よいアイデアに"イイネ!"をする' do + before { create :idea } + + context '未ログイン状態でトップページにアクセスしたとき' do + before { visit root_path } + + it 'イイネ!ボタンが表示されていないこと' do + expect(page).to have_no_css '.btn.js-like' + end + end + + context 'ログイン状態でトップページにアクセスしたとき' do + before do + login + visit root_path + end + + it 'イイネ!ボタンが表示されていること' do + expect(find('.btn.js-like')).to have_content 'イイネ!' + end + + context 'かつ、イイネ!をクリックしたとき', js: true do + before { click_link 'イイネ!' } + + it '"イイネ!" が "イイネ!済み" になり、disabled になっていること' do + expect(page).to have_no_css '.btn.js-like' + expect(find('.btn.disabled')).to have_content 'イイネ!済み' + end + end + end +end diff --git a/spec/helpers/likes_helper_spec.rb b/spec/helpers/likes_helper_spec.rb new file mode 100644 index 0000000..483b20c --- /dev/null +++ b/spec/helpers/likes_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the LikesHelper. For example: +# +# describe LikesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +describe LikesHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb new file mode 100644 index 0000000..ce06d89 --- /dev/null +++ b/spec/models/like_spec.rb @@ -0,0 +1,6 @@ +require 'spec_helper' + +describe Like do + it { should belong_to :user } + it { should belong_to :likable } +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d09b020..b64b929 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -36,7 +36,7 @@ # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. - config.use_transactional_fixtures = true + config.use_transactional_fixtures = false # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing @@ -65,4 +65,6 @@ config.after :each do DatabaseRewinder.clean end + + config.infer_spec_type_from_file_location! end