add batch endpoints for collection items
POST /collection/{characters,weapons,summons}/batch
This commit is contained in:
parent
4a471dd273
commit
99292f20ef
4 changed files with 210 additions and 15 deletions
|
|
@ -7,7 +7,7 @@ module Api
|
|||
before_action :set_collection_character_for_read, only: %i[show]
|
||||
|
||||
# Write actions: require auth, use current_user
|
||||
before_action :restrict_access, only: %i[create update destroy]
|
||||
before_action :restrict_access, only: %i[create update destroy batch]
|
||||
before_action :set_collection_character_for_write, only: %i[update destroy]
|
||||
|
||||
def index
|
||||
|
|
@ -74,6 +74,45 @@ module Api
|
|||
head :no_content
|
||||
end
|
||||
|
||||
# POST /collection/characters/batch
|
||||
# Creates multiple collection characters in a single request
|
||||
def batch
|
||||
items = batch_character_params[:collection_characters] || []
|
||||
created = []
|
||||
skipped = []
|
||||
errors = []
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
items.each_with_index do |item_params, index|
|
||||
# Check if already exists (skip duplicates)
|
||||
if current_user.collection_characters.exists?(character_id: item_params[:character_id])
|
||||
skipped << { index: index, character_id: item_params[:character_id], reason: 'already_exists' }
|
||||
next
|
||||
end
|
||||
|
||||
collection_character = current_user.collection_characters.build(item_params)
|
||||
|
||||
if collection_character.save
|
||||
created << collection_character
|
||||
else
|
||||
errors << {
|
||||
index: index,
|
||||
character_id: item_params[:character_id],
|
||||
error: collection_character.errors.full_messages.join(', ')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
status = errors.any? ? :multi_status : :created
|
||||
|
||||
render json: Api::V1::CollectionCharacterBlueprint.render(
|
||||
created,
|
||||
root: :characters,
|
||||
meta: { created: created.size, skipped: skipped.size, skipped_items: skipped, errors: errors }
|
||||
), status: status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_target_user
|
||||
|
|
@ -112,6 +151,18 @@ module Api
|
|||
earring: %i[modifier strength]
|
||||
)
|
||||
end
|
||||
|
||||
def batch_character_params
|
||||
params.permit(collection_characters: [
|
||||
:character_id, :uncap_level, :transcendence_step, :perpetuity,
|
||||
:awakening_id, :awakening_level,
|
||||
ring1: %i[modifier strength],
|
||||
ring2: %i[modifier strength],
|
||||
ring3: %i[modifier strength],
|
||||
ring4: %i[modifier strength],
|
||||
earring: %i[modifier strength]
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
module Api
|
||||
module V1
|
||||
class CollectionSummonsController < ApiController
|
||||
before_action :restrict_access
|
||||
before_action :set_collection_summon, only: %i[show update destroy]
|
||||
# Read actions: look up user from params, check privacy
|
||||
before_action :set_target_user, only: %i[index show]
|
||||
before_action :check_collection_access, only: %i[index show]
|
||||
before_action :set_collection_summon_for_read, only: %i[show]
|
||||
|
||||
# Write actions: require auth, use current_user
|
||||
before_action :restrict_access, only: %i[create update destroy batch]
|
||||
before_action :set_collection_summon_for_write, only: %i[update destroy]
|
||||
|
||||
def index
|
||||
@collection_summons = current_user.collection_summons
|
||||
@collection_summons = @target_user.collection_summons
|
||||
.includes(:summon)
|
||||
|
||||
@collection_summons = @collection_summons.by_summon(params[:summon_id]) if params[:summon_id]
|
||||
|
|
@ -16,7 +22,7 @@ module Api
|
|||
|
||||
render json: Api::V1::CollectionSummonBlueprint.render(
|
||||
@collection_summons,
|
||||
root: :collection_summons,
|
||||
root: :summons,
|
||||
meta: pagination_meta(@collection_summons)
|
||||
)
|
||||
end
|
||||
|
|
@ -57,9 +63,61 @@ module Api
|
|||
head :no_content
|
||||
end
|
||||
|
||||
# POST /collection/summons/batch
|
||||
# Creates multiple collection summons in a single request
|
||||
# Unlike characters, summons can have duplicates (user can own multiple copies)
|
||||
def batch
|
||||
items = batch_summon_params[:collection_summons] || []
|
||||
created = []
|
||||
errors = []
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
items.each_with_index do |item_params, index|
|
||||
collection_summon = current_user.collection_summons.build(item_params)
|
||||
|
||||
if collection_summon.save
|
||||
created << collection_summon
|
||||
else
|
||||
errors << {
|
||||
index: index,
|
||||
summon_id: item_params[:summon_id],
|
||||
error: collection_summon.errors.full_messages.join(', ')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
status = errors.any? ? :multi_status : :created
|
||||
|
||||
render json: Api::V1::CollectionSummonBlueprint.render(
|
||||
created,
|
||||
root: :summons,
|
||||
meta: { created: created.size, errors: errors }
|
||||
), status: status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_collection_summon
|
||||
def set_target_user
|
||||
@target_user = User.find(params[:user_id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render json: { error: "User not found" }, status: :not_found
|
||||
end
|
||||
|
||||
def check_collection_access
|
||||
return if @target_user.nil? # Already handled by set_target_user
|
||||
unless @target_user.collection_viewable_by?(current_user)
|
||||
render json: { error: "You do not have permission to view this collection" }, status: :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
def set_collection_summon_for_read
|
||||
@collection_summon = @target_user.collection_summons.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
raise CollectionErrors::CollectionItemNotFound.new('summon', params[:id])
|
||||
end
|
||||
|
||||
def set_collection_summon_for_write
|
||||
@collection_summon = current_user.collection_summons.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
raise CollectionErrors::CollectionItemNotFound.new('summon', params[:id])
|
||||
|
|
@ -70,6 +128,12 @@ module Api
|
|||
:summon_id, :uncap_level, :transcendence_step
|
||||
)
|
||||
end
|
||||
|
||||
def batch_summon_params
|
||||
params.permit(collection_summons: [
|
||||
:summon_id, :uncap_level, :transcendence_step
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
module Api
|
||||
module V1
|
||||
class CollectionWeaponsController < ApiController
|
||||
before_action :restrict_access
|
||||
before_action :set_collection_weapon, only: [:show, :update, :destroy]
|
||||
# Read actions: look up user from params, check privacy
|
||||
before_action :set_target_user, only: %i[index show]
|
||||
before_action :check_collection_access, only: %i[index show]
|
||||
before_action :set_collection_weapon_for_read, only: %i[show]
|
||||
|
||||
# Write actions: require auth, use current_user
|
||||
before_action :restrict_access, only: %i[create update destroy batch]
|
||||
before_action :set_collection_weapon_for_write, only: %i[update destroy]
|
||||
|
||||
def index
|
||||
@collection_weapons = current_user.collection_weapons
|
||||
@collection_weapons = @target_user.collection_weapons
|
||||
.includes(:weapon, :awakening,
|
||||
:weapon_key1, :weapon_key2,
|
||||
:weapon_key3, :weapon_key4)
|
||||
|
|
@ -18,7 +24,7 @@ module Api
|
|||
|
||||
render json: Api::V1::CollectionWeaponBlueprint.render(
|
||||
@collection_weapons,
|
||||
root: :collection_weapons,
|
||||
root: :weapons,
|
||||
meta: pagination_meta(@collection_weapons)
|
||||
)
|
||||
end
|
||||
|
|
@ -59,9 +65,61 @@ module Api
|
|||
head :no_content
|
||||
end
|
||||
|
||||
# POST /collection/weapons/batch
|
||||
# Creates multiple collection weapons in a single request
|
||||
# Unlike characters, weapons can have duplicates (user can own multiple copies)
|
||||
def batch
|
||||
items = batch_weapon_params[:collection_weapons] || []
|
||||
created = []
|
||||
errors = []
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
items.each_with_index do |item_params, index|
|
||||
collection_weapon = current_user.collection_weapons.build(item_params)
|
||||
|
||||
if collection_weapon.save
|
||||
created << collection_weapon
|
||||
else
|
||||
errors << {
|
||||
index: index,
|
||||
weapon_id: item_params[:weapon_id],
|
||||
error: collection_weapon.errors.full_messages.join(', ')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
status = errors.any? ? :multi_status : :created
|
||||
|
||||
render json: Api::V1::CollectionWeaponBlueprint.render(
|
||||
created,
|
||||
root: :weapons,
|
||||
meta: { created: created.size, errors: errors }
|
||||
), status: status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_collection_weapon
|
||||
def set_target_user
|
||||
@target_user = User.find(params[:user_id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render json: { error: "User not found" }, status: :not_found
|
||||
end
|
||||
|
||||
def check_collection_access
|
||||
return if @target_user.nil? # Already handled by set_target_user
|
||||
unless @target_user.collection_viewable_by?(current_user)
|
||||
render json: { error: "You do not have permission to view this collection" }, status: :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
def set_collection_weapon_for_read
|
||||
@collection_weapon = @target_user.collection_weapons.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
raise CollectionErrors::CollectionItemNotFound.new('weapon', params[:id])
|
||||
end
|
||||
|
||||
def set_collection_weapon_for_write
|
||||
@collection_weapon = current_user.collection_weapons.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
raise CollectionErrors::CollectionItemNotFound.new('weapon', params[:id])
|
||||
|
|
@ -76,6 +134,16 @@ module Api
|
|||
:element
|
||||
)
|
||||
end
|
||||
|
||||
def batch_weapon_params
|
||||
params.permit(collection_weapons: [
|
||||
:weapon_id, :uncap_level, :transcendence_step,
|
||||
:weapon_key1_id, :weapon_key2_id, :weapon_key3_id, :weapon_key4_id,
|
||||
:awakening_id, :awakening_level,
|
||||
:ax_modifier1, :ax_strength1, :ax_modifier2, :ax_strength2,
|
||||
:element
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -137,9 +137,21 @@ Rails.application.routes.draw do
|
|||
|
||||
# Writing to collections - requires auth, operates on current_user
|
||||
namespace :collection do
|
||||
resources :characters, only: [:create, :update, :destroy], controller: '/api/v1/collection_characters'
|
||||
resources :weapons, only: [:create, :update, :destroy], controller: '/api/v1/collection_weapons'
|
||||
resources :summons, only: [:create, :update, :destroy], controller: '/api/v1/collection_summons'
|
||||
resources :characters, only: [:create, :update, :destroy], controller: '/api/v1/collection_characters' do
|
||||
collection do
|
||||
post :batch
|
||||
end
|
||||
end
|
||||
resources :weapons, only: [:create, :update, :destroy], controller: '/api/v1/collection_weapons' do
|
||||
collection do
|
||||
post :batch
|
||||
end
|
||||
end
|
||||
resources :summons, only: [:create, :update, :destroy], controller: '/api/v1/collection_summons' do
|
||||
collection do
|
||||
post :batch
|
||||
end
|
||||
end
|
||||
resources :job_accessories, controller: '/api/v1/collection_job_accessories',
|
||||
only: [:index, :show, :create, :destroy]
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue