From e4f09e1d39ae443bbb14fbb6cbec48c20d7b1ab4 Mon Sep 17 00:00:00 2001 From: Yu Kitazume Date: Tue, 20 May 2014 18:08:13 +0900 Subject: [PATCH 1/3] =?UTF-8?q?like=E3=83=A2=E3=83=86=E3=82=99=E3=83=AB?= =?UTF-8?q?=E3=81=A8=E5=91=A8=E8=BE=BA=E3=81=AE=E3=83=A1=E3=82=BD=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=82=99=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/idea.rb | 1 + app/models/like.rb | 25 +++++++++++++++++++++++ app/models/user.rb | 12 +++++++++++ db/migrate/20140520052025_create_likes.rb | 15 ++++++++++++++ db/schema.rb | 14 ++++++++++++- spec/factories/likes.rb | 6 ++++++ spec/models/like_spec.rb | 21 +++++++++++++++++++ 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 app/models/like.rb create mode 100644 db/migrate/20140520052025_create_likes.rb create mode 100644 spec/factories/likes.rb create mode 100644 spec/models/like_spec.rb diff --git a/app/models/idea.rb b/app/models/idea.rb index bfdf8f2..792bc68 100644 --- a/app/models/idea.rb +++ b/app/models/idea.rb @@ -1,5 +1,6 @@ class Idea < ActiveRecord::Base has_many :comments + has_many :likes belongs_to :user validates :title, length: { maximum: 100 }, presence: true diff --git a/app/models/like.rb b/app/models/like.rb new file mode 100644 index 0000000..bd3cffb --- /dev/null +++ b/app/models/like.rb @@ -0,0 +1,25 @@ +class Like < ActiveRecord::Base + default_scope -> {where(:live => true)} + belongs_to :user + belongs_to :idea + + validate :idea, uniqueness: { scope: :user } + + class << self + def create_with_user_and_idea(user, idea) + like = self.new(user_id: user.id, idea_id: idea.id) + like.save + like + end + end + + def unlike + self.live = false + self.save + end + + def relike + self.live = true + self.save + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 8a46437..d458b70 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,4 +12,16 @@ def self.find_or_create_from_auth_hash(auth_hash) user.image_url = image_url end end + + def like(idea) + like = Like.unscoped.find_or_create_by(user_id: self.id, idea_id: idea.id) + if like and like.updated_at != like.created_at + like.relike + end + like + end + + def like?(idea) + (Like.where(user_id: self.id, idea_id: idea.id).count >= 1) + end end diff --git a/db/migrate/20140520052025_create_likes.rb b/db/migrate/20140520052025_create_likes.rb new file mode 100644 index 0000000..dcfdc3b --- /dev/null +++ b/db/migrate/20140520052025_create_likes.rb @@ -0,0 +1,15 @@ +class CreateLikes < ActiveRecord::Migration + def change + create_table :likes do |t| + + t.references :idea, :null => false + t.references :user, :null => false + t.boolean :live, :null => false, :default => true + t.timestamps + end + + add_index :likes, :idea_id + add_index :likes, :user_id + add_index :likes, [:idea_id, :user_id], :unique => true + end +end diff --git a/db/schema.rb b/db/schema.rb index 58b5f42..7210f2f 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: 20140520052025) do create_table "comments", force: true do |t| t.integer "idea_id" @@ -33,6 +33,18 @@ add_index "ideas", ["user_id"], name: "index_ideas_on_user_id" + create_table "likes", force: true do |t| + t.integer "idea_id", null: false + t.integer "user_id", null: false + t.boolean "live", default: true, null: false + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "likes", ["idea_id", "user_id"], name: "index_likes_on_idea_id_and_user_id", unique: true + add_index "likes", ["idea_id"], name: "index_likes_on_idea_id" + add_index "likes", ["user_id"], name: "index_likes_on_user_id" + create_table "users", force: true do |t| t.string "provider", null: false t.string "uid", null: false diff --git a/spec/factories/likes.rb b/spec/factories/likes.rb new file mode 100644 index 0000000..efac4f8 --- /dev/null +++ b/spec/factories/likes.rb @@ -0,0 +1,6 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :like do + end +end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb new file mode 100644 index 0000000..04944a4 --- /dev/null +++ b/spec/models/like_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Like do + + describe "relations" do + it { should belong_to(:user) } + it { should belong_to(:idea) } + end + + describe "#create_with_user_and_idea" do + before do + @user = build(:user) + @idea = build(:idea) + end + + it "return created instance" do + expect(Like.create_with_user_and_idea(@user, @idea).class).to eq(Like) + end + end + +end From 01e8d4d82ddf98d1ad2ff629162854278298ae3d Mon Sep 17 00:00:00 2001 From: Yu Kitazume Date: Tue, 20 May 2014 18:27:45 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Like=E3=81=AE=E3=80=80view=20=E3=81=A8=20co?= =?UTF-8?q?ntroller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/javascripts/application.js | 22 +++++++++++++++++ app/assets/stylesheets/application.css | 7 ++++++ app/controllers/ideas_controller.rb | 20 +++++++++++++++ app/helpers/application_helper.rb | 34 ++++++++++++++++++++++++++ app/views/ideas/show.html.haml | 2 ++ app/views/welcome/index.html.haml | 4 +++ config/routes.rb | 2 ++ 7 files changed, 91 insertions(+) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index e3a9f2d..2e23b02 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,3 +15,25 @@ //= require bootstrap //= require turbolinks //= require_tree . +$(document).ready(function(){ + $(".like").on('click', function(ev){ + console.log(this) + ev.preventDefault(); + + $.ajax(this.href) + .done(function(msg) { + if (msg.action === 'like') { + $(ev.target).parent().parent().children().toggleClass("hidden-button"); + $(ev.target).parent().addClass("hidden-button"); + $(".current-user-icon.idea-"+msg.idea_id).toggleClass("hidden-icon"); + } else { + $(ev.target).parent().parent().children().toggleClass("hidden-button"); + $(ev.target).parent().addClass("hidden-button"); + $(".current-user-icon.idea-"+msg.idea_id).addClass("hidden-icon"); + } + }) + .fail(function(msg) { + alert("しっぱいしました reloadしてね") + }); + }) +}); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 62a5c86..bb3fd56 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -12,3 +12,10 @@ *= require bootstrap *= require_tree . */ + +.hidden-icon { + display: none; +} +.hidden-button { + display: none; +} diff --git a/app/controllers/ideas_controller.rb b/app/controllers/ideas_controller.rb index e7d4cdb..0731740 100644 --- a/app/controllers/ideas_controller.rb +++ b/app/controllers/ideas_controller.rb @@ -18,4 +18,24 @@ def create render 'welcome/index' end end + + def like + idea = Idea.find(params[:idea_id]) + if current_user.like(idea) + render :json => {action: 'like', idea_id: idea.id}, :status => 200 + else + render :text => 'ng', :status => 500 + end + end + + def unlike + idea = Idea.find(params[:idea_id]) + like = Like.where(idea_id: idea.id, user_id: current_user.id).first + if like and like.unlike + render :json => {action: 'unlike', idea_id: idea.id}, :status => 200 + else + render :text => 'ng', :status => 500 + end + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be79..6948895 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,36 @@ module ApplicationHelper + def like_button(idea) + return nil unless logged_in? + like_flag = current_user.like?(idea) + + buttons = content_tag(:button, class: "#{(like_flag) ? '' : 'hidden-button'}") do + link_to "unlike", unlike_path(idea_id: idea.id), class: "like" + end + buttons << content_tag(:button, class: "#{(like_flag) ? 'hidden-button' : ''}") do + link_to "like", like_path(idea_id: idea.id), class: "like" + end + content_tag :div do + buttons + end + end + + def likes_list(idea) + users = idea.likes.map(&:user) + if logged_in? + users.reject!{|u| u == current_user} + like_now = current_user.like?(idea) + end + users_icon(users, like_now, "idea-#{idea.id}") + end + + def users_icon(users, current_user_show, klass = "") + content_tag :div, :class => 'user-icon' do + html = "" + users.each do |user| + html << image_tag(user.image_url, width: 30, height: 30, alt: user.nickname, title: user.nickname) + end + html << image_tag(current_user.image_url, width: 30, height: 30, alt: current_user.nickname, title: current_user.nickname, class: "#{klass} current-user-icon #{(current_user_show) ? '' : 'hidden-icon'}") + html.html_safe + end + end end diff --git a/app/views/ideas/show.html.haml b/app/views/ideas/show.html.haml index 60f04d9..b1dcf84 100644 --- a/app/views/ideas/show.html.haml +++ b/app/views/ideas/show.html.haml @@ -1,5 +1,7 @@ %h1 = @idea.title += likes_list(@idea) += like_button(@idea) %hr diff --git a/app/views/welcome/index.html.haml b/app/views/welcome/index.html.haml index 2d0fc84..db71c10 100644 --- a/app/views/welcome/index.html.haml +++ b/app/views/welcome/index.html.haml @@ -29,3 +29,7 @@ = idea.title - else = idea.title + %p + %span ↑ + = likes_list(idea) + = like_button(idea) diff --git a/config/routes.rb b/config/routes.rb index 8c94f3a..28c7245 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,8 @@ get '/auth/:provider/callback' => 'sessions#create' get '/auth/failure' => 'sessions#failure' get '/logout' => 'sessions#destroy', as: :logout + get '/like' => 'ideas#like', as: :like + get '/unlike' => 'ideas#unlike', as: :unlike resources :ideas, only: [:show, :create] do resources :comments, only: :create From 55371da29e4603223629abfa319893dab3e34df1 Mon Sep 17 00:00:00 2001 From: Yu Kitazume Date: Tue, 20 May 2014 19:51:21 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9C=AA=E3=83=AD=E3=82=AF=E3=82=99?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E6=99=82=E3=81=ABbug=E3=81=8B=E3=82=99?= =?UTF-8?q?=E3=81=82=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/application_helper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6948895..6e1b853 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -29,7 +29,9 @@ def users_icon(users, current_user_show, klass = "") users.each do |user| html << image_tag(user.image_url, width: 30, height: 30, alt: user.nickname, title: user.nickname) end - html << image_tag(current_user.image_url, width: 30, height: 30, alt: current_user.nickname, title: current_user.nickname, class: "#{klass} current-user-icon #{(current_user_show) ? '' : 'hidden-icon'}") + if logged_in? + html << image_tag(current_user.image_url, width: 30, height: 30, alt: current_user.nickname, title: current_user.nickname, class: "#{klass} current-user-icon #{(current_user_show) ? '' : 'hidden-icon'}") + end html.html_safe end end