diff --git a/app/assets/javascripts/likes.js.coffee b/app/assets/javascripts/likes.js.coffee new file mode 100644 index 0000000..fea3c7b --- /dev/null +++ b/app/assets/javascripts/likes.js.coffee @@ -0,0 +1,22 @@ +$ -> + $('.btn_like_idea').click -> + $(@).attr('disabled', '') + likable_id = $(@).attr("name").match(/^like_button_idea([0-9]+)/)[1] + url = '/likes/ideas/' + likable_id + '.json' + $.getJSON url, (json) -> + if json.status + button_name = 'like_button_idea' + json.likable_id + $("button[name='" + button_name + "']").each -> + $(@).removeAttr('disabled') + $(@).find('.like_count').text(json.count) + + $('.btn_like_comment').click -> + $(@).attr('disabled', '') + likable_id = $(@).attr("name").match(/^like_button_comment([0-9]+)/)[1] + url = '/likes/comments/' + likable_id + '.json' + $.getJSON url, (json) -> + if json.status + button_name = 'like_button_comment' + json.likable_id + $("button[name='" + button_name + "']").each -> + $(@).removeAttr('disabled') + $(@).find('.like_count').text(json.count) diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb new file mode 100644 index 0000000..0e984f0 --- /dev/null +++ b/app/controllers/likes_controller.rb @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +class LikesController < ApplicationController + before_action :authenticate, except: :show + + def idea + @idea = Idea.find(params[:likable_id]) + if current_user + @current_user_like = @idea.like(current_user) + end + end + + def comment + @comment = Comment.find(params[:likable_id]) + if current_user + @current_user_like = @comment.like(current_user) + end + end +end diff --git a/app/models/comment.rb b/app/models/comment.rb index a3d82d4..d152ac3 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,6 @@ class Comment < ActiveRecord::Base + include Liking + belongs_to :idea belongs_to :user diff --git a/app/models/concerns/liking.rb b/app/models/concerns/liking.rb new file mode 100644 index 0000000..40b9230 --- /dev/null +++ b/app/models/concerns/liking.rb @@ -0,0 +1,21 @@ +module Liking + extend ActiveSupport::Concern + + included do + has_many :likes, as: :likable + + def like_count + self.likes.active.count + end + + def like(user) + user_like = self.likes.find_by(user: user) + if user_like + user_like.toggle! + else + user_like = self.likes.create(user: user) + end + user_like + end + end +end diff --git a/app/models/idea.rb b/app/models/idea.rb index bfdf8f2..f0aefff 100644 --- a/app/models/idea.rb +++ b/app/models/idea.rb @@ -1,4 +1,6 @@ class Idea < ActiveRecord::Base + include Liking + has_many :comments belongs_to :user diff --git a/app/models/like.rb b/app/models/like.rb new file mode 100644 index 0000000..f87e02e --- /dev/null +++ b/app/models/like.rb @@ -0,0 +1,11 @@ +class Like < ActiveRecord::Base + belongs_to :likable, polymorphic: true + belongs_to :user + + scope :active, -> { where(deleted: false) } + + def toggle! + self.deleted = self.deleted ? false : true + self.save! + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 8a46437..c195383 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ class User < ActiveRecord::Base has_many :ideas + has_many :likes def self.find_or_create_from_auth_hash(auth_hash) provider = auth_hash[:provider] diff --git a/app/views/ideas/show.html.haml b/app/views/ideas/show.html.haml index 60f04d9..a11ee32 100644 --- a/app/views/ideas/show.html.haml +++ b/app/views/ideas/show.html.haml @@ -1,5 +1,9 @@ %h1 = @idea.title + = button_tag name: "like_button_idea#{@idea.id}", class: "btn_like_idea btn pull-right" do + %span.glyphicon.glyphicon-thumbs-up + %span.like_count + = @idea.like_count %hr @@ -12,6 +16,12 @@ = comment.body - else = comment.body + + = button_tag name: "like_button_comment#{comment.id}", class: "btn_like_comment btn pull-right" do + %span.glyphicon.glyphicon-thumbs-up + %span.like_count + = comment.like_count + - if logged_in? = form_for [@idea, @comment] do |f| - if @comment.errors.any? diff --git a/app/views/likes/comment.json.jbuilder b/app/views/likes/comment.json.jbuilder new file mode 100644 index 0000000..9d49342 --- /dev/null +++ b/app/views/likes/comment.json.jbuilder @@ -0,0 +1,7 @@ +json.count @comment.like_count +if @current_user_like + json.(@current_user_like, :likable_id, :id, :created_at, :updated_at) + json.status true +else + json.status false +end diff --git a/app/views/likes/idea.json.jbuilder b/app/views/likes/idea.json.jbuilder new file mode 100644 index 0000000..b078c4e --- /dev/null +++ b/app/views/likes/idea.json.jbuilder @@ -0,0 +1,7 @@ +json.count @idea.like_count +if @current_user_like + json.(@current_user_like, :likable_id, :id, :created_at, :updated_at) + json.status true +else + json.status false +end diff --git a/app/views/welcome/index.html.haml b/app/views/welcome/index.html.haml index 2d0fc84..42b037e 100644 --- a/app/views/welcome/index.html.haml +++ b/app/views/welcome/index.html.haml @@ -29,3 +29,8 @@ = idea.title - else = idea.title + + = button_tag name: "like_button_idea#{idea.id}", class: "btn_like_idea btn pull-right" do + %span.glyphicon.glyphicon-thumbs-up + %span.like_count + = idea.like_count diff --git a/config/routes.rb b/config/routes.rb index 8c94f3a..24cc656 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,5 +8,10 @@ resources :comments, only: :create end + scope :likes do + get 'ideas/:likable_id' => 'likes#idea' + get 'comments/:likable_id' => 'likes#comment' + end + match '*path' => 'application#error404', via: :all end diff --git a/db/migrate/20140517034628_create_likes.rb b/db/migrate/20140517034628_create_likes.rb new file mode 100644 index 0000000..955b159 --- /dev/null +++ b/db/migrate/20140517034628_create_likes.rb @@ -0,0 +1,14 @@ +class CreateLikes < ActiveRecord::Migration + def change + create_table :likes do |t| + t.string :likable_type, null: false + t.integer :likable_id, null: false + t.integer :user_id, null: false + t.boolean :deleted, null: false, default: false + + t.timestamps + end + + add_index :likes, [:likable_type, :user_id] + end +end diff --git a/db/schema.rb b/db/schema.rb index 58b5f42..1b743d2 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: 20140517034628) 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.string "likable_type", null: false + t.integer "likable_id", null: false + t.integer "user_id", null: false + t.boolean "deleted", default: false, null: false + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "likes", ["likable_type", "user_id"], name: "index_likes_on_likable_type_and_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..6250a33 --- /dev/null +++ b/spec/models/like_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Like do + pending "add some examples to (or delete) #{__FILE__}" +end