diff --git a/.rubocop.yml b/.rubocop.yml index 86b23e6..96c38e3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -24,6 +24,9 @@ AllCops: Documentation: Enabled: false +Lint/Void: + Exclude: + - spec/support/**/* HasAndBelongsToMany: Enabled: false @@ -34,3 +37,5 @@ Metrics/BlockLength: Style/FrozenStringLiteralComment: Enabled: false + + diff --git a/app/controllers/api/v1/api_controller.rb b/app/controllers/api/v1/api_controller.rb index e1d972d..536808a 100644 --- a/app/controllers/api/v1/api_controller.rb +++ b/app/controllers/api/v1/api_controller.rb @@ -5,6 +5,14 @@ class ApiController < ::ActionController::API include Pagination before_action :authenticate_user! + + rescue_from ActionController::ParameterMissing, with: :parameter_missing + + private + + def parameter_missing(error) + render json: { error: error }, status: :bad_request + end end end end diff --git a/app/controllers/api/v1/labs_controller.rb b/app/controllers/api/v1/labs_controller.rb index 232c45e..3231ef0 100644 --- a/app/controllers/api/v1/labs_controller.rb +++ b/app/controllers/api/v1/labs_controller.rb @@ -4,6 +4,24 @@ class LabsController < ApiController def index render_paginated Lab.all end + + def create + lab = Lab.new(permitted_params) + if lab.save + render json: lab, status: :created + else + render json: { errors: lab.errors }, status: :unprocessable_entity + end + end + + private + + def permitted_params + params.require(:lab).permit( + :name, :address, :location, :ownership, :has_farmacy, + :identified_patients, :permanently_identified_patients + ) + end end end end diff --git a/config/routes.rb b/config/routes.rb index fc78bc9..9ddad8a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,7 +12,7 @@ get :me end end - resources :labs, only: [:index] + resources :labs, only: [:index, :create] resources :specimen_sources, only: [:index] end end diff --git a/spec/controllers/api/v1/labs_controller_spec.rb b/spec/controllers/api/v1/labs_controller_spec.rb index 0f40b70..b3cadf9 100644 --- a/spec/controllers/api/v1/labs_controller_spec.rb +++ b/spec/controllers/api/v1/labs_controller_spec.rb @@ -15,7 +15,7 @@ let!(:labs) { create_list :lab, 10 } before do authenticate(user) - get :index + post :index end it 'responds ok' do @@ -25,4 +25,21 @@ it_behaves_like 'a paginated request', Lab.all end end + + describe 'POST /labs' do + context 'with an unauthenticated user' do + before { post :create } + + it 'should respond unauthorized' do + expect(response).to have_http_status(:unauthorized) + end + end + + context 'with an authenticated user' do + before { authenticate(user) } + let(:user) { create :user } + + it_behaves_like 'a create endpoint', Lab, :create, :name + end + end end diff --git a/spec/support/shared_examples/create_endpoint.rb b/spec/support/shared_examples/create_endpoint.rb new file mode 100644 index 0000000..fbb106e --- /dev/null +++ b/spec/support/shared_examples/create_endpoint.rb @@ -0,0 +1,66 @@ +RSpec.shared_examples 'a create endpoint' do |entity, action, required_field| + let!(:entity_name) { entity.name.underscore.singularize } + let(:create_request) { post action, params: params } + + context 'with required fields' do + let(:attributes) { attributes_for(entity_name) } + let(:params) { { entity_name => attributes } } + + it 'creates the new entity' do + expect { create_request }.to(change { entity.count }.by(1)) + end + it 'renders the new entity' do + create_request + expect(response_body).to eq( + JSON[ + ActiveModelSerializers::SerializableResource.new( + entity.first + ).to_json + ].symbolize_keys + ) + end + it 'responds with created' do + create_request + expect(response).to have_http_status(:created) + end + end + + context 'without required fields' do + let(:params) { {} } + + it 'does not create the new entity' do + expect { create_request }.not_to(change { entity.count }) + end + it 'renders the missing fields' do + create_request + # TODO: add I18n to the error text + expect(response_body).to eq( + error: "param is missing or the value is empty: #{entity_name}" + ) + end + it 'renders bad request' do + create_request + expect(response).to have_http_status(:bad_request) + end + end + + context 'with invalid fields' do + let(:params) do + { entity_name => attributes_for(entity_name, required_field => '') } + end + + it 'does not create the new entity' do + expect { create_request }.not_to(change { entity.count }) + end + it 'renders the errors' do + create_request + expect(response_body).to have_key( + :errors + ) + end + it 'renders unprocessable entity' do + create_request + expect(response).to have_http_status(:unprocessable_entity) + end + end +end