Add likes model, controller and tests

This commit is contained in:
riggraz
2019-09-27 12:32:30 +02:00
parent e1d8dbc281
commit 970cd6934c
13 changed files with 118 additions and 2 deletions

View File

@@ -0,0 +1,3 @@
// Place all the styles related to the likes controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@@ -0,0 +1,33 @@
class LikesController < ApplicationController
before_action :authenticate_user!
def create
like = Like.new(like_params)
if like.save
render json: like, status: :created
else
render json: {
error: I18n.t('errors.likes.create', message: like.errors.full_messages)
}, status: :unprocessable_entity
end
end
def destroy
like = Like.where(like_params)
if like.destroy
render json: {}, status: :no_content
else
render json: {
error: I18n.t('errors.likes.destroy', message: like.errors.full_messages)
}, status: :unprocessable_entity
end
end
private
def like_params
params.permit(:post_id).merge(user_id: current_user.id)
end
end

View File

@@ -0,0 +1,2 @@
module LikesHelper
end

6
app/models/like.rb Normal file
View File

@@ -0,0 +1,6 @@
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
validates :user_id, uniqueness: { scope: :post_id }
end

View File

@@ -2,6 +2,7 @@ class Post < ApplicationRecord
belongs_to :board belongs_to :board
belongs_to :user belongs_to :user
belongs_to :post_status, optional: true belongs_to :post_status, optional: true
has_many :likes, dependent: :destroy
has_many :comments, dependent: :destroy has_many :comments, dependent: :destroy
validates :title, presence: true, length: { in: 4..64 } validates :title, presence: true, length: { in: 4..64 }

View File

@@ -4,6 +4,7 @@ class User < ApplicationRecord
:confirmable :confirmable
has_many :posts, dependent: :destroy has_many :posts, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :comments, dependent: :destroy has_many :comments, dependent: :destroy
enum role: [:user, :moderator, :admin] enum role: [:user, :moderator, :admin]

View File

@@ -4,5 +4,7 @@ en:
post: post:
create: 'Post create error: %{message}' create: 'Post create error: %{message}'
update: 'Post update error: %{message}' update: 'Post update error: %{message}'
like:
create: 'Like create error: %{message}'
comment: comment:
create: 'Comment create error: %{message}' create: 'Comment create error: %{message}'

View File

@@ -14,9 +14,10 @@ Rails.application.routes.draw do
devise_for :users devise_for :users
resources :boards, only: [:show]
resources :posts, only: [:index, :create, :show, :update] do resources :posts, only: [:index, :create, :show, :update] do
resource :likes, only: [:create, :destroy]
resources :comments, only: [:index, :create] resources :comments, only: [:index, :create]
end end
resources :boards, only: [:show]
resources :post_statuses, only: [:index] resources :post_statuses, only: [:index]
end end

View File

@@ -0,0 +1,12 @@
class CreateLikes < ActiveRecord::Migration[6.0]
def change
create_table :likes do |t|
t.references :user, null: false, foreign_key: true
t.references :post, null: false, foreign_key: true
t.timestamps
end
add_index :likes, [:user_id, :post_id], unique: true
end
end

View File

@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_09_18_151626) do ActiveRecord::Schema.define(version: 2019_09_27_094233) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -36,6 +36,16 @@ ActiveRecord::Schema.define(version: 2019_09_18_151626) do
t.index ["user_id"], name: "index_comments_on_user_id" t.index ["user_id"], name: "index_comments_on_user_id"
end end
create_table "likes", force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "post_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["post_id"], name: "index_likes_on_post_id"
t.index ["user_id", "post_id"], name: "index_likes_on_user_id_and_post_id", unique: true
t.index ["user_id"], name: "index_likes_on_user_id"
end
create_table "post_statuses", force: :cascade do |t| create_table "post_statuses", force: :cascade do |t|
t.string "name", null: false t.string "name", null: false
t.string "color", null: false t.string "color", null: false
@@ -81,6 +91,8 @@ ActiveRecord::Schema.define(version: 2019_09_18_151626) do
add_foreign_key "comments", "comments", column: "parent_id" add_foreign_key "comments", "comments", column: "parent_id"
add_foreign_key "comments", "posts" add_foreign_key "comments", "posts"
add_foreign_key "comments", "users" add_foreign_key "comments", "users"
add_foreign_key "likes", "posts"
add_foreign_key "likes", "users"
add_foreign_key "posts", "boards" add_foreign_key "posts", "boards"
add_foreign_key "posts", "post_statuses" add_foreign_key "posts", "post_statuses"
add_foreign_key "posts", "users" add_foreign_key "posts", "users"

6
spec/factories/likes.rb Normal file
View File

@@ -0,0 +1,6 @@
FactoryBot.define do
factory :like do
user
post
end
end

19
spec/models/like_spec.rb Normal file
View File

@@ -0,0 +1,19 @@
require 'rails_helper'
RSpec.describe Like, type: :model do
let(:like) { FactoryBot.build(:like) }
it 'is valid' do
expect(like).to be_valid
end
it 'must have a user_id' do
like.user = nil
expect(like).to be_invalid
end
it 'must have a post_id' do
like.post = nil
expect(like).to be_invalid
end
end

View File

@@ -0,0 +1,18 @@
require 'rails_helper'
RSpec.describe 'likes routing', :aggregate_failures, type: :routing do
it 'routes likes' do
expect(post: '/posts/1/likes').to route_to(
controller: 'likes', action: 'create', post_id: "1"
)
expect(delete: '/posts/1/likes').to route_to(
controller: 'likes', action: 'destroy', post_id: "1"
)
expect(get: '/posts/1/likes').not_to be_routable
expect(get: '/posts/1/likes/1').not_to be_routable
expect(get: '/posts/1/likes/new').not_to be_routable
expect(get: '/posts/1/likes/1/edit').not_to be_routable
expect(patch: '/posts/1/likes/1').not_to be_routable
end
end