Skip to content

Commit

Permalink
Merge pull request #55 from WWC-Hackathon-2023/readme_final
Browse files Browse the repository at this point in the history
BE | Refactor `UserLoansController#create` & `#update`
  • Loading branch information
kem247 authored Oct 22, 2023
2 parents 0464b84 + cc153f4 commit 2e048ea
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 68 deletions.
28 changes: 18 additions & 10 deletions app/controllers/api/v1/users/loans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,34 @@ class Api::V1::Users::LoansController < ApplicationController

def create
loan = Loan.new(owner_id: @owner.id, puzzle_id: @puzzle.id, borrower_id: @borrower.id)

if loan.save
loan.puzzle.update(status: 1)
render json: LoanSerializer.new(loan), status: :created #201
else
render json: { error: "Unable to create loan" }, status: :unprocessable_entity #422
end
end

def update
user = User.find(params[:id])
loan = Loan.find(params[:loan_id])

if params[:action_type] == 'deny' || params[:action_type] == 'withdraw'
if loan.update(status: 2)
render json: LoanSerializer.new(loan), status: 200
else
render json: { error: "Unable to update loan status" }, status: 422
end
elsif params[:action_type] == 'invalid_action'
render json: { error: "Invalid action" }, status: 422
if params[:action_type] == 'accept'
loan.update(status: 1)
loan.puzzle.update(status: 2)
render json: LoanSerializer.new(loan), status: 200
elsif params[:action_type] == 'withdraw'
loan.update(status: 2)
loan.puzzle.update(status: 0)
render json: LoanSerializer.new(loan), status: 200
elsif params[:action_type] == 'deny'
loan.update(status: 2)
loan.puzzle.update(status: 2)
render json: LoanSerializer.new(loan), status: 200
elsif params[:action_type] == 'close'
loan.update(status: 3)
loan.puzzle.update(status: 0)
render json: LoanSerializer.new(loan), status: 200
else
render json: { error: "Unable to update loan status" }, status: 422
end
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
patch '/users/:user_id/puzzles/:puzzle_id', to: 'users/puzzles#update'

post '/users/:user_id/loans', to: 'users/loans#create'
patch '/users/:id/loans/:loan_id', to: 'users/loans#update'
patch '/users/:user_id/loans/:loan_id', to: 'users/loans#update'
end
end
end
151 changes: 94 additions & 57 deletions spec/requests/api/v1/users/loans_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@

RSpec.describe 'Users/LoansController' do
describe '#create' do
let(:user_1) { create(:user, id: 1) }
let(:user_2) { create(:user, id: 2) }
let(:puzzle_1) { create(:puzzle, user: user_1) }
let(:loan_1) { create(:loan, owner: user_1, borrower: user_2) }

context "when successful" do
it 'creates a new loan' do
user_1 = create(:user, id: 1)
user_2 = create(:user, id: 2)
puzzle_1 = create(:puzzle, user: user_1)

post "/api/v1/users/#{user_1.id}/loans", params: {

expect(puzzle_1.status).to eq("Available")

loan_request = {
puzzle_id: puzzle_1.id,
borrower_id: user_2.id
}

headers = { 'CONTENT_TYPE' => 'application/json' }
post "/api/v1/users/#{user_1.id}/loans", headers:, params: JSON.generate(loan_request)

expect(Loan.last.puzzle.status).to eq("Pending")
expect(response).to have_http_status(201)

parsed_data = JSON.parse(response.body, symbolize_names: true)
Expand Down Expand Up @@ -100,87 +101,123 @@
end

describe '#update' do
let(:user_1) { create(:user) }
let(:user_2) { create(:user) }
let(:puzzle_1) { create(:puzzle) }
let(:loan_2) { create(:loan, owner: user_1, borrower: user_2, puzzle: puzzle_1) }
before(:each) do
@user_1 = create(:user, id: 1)
@user_2 = create(:user, id: 2)
@puzzle_1 = create(:puzzle, user: @user_1)

loan_request = {
puzzle_id: @puzzle_1.id,
borrower_id: @user_2.id
}

headers = { 'CONTENT_TYPE' => 'application/json' }
post "/api/v1/users/#{@user_1.id}/loans", headers:, params: JSON.generate(loan_request)

@current_loan = Loan.last
end

context "when successful" do
it 'updates loan status to 2 when status is deny' do
patch "/api/v1/users/#{user_1.id}/loans/#{loan_2.id}", params: {
id: user_1.id, loan_id: loan_2.id, action_type: 'deny'
}
#REFACTOR: the following tests test both the puzzle status and the loan status changes

it 'updates loan status to Accepted when loan action type is Accept' do
expect(@current_loan.puzzle.status).to eq("Pending")

expect(response).to have_http_status(200)
expect(loan_2.reload.status).to eq('Cancelled')
loan_update = { action_type: "accept" }

parsed_data = JSON.parse(response.body, symbolize_names: true)
headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

expect(parsed_data).to be_a(Hash)
expect(parsed_data.keys).to eq([:data])
expect(parsed_data[:data]).to be_an(Hash)
expect(parsed_data[:data].keys).to eq([:id, :type, :attributes])
@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Not Available")

expect(parsed_data[:data][:attributes]).to be_a(Hash)
expect(parsed_data[:data][:attributes].keys).to eq([:owner_id, :borrower_id, :puzzle_id, :status])
expect(parsed_data[:data][:attributes][:owner_id]).to eq(loan_2.owner_id)
expect(parsed_data[:data][:attributes][:borrower_id]).to eq(loan_2.borrower_id)
expect(parsed_data[:data][:attributes][:puzzle_id]).to eq(loan_2.puzzle_id)
expect(parsed_data[:data][:attributes][:status]).to eq(loan_2.status)
expect(response).to have_http_status(200)
parsed_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_data[:data][:attributes][:status]).to eq("Accepted")
end

