Skip to content

Commit

Permalink
Add User Skills controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Rheniery committed Sep 25, 2024
1 parent c915e6e commit e98fdeb
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 6 deletions.
18 changes: 18 additions & 0 deletions app/controllers/skills_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,22 @@ class SkillsController < ApplicationController
def index
@skills = Skill.all
end

def create
@skill = Skill.new(skill_params)

if @skill.save
render json: @skill, status: :created, location: @skill
else
render json: @skill.errors, status: :unprocessable_entity
end
end

private


# Only allow a trusted parameter "white list" through.
def skill_params
params.require(:skill).permit(:name)
end
end
68 changes: 68 additions & 0 deletions app/controllers/user_skills_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# frozen_string_literal: true

class UserSkillsController < ApplicationController
before_action :set_user_skill, only: %i[destroy]

# GET /user_skills?user_id=:id
def index
@user_skills = UserSkill.where(user_id: params[:user_id])

render json: @user_skills
end

# POST /user_skills
def create
@user_skill = UserSkill.new(user_skill_params)

if @user_skill.save
render json: @user_skill, status: :created, location: @user_skill
else
render json: @user_skill.errors, status: :unprocessable_entity
end
end

# PATCH/PUT /user_skills
def bulk_update
ApplicationRecord.transaction do
# Remove all existing skills for the user
UserSkill.where(user_id: params.dig(:params, :user_id)).destroy_all

# Permit and process the new list of user skills
user_skills_list_params.each do |user_skill|
new_skill = UserSkill.new(user_skill.merge(user_id: params.dig(:params, :user_id)))
unless new_skill.save
raise ActiveRecord::Rollback
end
end
end

render json: { message: 'Skills updated successfully' }, status: :ok
end

# DELETE /user_skills/:id
def destroy
@user_skill.destroy
head :no_content
rescue ActiveRecord::RecordNotFound
head :not_found
end

private

# Use callbacks to share common setup or constraints between actions.
def set_user_skill
@user_skill = UserSkill.find(params[:id])
end

# Only allow a trusted parameter "white list" through.
def user_skills_list_params
params.require(:params).require(:user_skills).map do |skill|
skill.permit(:last_applied_in_year, :level, :years_of_experience, :skill_id)
end
end

# Only allow a trusted parameter "white list" through.
def user_skill_params
params.require(:user_skill).permit(:last_applied_in_year, :level, :years_of_experience, :skill_id, :user_id)
end
end
6 changes: 5 additions & 1 deletion app/models/skill.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_skills_on_lower_name (lower((name)::text)) UNIQUE
#
class Skill < ApplicationRecord
has_many :user_skills, dependent: :destroy
has_many :users, through: :user_skills

validates :name, presence: true
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
8 changes: 7 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require 'sidekiq/web'
require 'sidekiq/cron/web'

# rubocop:disable Metrics/BlockLength
Rails.application.routes.draw do
resources :dynamic_datasets
resources :time_offs, only: [:create]
Expand Down Expand Up @@ -38,4 +38,10 @@
resources :skills, only: [:index]
resources :issues, only: [:index]
resources :permissions, only: [:index]
resources :user_skills do
collection do
patch :bulk_update
end
end
end
# rubocop:enable Metrics/BlockLength
7 changes: 7 additions & 0 deletions db/migrate/20240923192947_add_unique_index_to_skills_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddUniqueIndexToSkillsName < ActiveRecord::Migration[7.0]
def change
add_index :skills, 'LOWER(name)', unique: true, name: 'index_skills_on_lower_name'
end
end
4 changes: 2 additions & 2 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 89 additions & 0 deletions spec/controllers/user_skills_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe UserSkillsController, type: :controller do
let(:user) { double("User", id: 1) }
let(:skill) { double("Skill", id: 1, name: 'Ruby') }
let(:user_skill) { double("UserSkill", id: 1, user_id: user.id, skill_id: skill.id, years_of_experience: 3, last_applied_in_year: 2021, level: 'beginner') }

before do
# Mocking UserSkill model interactions
allow(UserSkill).to receive(:where).and_return([user_skill])
allow(UserSkill).to receive(:new).and_return(user_skill)
allow(user_skill).to receive(:save).and_return(true)
allow(user_skill).to receive(:destroy).and_return(true)
allow(UserSkill).to receive(:find).and_return(user_skill)
end

describe 'GET #index' do
it 'returns a list of user skills' do
get :index, params: { user_id: user.id }

expect(UserSkill).to have_received(:where).with(user_id: user.id)
expect(response).to have_http_status(:ok)
end
end

describe 'POST #create' do
it 'creates a new user skill' do
post :create, params: {
user_skill: {
user_id: user.id,
skill_id: skill.id,
years_of_experience: 3,
last_applied_in_year: 2021,
level: 'beginner'
}
}

expect(UserSkill).to have_received(:new).with(
'user_id' => user.id.to_s,
'skill_id' => skill.id.to_s,
'years_of_experience' => '3',
'last_applied_in_year' => '2021',
'level' => 'beginner'
)
expect(user_skill).to have_received(:save)
expect(response).to have_http_status(:created)
end
end

describe 'PATCH #bulk_update' do
it 'updates the user skills' do
allow(UserSkill).to receive(:destroy_all).and_return(true)
patch :bulk_update, params: {
user_id: user.id,
user_skills: [
{
last_applied_in_year: 2023,
level: 'intermediate',
years_of_experience: 2,
skill_id: skill.id
}
]
}

expect(UserSkill).to have_received(:destroy_all).with(user_id: user.id)
expect(UserSkill).to have_received(:new).with(
'last_applied_in_year' => 2023,
'level' => 'intermediate',
'years_of_experience' => 2,
'skill_id' => skill.id,
'user_id' => user.id
)
expect(user_skill).to have_received(:save)
expect(response).to have_http_status(:ok)
end
end

describe 'DELETE #destroy' do
it 'deletes the user skill' do
delete :destroy, params: { id: user_skill.id }

expect(UserSkill).to have_received(:find).with(user_skill.id.to_s)
expect(user_skill).to have_received(:destroy)
expect(response).to have_http_status(:no_content)
end
end
end
4 changes: 4 additions & 0 deletions spec/factories/skills.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_skills_on_lower_name (lower((name)::text)) UNIQUE
#
FactoryBot.define do
factory :skill do
name { FFaker::Skill.tech_skill }
Expand Down
4 changes: 2 additions & 2 deletions spec/models/project_report_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# == Schema Information
#
# Table name: project_auths
# Table name: project_reports
#
# id :bigint not null, primary key
# key :string
Expand All @@ -12,7 +12,7 @@
#
# Indexes
#
# index_project_auths_on_project_id (project_id)
# index_project_reports_on_project_id (project_id)
#
# Foreign Keys
#
Expand Down
4 changes: 4 additions & 0 deletions spec/models/skill_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_skills_on_lower_name (lower((name)::text)) UNIQUE
#
require 'rails_helper'

RSpec.describe Skill, type: :model do
Expand Down

0 comments on commit e98fdeb

Please sign in to comment.