From 82ac6b237c8fe05f6613a4a7b6bbbedc498ec514 Mon Sep 17 00:00:00 2001 From: 23vbq <42277522+23vbq@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:24:07 +0200 Subject: [PATCH] Feature/group controller (#7) * first groups api test * code style fixes * started writing controller and fixed test * finished controller and fixed tests * postman collection for backend * code style fixes * code style fixes 2 --- .../app/controllers/application_controller.rb | 2 + .../controllers/concerns/exception_handler.rb | 13 ++ .../app/controllers/concerns/response.rb | 5 + .../app/controllers/group_controller.rb | 38 +++++ todo_backend/config/routes.rb | 1 + todo_backend/spec/factories/group.rb | 5 + todo_backend/spec/rails_helper.rb | 7 + todo_backend/spec/requests/group_spec.rb | 80 +++++++++++ .../spec/support/group_spec_helper.rb | 5 + todo_vue_rails.postman_collection.json | 136 ++++++++++++++++++ 10 files changed, 292 insertions(+) create mode 100644 todo_backend/app/controllers/concerns/exception_handler.rb create mode 100644 todo_backend/app/controllers/concerns/response.rb create mode 100644 todo_backend/app/controllers/group_controller.rb create mode 100644 todo_backend/spec/factories/group.rb create mode 100644 todo_backend/spec/requests/group_spec.rb create mode 100644 todo_backend/spec/support/group_spec_helper.rb create mode 100644 todo_vue_rails.postman_collection.json diff --git a/todo_backend/app/controllers/application_controller.rb b/todo_backend/app/controllers/application_controller.rb index 4ac8823..45e34ea 100644 --- a/todo_backend/app/controllers/application_controller.rb +++ b/todo_backend/app/controllers/application_controller.rb @@ -1,2 +1,4 @@ class ApplicationController < ActionController::API + include Response + include ExceptionHandler end diff --git a/todo_backend/app/controllers/concerns/exception_handler.rb b/todo_backend/app/controllers/concerns/exception_handler.rb new file mode 100644 index 0000000..94659c2 --- /dev/null +++ b/todo_backend/app/controllers/concerns/exception_handler.rb @@ -0,0 +1,13 @@ +module ExceptionHandler + extend ActiveSupport::Concern + + included do + rescue_from ActiveRecord::RecordNotFound do |e| + json_response({ message: e.message }, :not_found) + end + + rescue_from ActiveRecord::RecordInvalid do |e| + json_response({ message: e.message }, :unprocessable_entity) + end + end +end diff --git a/todo_backend/app/controllers/concerns/response.rb b/todo_backend/app/controllers/concerns/response.rb new file mode 100644 index 0000000..828b10d --- /dev/null +++ b/todo_backend/app/controllers/concerns/response.rb @@ -0,0 +1,5 @@ +module Response + def json_response(object, status = :ok) + render json: object, status: status + end +end diff --git a/todo_backend/app/controllers/group_controller.rb b/todo_backend/app/controllers/group_controller.rb new file mode 100644 index 0000000..962c03b --- /dev/null +++ b/todo_backend/app/controllers/group_controller.rb @@ -0,0 +1,38 @@ +class GroupController < ApplicationController +# skip_before_action :verify_authenticity_token +before_action :set_group, only: [ :update, :destroy ] + + # GET /group + def index + @groups = Group.all + json_response(@groups) + end + + # POST /group + def create + @group = Group.create!(group_params) + json_response(@group, :created) + end + + # PUT /group/:id + def update + @group.update(group_params) + head :no_content + end + + # DELETE /group/:id + def destroy + @group.destroy + head :no_content + end + + private + + def group_params + params.permit(:name) + end + + def set_group + @group = Group.find(params[:id]) + end +end diff --git a/todo_backend/config/routes.rb b/todo_backend/config/routes.rb index 33c9639..237d45a 100644 --- a/todo_backend/config/routes.rb +++ b/todo_backend/config/routes.rb @@ -11,4 +11,5 @@ # Defines the root path route ("/") # root "posts#index" + resources :group end diff --git a/todo_backend/spec/factories/group.rb b/todo_backend/spec/factories/group.rb new file mode 100644 index 0000000..c6e9636 --- /dev/null +++ b/todo_backend/spec/factories/group.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :group do + name { Faker::Lorem.unique.word } + end +end diff --git a/todo_backend/spec/rails_helper.rb b/todo_backend/spec/rails_helper.rb index 22883a8..35199da 100644 --- a/todo_backend/spec/rails_helper.rb +++ b/todo_backend/spec/rails_helper.rb @@ -39,6 +39,12 @@ end end +Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } + +# RSpec.configuration do |config| +# config.include RequestSpecHelper, type :request +# end + RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_paths = [ @@ -74,6 +80,7 @@ # config.filter_gems_from_backtrace("gem name") config.include FactoryBot::Syntax::Methods + config.include RequestSpecHelper config.before(:suite) do DatabaseCleaner.clean_with(:truncation) diff --git a/todo_backend/spec/requests/group_spec.rb b/todo_backend/spec/requests/group_spec.rb new file mode 100644 index 0000000..e48ee4c --- /dev/null +++ b/todo_backend/spec/requests/group_spec.rb @@ -0,0 +1,80 @@ +require 'rails_helper' + +RSpec.describe "Groups", type: :request do + # describe "GET /index" do + # pending "add some examples (or delete) #{__FILE__}" + # end + let!(:groups) { create_list(:group, 10) } + let(:group_id) { groups.first.id.to_s } + + # Get list of groups + describe "GET /group" do + before { get '/group' } + + it 'returns groups' do + expect(json).not_to be_empty + expect(json.size).to eq(10) + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + + # Create new group + describe "POST /group" do + let(:valid_attributes) { { name: 'Group' } } + + context "request is valid" do + before { post '/group', params: valid_attributes } + + it "creates a group" do + expect(json['name']).to eq('Group') + end + + it "returns status code 201" do + expect(response).to have_http_status(201) + end + end + + context "request is invalid" do + before { post '/group', params: {} } + + it "returns status code 422" do + expect(response).to have_http_status(422) + end + + it "returns validation presence failure" do + expect(response.body) + .to match("{\"message\":\"Validation failed: Name can't be blank\"}") + end + end + # TODO other validations + end + + # Update existing group + describe "PUT /group/:id" do + let(:valid_attributes) { { name: 'Tasks' } } + + context "record exists" do + before { put '/group/' + group_id, params: valid_attributes } + + it "updates record" do + expect(response.body).to be_empty + end + + it "returns status code 204" do + expect(response).to have_http_status(204) + end + end + end + + # Delete group + describe "DELETE /group/:id" do + before { delete '/group/' + group_id } + + it "returns status code 204" do + expect(response).to have_http_status(204) + end + end +end diff --git a/todo_backend/spec/support/group_spec_helper.rb b/todo_backend/spec/support/group_spec_helper.rb new file mode 100644 index 0000000..ef7a657 --- /dev/null +++ b/todo_backend/spec/support/group_spec_helper.rb @@ -0,0 +1,5 @@ +module RequestSpecHelper + def json + JSON.parse(response.body) + end +end diff --git a/todo_vue_rails.postman_collection.json b/todo_vue_rails.postman_collection.json new file mode 100644 index 0000000..1856233 --- /dev/null +++ b/todo_vue_rails.postman_collection.json @@ -0,0 +1,136 @@ +{ + "info": { + "_postman_id": "e45012ad-df75-41a5-83cd-f8ad1ddb265e", + "name": "todo_vue_rails", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "29255098" + }, + "item": [ + { + "name": "group", + "item": [ + { + "name": "List groups", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{ADDR}}/group", + "host": [ + "{{ADDR}}" + ], + "path": [ + "group" + ] + } + }, + "response": [] + }, + { + "name": "Create group", + "request": { + "method": "POST", + "header": [], + "url": { + "raw": "{{ADDR}}/group?name", + "host": [ + "{{ADDR}}" + ], + "path": [ + "group" + ], + "query": [ + { + "key": "name", + "value": null + } + ] + } + }, + "response": [] + }, + { + "name": "Update group", + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{ADDR}}/group/:id?name", + "host": [ + "{{ADDR}}" + ], + "path": [ + "group", + ":id" + ], + "query": [ + { + "key": "name", + "value": null + } + ], + "variable": [ + { + "key": "id", + "value": "" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete group", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{ADDR}}/group/:id", + "host": [ + "{{ADDR}}" + ], + "path": [ + "group", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "" + } + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "ADDR", + "value": "http://localhost:3000", + "type": "string" + } + ] +} \ No newline at end of file