Merge pull request 'Define CUD endpoints for the Groups model' (#173) from groups-endpoints into main
All checks were successful
Check usage of free licenses / check-licenses (push) Successful in 56s
Run unit tests / unit_tests (push) Successful in 2m28s
Build Nginx-based docker image / build-static-assets (push) Successful in 22m36s

Reviewed-on: #173
This commit is contained in:
bustikiller 2024-12-08 10:52:59 +00:00
commit cbcb7b70e3
11 changed files with 133 additions and 32 deletions

View File

@ -23,6 +23,7 @@ gem 'rubytree'
gem 'acts_as_tenant'
gem 'httparty'
gem 'rswag'
gem 'pluck_to_hash'
group :development, :test do
gem 'annotaterb'

View File

@ -222,6 +222,9 @@ GEM
ast (~> 2.4.1)
racc
pg (1.5.9)
pluck_to_hash (1.0.2)
activerecord (>= 4.0.2)
activesupport (>= 4.0.2)
pry (0.15.0)
coderay (~> 1.1)
method_source (~> 1.0)
@ -413,6 +416,7 @@ DEPENDENCIES
license_finder
money
pg (~> 1.1)
pluck_to_hash
pry
puma (>= 5.0)
rack-cors

View File

@ -4,4 +4,30 @@ class GroupsController < ApplicationController
def index
render json: Groups::SummaryQuery.new.call.as_json
end
def create
group = Group.create!(**group_params, parent:)
render json: group.as_json(only: %i[id name icon color parent_id]), status: :created
end
def update
group = Group.find(params[:id])
group.update!(**group_params, parent:)
render json: group.as_json(only: %i[id name icon color parent_id]), status: :ok
end
def destroy
Group.find(params[:id]).destroy!
render json: {}, status: :ok
end
private
def parent
params[:group][:parent_id].present? ? Group.find(params[:group][:parent_id]) : nil
end
def group_params
params.expect(group: [:name, :icon, :color])
end
end

View File

@ -38,7 +38,7 @@ class Group < ApplicationRecord
scope :roots, -> { where(parent_id: nil) }
has_many :guests
has_many :guests, dependent: :nullify
def colorize_children(generation = 1)
derived_colors = generation == 1 ? color.paint.palette.analogous(size: children.count) : color.paint.palette.decreasing_saturation

View File

@ -10,7 +10,7 @@
# status :integer default("considered")
# created_at :datetime not null
# updated_at :datetime not null
# group_id :uuid not null
# group_id :uuid
# wedding_id :uuid not null
#
# Indexes

View File

@ -3,29 +3,19 @@
module Groups
class SummaryQuery
def call
ActiveRecord::Base.connection.execute(query).to_a
end
private
def query
<<~SQL.squish
SELECT
groups.id,
groups.name,
groups.icon,
groups.parent_id,
groups.color,
count(*) filter (where status IS NOT NULL) as total,
count(*) filter (where status = 0) as considered,
count(*) filter (where status = 10) as invited,
count(*) filter (where status = 20) as confirmed,
count(*) filter (where status = 30) as declined,
count(*) filter (where status = 40) as tentative
FROM groups
LEFT JOIN guests on groups.id = guests.group_id
GROUP BY groups.id
SQL
Group.left_joins(:guests).group(:id).pluck_to_hash(
:id,
:name,
:icon,
:parent_id,
:color,
Arel.sql('count(*) filter (where status IS NOT NULL) as total'),
Arel.sql('count(*) filter (where status = 0) as considered'),
Arel.sql('count(*) filter (where status = 10) as invited'),
Arel.sql('count(*) filter (where status = 20) as confirmed'),
Arel.sql('count(*) filter (where status = 30) as declined'),
Arel.sql('count(*) filter (where status = 40) as tentative'),
)
end
end
end

View File

@ -23,7 +23,7 @@ Rails.application.routes.draw do
get '/users/confirmation', to: 'users/confirmations#show', as: :confirmation
end
resources :groups, only: :index
resources :groups, only: %i[index create update destroy]
resources :guests, only: %i[index create update destroy] do
post :bulk_update, on: :collection
end

View File

@ -0,0 +1,7 @@
# Copyright (C) 2024 Manuel Bustillo
class AllowUngroupedGuests < ActiveRecord::Migration[8.0]
def change
change_column_null :guests, :group_id, true
end
end

4
db/schema.rb generated
View File

@ -12,7 +12,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2024_12_07_112305) do
ActiveRecord::Schema[8.0].define(version: 2024_12_08_102932) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -48,7 +48,7 @@ ActiveRecord::Schema[8.0].define(version: 2024_12_07_112305) do
t.string "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.uuid "group_id", null: false
t.uuid "group_id"
t.integer "status", default: 0
t.string "name"
t.uuid "wedding_id", null: false

View File

@ -31,5 +31,72 @@ RSpec.describe 'groups', type: :request do
end
regular_api_responses
end
post('create group') do
tags 'Groups'
consumes 'application/json'
produces 'application/json'
parameter Swagger::Schema::SLUG
parameter name: :body, in: :body, schema: {
type: :object,
required: %i[group],
properties: {
group: {
type: :object,
required: %i[name],
properties: Swagger::Schema::GROUP
}
}
}
response(201, 'created') do
schema type: :object, properties: {
id: { type: :string, format: :uuid, required: true },
**Swagger::Schema::GROUP
}
xit
end
regular_api_responses
end
path '/{slug}/groups/{id}' do
put('update group') do
tags 'Groups'
consumes 'application/json'
produces 'application/json'
parameter Swagger::Schema::SLUG
parameter name: :id, in: :path, type: :string, format: :uuid
parameter name: :body, in: :body, schema: {
type: :object,
required: %i[group],
properties: {
group: {
type: :object,
required: %i[name],
properties: Swagger::Schema::GROUP
}
}
}
response(200, 'updated') do
schema type: :object, properties: {
id: { type: :string, format: :uuid, required: true },
**Swagger::Schema::GROUP
}
xit
end
regular_api_responses
end
delete('delete group') do
tags 'Groups'
produces 'application/json'
parameter Swagger::Schema::SLUG
parameter name: :id, in: :path, type: :string, format: :uuid
response_empty_200
regular_api_responses
end
end
end
end

View File

@ -4,10 +4,16 @@ module Swagger
module Schema
USER = {
id: { type: :string, format: :uuid },
email: { type: :string, format: :email },
created_at: SwaggerResponseHelper::TIMESTAMP,
updated_at: SwaggerResponseHelper::TIMESTAMP
email: { type: :string, format: :email },
created_at: SwaggerResponseHelper::TIMESTAMP,
updated_at: SwaggerResponseHelper::TIMESTAMP
}
GROUP = {
name: { type: :string },
icon: { type: :string, example: 'pi pi-crown', description: 'The CSS classes used by the icon' },
parent_id: { type: :string, format: :uuid },
color: { type: :string, pattern: '^#(?:[0-9a-fA-F]{3}){1,2}$' }
}
SLUG = {