Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a feature to send likes for ideas #7

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/assets/stylesheets/welcome.css.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
// Place all the styles related to the welcome controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
.likeLink {
float: right;
}

.ideaLink {
float: left;
}

.list-group-item {
clear: both;
}
20 changes: 19 additions & 1 deletion app/controllers/ideas_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
class IdeasController < ApplicationController
before_action :authenticate, except: :show
before_action :find_idea, only: [:show, :like, :dislike]

def show
@idea = Idea.find(params[:id])
@comments = @idea.comments
@comment = Comment.new
end
Expand All @@ -18,4 +18,22 @@ def create
render 'welcome/index'
end
end

# PUT /like/1
def like
current_user.like @idea

redirect_to root_path, notice: 'いいね!しました。'
end

def dislike
current_user.dislike @idea

redirect_to root_path
end

private
def find_idea
@idea = Idea.find(params[:id])
end
end
1 change: 1 addition & 0 deletions app/models/comment.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Comment < ActiveRecord::Base
belongs_to :idea
belongs_to :user
has_many :likes, as: :likeable

validates :body, length: { maximum: 1000 }, presence: true
end
1 change: 1 addition & 0 deletions app/models/idea.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Idea < ActiveRecord::Base
has_many :comments
belongs_to :user
has_many :likes, as: :likeable

validates :title, length: { maximum: 100 }, presence: true
end
6 changes: 6 additions & 0 deletions app/models/like.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :likeable, polymorphic: true

validates :user_id, uniqueness: {scope: [:likeable_id, :likeable_type]}
end
14 changes: 14 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,18 @@ def self.find_or_create_from_auth_hash(auth_hash)
user.image_url = image_url
end
end

def like(idea)
idea.likes.create!(user_id: id)
end

def dislike(idea)
like = idea.likes.where(user_id: id).first
raise ActiveRecord::RecordNotFound if like.nil?
like.destroy
end

def liked?(idea)
idea.likes.where(user_id: id).count > 0
end
end
13 changes: 10 additions & 3 deletions app/views/welcome/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@
.list-group
- @ideas.each do |idea|
.list-group-item
.ideaLink
= link_to idea do
- if idea.user.try(:image_url)
= image_tag(idea.user.image_url, width: 30, height: 30, alt: idea.user.nickname, title: idea.user.nickname).html_safe
= idea.title
- else
= idea.title
= idea.title
= "(#{idea.likes.count} いいね!)"

.likeLink
- if current_user
- if current_user.liked?(idea)
= link_to 'いいね!を取り消す', dislike_idea_path(idea), class: 'dislike', method: :put
- else
= link_to 'いいね!', like_idea_path(idea), class: 'like', method: :put
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
get '/logout' => 'sessions#destroy', as: :logout

resources :ideas, only: [:show, :create] do
member do
put :like
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PATCHですかね

put :dislike
end
resources :comments, only: :create
end

Expand Down
14 changes: 14 additions & 0 deletions db/migrate/20140520051103_create_likes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateLikes < ActiveRecord::Migration
def change
create_table :likes do |t|
t.integer :likeable_id
t.string :likeable_type
t.belongs_to :user, index: true

t.timestamps
end

add_index :likes, [:likeable_id, :likeable_type]
add_index :likes, [:likeable_id, :likeable_type, :user_id], unique: true
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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: 20140520051103) do

create_table "comments", force: true do |t|
t.integer "idea_id"
Expand All @@ -33,6 +33,18 @@

add_index "ideas", ["user_id"], name: "index_ideas_on_user_id"

create_table "likes", force: true do |t|
t.integer "likeable_id"
t.string "likeable_type"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end

add_index "likes", ["likeable_id", "likeable_type", "user_id"], name: "index_likes_on_likeable_id_and_likeable_type_and_user_id", unique: true
add_index "likes", ["likeable_id", "likeable_type"], name: "index_likes_on_likeable_id_and_likeable_type"
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
Expand Down
9 changes: 9 additions & 0 deletions spec/factories/likes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Read about factories at https://github.com/thoughtbot/factory_girl

FactoryGirl.define do
factory :like do
likeable_id 1
likeable_type "MyString"
user nil
end
end
49 changes: 49 additions & 0 deletions spec/features/like_idea_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
require 'spec_helper'

describe 'アイデアに「いいね!」を付けられるようにする' do
let(:idea) { create :idea }

context '未ログイン状態でトップページにアクセスしたとき' do
before { visit root_path(idea) }

it 'いいね!用のリンクが表示されていないこと' do
expect(page).to have_no_css 'a.like'
end
end

context 'ログイン状態でトップページにアクセスしたとき' do
before do
idea
login
visit root_path
end

context 'いいね!を付ける前のとき' do
it 'いいね!用のリンクが表示されていること' do
expect(page).to have_css 'a.like'
end
end

context 'いいね!ボタンを押したとき' do
before do
click_link 'いいね!'
end

it '"いいね!を取り消す"と表示されていること' do
expect(page).to have_css 'a.dislike'
end

it '"いいね!"した人の数が表示されていること' do
expect(page).to have_content "(1 いいね!)"
end

it '"いいね!"を取り消すことができること' do
click_link 'いいね!を取り消す'
expect(page).to have_content "(0 いいね!)"
expect(page).to have_css 'a.like'
end
end

end
end
6 changes: 6 additions & 0 deletions spec/models/like_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'spec_helper'

describe Like do
it { should belong_to(:user) }
it { should belong_to(:likeable) }
end
75 changes: 75 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,79 @@
end
end
end

describe '#like' do
let!(:user) { create :user, provider: 'twitter', uid: 'uid' }
let!(:comment) { create :comment }
let(:idea) { comment.idea }

context "アイデアに対して" do
it 'いいね!をするとlikeが増える' do
expect {
user.like(idea)
}.to change(idea.likes, :count).by(1)
end
end

context "コメントに対して" do
it 'いいね!をするとlikeが増える' do
expect {
user.like(comment)
}.to change(comment.likes, :count).by(1)
end
end
end

describe "#dislike" do
let!(:user) { create :user, provider: 'twitter', uid: 'uid' }
let!(:comment) { create :comment }
let(:idea) { comment.idea }

context "アイデアに対して" do
context "すでにいいね!している場合" do
before do
user.like(idea)
end

it 'いいね!を取り消すとlikeが減る' do
expect {
user.dislike(idea)
}.to change(idea.likes, :count).by(-1)
end
end

context "いいね!していない場合" do
it 'RecordNotFoundが返る' do
expect {
user.dislike(idea)
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

context "コメントに対して" do
context "すでにいいね!している場合" do
before do
user.like(comment)
end

it 'いいね!を取り消すとlikeが減る' do
expect {
user.dislike(comment)
}.to change(comment.likes, :count).by(-1)
end
end

context "いいね!していない場合" do
it 'RecordNotFoundが返る' do
expect {
user.dislike(comment)
}.to raise_error(ActiveRecord::RecordNotFound)
end
end

end


end
end