it 'updates loan status to 2 when status is withdraw' do
patch "/api/v1/users/#{user_1.id}/loans/#{loan_2.id}", params: {
id: user_1.id, loan_id: loan_2.id, action_type: 'withdraw'
}
it 'updates loan status to Cancelled when loan action type is Withdraw' do
expect(@current_loan.puzzle.status).to eq("Pending")

loan_update = { action_type: "withdraw" }

headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Available")

expect(response).to have_http_status(200)
expect(loan_2.reload.status).to eq('Cancelled')
parsed_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_data[:data][:attributes][:status]).to eq("Cancelled")
end

it 'updates loan status to Cancelled when loan action type is Deny' do
expect(@current_loan.puzzle.status).to eq("Pending")

loan_update = { action_type: "deny" }

headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Not Available")

expect(response).to have_http_status(200)
parsed_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_data[:data][:attributes][:status]).to eq("Cancelled")
end

expect(parsed_data).to be_a(Hash)
expect(parsed_data.keys).to eq([:data])
expect(parsed_data[:data]).to be_an(Hash)
expect(parsed_data[:data].keys).to eq([:id, :type, :attributes])
it 'updates loan status to Closed when loan action type is Close' do
expect(@current_loan.puzzle.status).to eq("Pending")

expect(parsed_data[:data][:attributes]).to be_a(Hash)
expect(parsed_data[:data][:attributes].keys).to eq([:owner_id, :borrower_id, :puzzle_id, :status])
expect(parsed_data[:data][:attributes][:owner_id]).to eq(loan_2.owner_id)
expect(parsed_data[:data][:attributes][:borrower_id]).to eq(loan_2.borrower_id)
expect(parsed_data[:data][:attributes][:puzzle_id]).to eq(loan_2.puzzle_id)
expect(parsed_data[:data][:attributes][:status]).to eq(loan_2.status)
loan_update = { action_type: "close" }

headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Available")

expect(response).to have_http_status(200)
parsed_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_data[:data][:attributes][:status]).to eq("Closed")
end
end

context "when NOT successful" do
it 'returns an error message when an action type is invalid' do
patch "/api/v1/users/#{user_1.id}/loans/#{loan_2.id}", params: {
id: user_1.id, loan_id: loan_2.id, action_type: 'invalid_action'
}
expect(@current_loan.puzzle.status).to eq("Pending")

expect(response).to have_http_status(422)
loan_update = { action_type: "puzzled" }

parsed_error_data = JSON.parse(response.body, symbolize_names: true)
headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Pending")

expect(response).to have_http_status(422)
parsed_error_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_error_data).to be_a(Hash)
expect(parsed_error_data.keys).to eq([:error])
expect(parsed_error_data[:error]).to eq("Invalid action")
expect(parsed_error_data[:error]).to eq("Unable to update loan status")
end

before do
it 'returns an error message when loan update fails' do
allow_any_instance_of(Loan).to receive(:update).and_return(false)
end
expect(@current_loan.puzzle.status).to eq("Pending")

it 'returns an error message when loan update fails' do
patch "/api/v1/users/#{user_1.id}/loans/#{loan_2.id}", params: {
id: user_1.id, loan_id: loan_2.id, action_type: 'deny'
}
loan_update = { action_type: "accepted" }

expect(response).to have_http_status(422)
headers = { 'CONTENT_TYPE' => 'application/json' }
patch "/api/v1/users/#{@user_1.id}/loans/#{@current_loan.id}", headers:, params: JSON.generate(loan_update)

parsed_error_data = JSON.parse(response.body, symbolize_names: true)
@current_loan.reload
expect(@current_loan.puzzle.status).to eq("Pending")

expect(response).to have_http_status(422)
parsed_error_data = JSON.parse(response.body, symbolize_names: true)
expect(parsed_error_data).to be_a(Hash)
expect(parsed_error_data.keys).to eq([:error])
expect(parsed_error_data[:error]).to eq("Unable to update loan status")
Expand Down

0 comments on commit 2e048ea

Please sign in to comment.