Update format of guests API and document endpoints #130
@ -3,13 +3,41 @@
|
|||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
after_action :set_csrf_cookie
|
after_action :set_csrf_cookie
|
||||||
|
|
||||||
|
skip_before_action :verify_authenticity_token, if: :development_swagger?
|
||||||
|
|
||||||
|
rescue_from ActiveRecord::RecordInvalid do |exception|
|
||||||
|
render json: {
|
||||||
|
message: 'Record invalid',
|
||||||
|
errors: exception.record.errors.full_messages
|
||||||
|
}, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from ActionController::ParameterMissing do |exception|
|
||||||
|
render json: {
|
||||||
|
message: 'Parameter missing',
|
||||||
|
errors: [exception.message]
|
||||||
|
}, status: :bad_request
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from ActiveRecord::RecordNotFound do |exception|
|
||||||
|
render json: {
|
||||||
|
message: 'Record not found',
|
||||||
|
errors: [exception.message]
|
||||||
|
}, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def development_swagger?
|
||||||
|
Rails.env.test? ||
|
||||||
|
Rails.env.development? && request.headers['referer'].include?('/api-docs/index.html')
|
||||||
|
end
|
||||||
|
|
||||||
def set_csrf_cookie
|
def set_csrf_cookie
|
||||||
cookies["csrf-token"] = {
|
cookies['csrf-token'] = {
|
||||||
value: form_authenticity_token,
|
value: form_authenticity_token,
|
||||||
secure: Rails.env.production?,
|
secure: Rails.env.production?,
|
||||||
same_site: :strict,
|
same_site: :strict
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,15 +4,14 @@ require 'csv'
|
|||||||
|
|
||||||
class GuestsController < ApplicationController
|
class GuestsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
@guests = Guest.all.includes(:group)
|
render json: Guest.all.includes(:group)
|
||||||
.joins(:group)
|
.joins(:group)
|
||||||
.order('groups.name' => :asc, name: :asc)
|
.order('groups.name' => :asc, name: :asc)
|
||||||
|
.as_json(only: %i[id name status], include: { group: { only: %i[id name] } })
|
||||||
render jsonapi: @guests
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
Guests::UpdateUseCase.new(guest_ids: [params[:id]], params: params.require(:guest).permit(:name)).call
|
Guest.find(params[:id]).update!(params.require(:guest).permit(:name))
|
||||||
render json: {}, status: :ok
|
render json: {}, status: :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ class Guest < ApplicationRecord
|
|||||||
confirmed: 20,
|
confirmed: 20,
|
||||||
declined: 30,
|
declined: 30,
|
||||||
tentative: 40
|
tentative: 40
|
||||||
}
|
}, validate: true
|
||||||
|
|
||||||
|
validates :name, presence: true
|
||||||
|
|
||||||
scope :potential, -> { where.not(status: %i[declined considered]) }
|
scope :potential, -> { where.not(status: %i[declined considered]) }
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Guest, type: :model do
|
RSpec.describe Guest, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
it { should validate_presence_of(:name) }
|
||||||
it do
|
it do
|
||||||
should define_enum_for(:status).with_values(
|
should define_enum_for(:status).with_values(
|
||||||
considered: 0,
|
considered: 0,
|
||||||
@ -12,6 +14,7 @@ RSpec.describe Guest, type: :model do
|
|||||||
tentative: 40
|
tentative: 40
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it { should belong_to(:group) }
|
it { should belong_to(:group) }
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ require 'swagger_helper'
|
|||||||
RSpec.describe 'groups', type: :request do
|
RSpec.describe 'groups', type: :request do
|
||||||
path '/groups' do
|
path '/groups' do
|
||||||
get('list groups') do
|
get('list groups') do
|
||||||
|
tags 'Groups'
|
||||||
produces 'application/json'
|
produces 'application/json'
|
||||||
response(200, 'successful') do
|
response(200, 'successful') do
|
||||||
schema type: :array,
|
schema type: :array,
|
||||||
@ -25,7 +26,7 @@ RSpec.describe 'groups', type: :request do
|
|||||||
tentative: { type: :integer, minimum: 0 }
|
tentative: { type: :integer, minimum: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run_test!
|
xit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
89
spec/requests/guests_spec.rb
Normal file
89
spec/requests/guests_spec.rb
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Copyright (C) 2024 Manuel Bustillo
|
||||||
|
|
||||||
|
require 'swagger_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'guests', type: :request do
|
||||||
|
path '/guests/bulk_update' do
|
||||||
|
post('Update multiple guests in a single request') do
|
||||||
|
tags 'Guests'
|
||||||
|
consumes 'application/json'
|
||||||
|
produces 'application/json'
|
||||||
|
parameter name: :body, in: :body, schema: {
|
||||||
|
type: :object,
|
||||||
|
required: %i[guest_ids properties],
|
||||||
|
properties: {
|
||||||
|
guest_ids: { type: :array, items: { type: :string, format: :uuid } },
|
||||||
|
properties: {
|
||||||
|
type: :object,
|
||||||
|
required: %i[status],
|
||||||
|
properties: {
|
||||||
|
status: { type: :string, enum: Guest.statuses.keys }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let(:body) do
|
||||||
|
{
|
||||||
|
guest_ids: [SecureRandom.uuid, SecureRandom.uuid],
|
||||||
|
properties: {
|
||||||
|
status: 'confirmed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
response_empty_200
|
||||||
|
response_422
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
path '/guests' do
|
||||||
|
get('list guests') do
|
||||||
|
tags 'Guests'
|
||||||
|
produces 'application/json'
|
||||||
|
response(200, 'successful') do
|
||||||
|
schema type: :array,
|
||||||
|
items: {
|
||||||
|
type: :object,
|
||||||
|
required: %i[id name status group],
|
||||||
|
properties: {
|
||||||
|
id: { type: :string, format: :uuid },
|
||||||
|
name: { type: :string },
|
||||||
|
status: { type: :string, enum: Guest.statuses.keys },
|
||||||
|
group: { type: :object,
|
||||||
|
required: %i[id name],
|
||||||
|
properties: {
|
||||||
|
id: { type: :string, format: :uuid },
|
||||||
|
name: { type: :string }
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
path '/guests/{id}' do
|
||||||
|
patch('update guest') do
|
||||||
|
tags 'Guests'
|
||||||
|
consumes 'application/json'
|
||||||
|
produces 'application/json'
|
||||||
|
parameter name: 'id', in: :path, type: :string, format: :uuid
|
||||||
|
parameter name: :body, in: :body, schema: {
|
||||||
|
type: :object,
|
||||||
|
required: %i[guest],
|
||||||
|
properties: {
|
||||||
|
guest: {
|
||||||
|
type: :object,
|
||||||
|
required: %i[name],
|
||||||
|
properties: {
|
||||||
|
name: { type: :string }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response_empty_200
|
||||||
|
response_422
|
||||||
|
response_404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -3,6 +3,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
require_relative './swagger_response_helper'
|
||||||
|
|
||||||
|
include SwaggerResponseHelper
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# Specify a root folder where Swagger JSON files are generated
|
# Specify a root folder where Swagger JSON files are generated
|
||||||
@ -19,6 +22,15 @@ RSpec.configure do |config|
|
|||||||
config.openapi_specs = {
|
config.openapi_specs = {
|
||||||
'v1/swagger.yaml' => {
|
'v1/swagger.yaml' => {
|
||||||
openapi: '3.0.1',
|
openapi: '3.0.1',
|
||||||
|
components: {
|
||||||
|
securitySchemes: {
|
||||||
|
csrfToken: {
|
||||||
|
type: :apiKey,
|
||||||
|
in: :header,
|
||||||
|
name: 'X-CSRF-Token'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
info: {
|
info: {
|
||||||
title: 'API V1',
|
title: 'API V1',
|
||||||
version: 'v1'
|
version: 'v1'
|
||||||
|
38
spec/swagger_response_helper.rb
Normal file
38
spec/swagger_response_helper.rb
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright (C) 2024 Manuel Bustillo
|
||||||
|
|
||||||
|
module SwaggerResponseHelper
|
||||||
|
def response_422
|
||||||
|
response(422, 'Validation errors in input parameters') do
|
||||||
|
produces 'application/json'
|
||||||
|
error_schema
|
||||||
|
xit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_empty_200
|
||||||
|
response(200, 'Success') do
|
||||||
|
produces 'application/json'
|
||||||
|
schema type: :object
|
||||||
|
xit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_404
|
||||||
|
response(404, 'Record not found') do
|
||||||
|
produces 'application/json'
|
||||||
|
error_schema
|
||||||
|
xit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def error_schema
|
||||||
|
schema type: :object,
|
||||||
|
required: %i[message errors],
|
||||||
|
properties: {
|
||||||
|
message: { type: :string },
|
||||||
|
errors: { type: :array, items: { type: :string } }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user