Add method comments
This commit is contained in:
parent
9f86f3bf29
commit
1bc7d5fac9
1 changed files with 104 additions and 0 deletions
|
|
@ -2,22 +2,41 @@
|
||||||
|
|
||||||
module Api
|
module Api
|
||||||
module V1
|
module V1
|
||||||
|
# Controller for managing party-related operations in the API
|
||||||
|
# @api public
|
||||||
class PartiesController < Api::V1::ApiController
|
class PartiesController < Api::V1::ApiController
|
||||||
before_action :set_from_slug,
|
before_action :set_from_slug,
|
||||||
except: %w[create destroy update index favorites]
|
except: %w[create destroy update index favorites]
|
||||||
before_action :set, only: %w[update destroy]
|
before_action :set, only: %w[update destroy]
|
||||||
before_action :authorize, only: %w[update destroy]
|
before_action :authorize, only: %w[update destroy]
|
||||||
|
|
||||||
|
# == Constants
|
||||||
|
|
||||||
|
# Maximum number of characters allowed in a party
|
||||||
MAX_CHARACTERS = 5
|
MAX_CHARACTERS = 5
|
||||||
|
|
||||||
|
# Maximum number of summons allowed in a party
|
||||||
MAX_SUMMONS = 8
|
MAX_SUMMONS = 8
|
||||||
|
|
||||||
|
# Maximum number of weapons allowed in a party
|
||||||
MAX_WEAPONS = 13
|
MAX_WEAPONS = 13
|
||||||
|
|
||||||
|
# Default minimum number of characters required for filtering
|
||||||
DEFAULT_MIN_CHARACTERS = 3
|
DEFAULT_MIN_CHARACTERS = 3
|
||||||
|
|
||||||
|
# Default minimum number of summons required for filtering
|
||||||
DEFAULT_MIN_SUMMONS = 2
|
DEFAULT_MIN_SUMMONS = 2
|
||||||
|
|
||||||
|
# Default minimum number of weapons required for filtering
|
||||||
DEFAULT_MIN_WEAPONS = 5
|
DEFAULT_MIN_WEAPONS = 5
|
||||||
|
|
||||||
|
# Default maximum clear time in seconds
|
||||||
DEFAULT_MAX_CLEAR_TIME = 5400
|
DEFAULT_MAX_CLEAR_TIME = 5400
|
||||||
|
|
||||||
|
# == Primary CRUD Actions
|
||||||
|
|
||||||
|
# Creates a new party with optional user association
|
||||||
|
# @return [void]
|
||||||
def create
|
def create
|
||||||
party = Party.new
|
party = Party.new
|
||||||
party.user = current_user if current_user
|
party.user = current_user if current_user
|
||||||
|
|
@ -36,6 +55,8 @@ module Api
|
||||||
render_validation_error_response(@party)
|
render_validation_error_response(@party)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Shows a specific party if the user has permission to view it
|
||||||
|
# @return [void]
|
||||||
def show
|
def show
|
||||||
# If a party is private, check that the user is the owner or an admin
|
# If a party is private, check that the user is the owner or an admin
|
||||||
if (@party.private? && !current_user) || (@party.private? && not_owner && !admin_mode)
|
if (@party.private? && !current_user) || (@party.private? && not_owner && !admin_mode)
|
||||||
|
|
@ -47,6 +68,8 @@ module Api
|
||||||
render_not_found_response('project')
|
render_not_found_response('project')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Updates an existing party's attributes
|
||||||
|
# @return [void]
|
||||||
def update
|
def update
|
||||||
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
|
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
|
||||||
|
|
||||||
|
|
@ -62,10 +85,16 @@ module Api
|
||||||
render_validation_error_response(@party)
|
render_validation_error_response(@party)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Deletes a party if the user has permission
|
||||||
|
# @return [void]
|
||||||
def destroy
|
def destroy
|
||||||
return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy
|
return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Extended Party Actions
|
||||||
|
|
||||||
|
# Creates a copy of an existing party with attribution
|
||||||
|
# @return [void]
|
||||||
def remix
|
def remix
|
||||||
new_party = @party.amoeba_dup
|
new_party = @party.amoeba_dup
|
||||||
new_party.attributes = {
|
new_party.attributes = {
|
||||||
|
|
@ -78,6 +107,8 @@ module Api
|
||||||
new_party.local_id = party_params[:local_id] unless party_params.nil?
|
new_party.local_id = party_params[:local_id] unless party_params.nil?
|
||||||
|
|
||||||
if new_party.save
|
if new_party.save
|
||||||
|
# Remixed parties should have content, so generate preview
|
||||||
|
new_party.schedule_preview_generation
|
||||||
render json: PartyBlueprint.render(new_party, view: :created, root: :party),
|
render json: PartyBlueprint.render(new_party, view: :created, root: :party),
|
||||||
status: :created
|
status: :created
|
||||||
else
|
else
|
||||||
|
|
@ -85,6 +116,8 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Lists parties based on various filter criteria
|
||||||
|
# @return [void]
|
||||||
def index
|
def index
|
||||||
conditions = build_filters
|
conditions = build_filters
|
||||||
|
|
||||||
|
|
@ -116,6 +149,10 @@ module Api
|
||||||
render_party_json(@parties, count, total_pages)
|
render_party_json(@parties, count, total_pages)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Preview Management
|
||||||
|
|
||||||
|
# Serves the party's preview image
|
||||||
|
# @return [void]
|
||||||
def preview
|
def preview
|
||||||
coordinator = PreviewService::Coordinator.new(@party)
|
coordinator = PreviewService::Coordinator.new(@party)
|
||||||
|
|
||||||
|
|
@ -173,12 +210,18 @@ module Api
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# == Authorization Helpers
|
||||||
|
|
||||||
|
# Checks if the current user is authorized to modify the party
|
||||||
|
# @return [void]
|
||||||
def authorize
|
def authorize
|
||||||
return unless not_owner && !admin_mode
|
return unless not_owner && !admin_mode
|
||||||
|
|
||||||
render_unauthorized_response
|
render_unauthorized_response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Determines if the current user is not the owner of the party
|
||||||
|
# @return [Boolean]
|
||||||
def not_owner
|
def not_owner
|
||||||
if @party.user
|
if @party.user
|
||||||
# party has a user and current_user does not match
|
# party has a user and current_user does not match
|
||||||
|
|
@ -220,28 +263,52 @@ module Api
|
||||||
}.delete_if { |_k, v| v.nil? }
|
}.delete_if { |_k, v| v.nil? }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Parameter Processing Helpers
|
||||||
|
|
||||||
|
# Converts start time parameter for filtering
|
||||||
|
# @param recency [String, nil] time period in seconds
|
||||||
|
# @return [DateTime, nil] calculated start time
|
||||||
def build_start_time(recency)
|
def build_start_time(recency)
|
||||||
return unless recency.present?
|
return unless recency.present?
|
||||||
|
|
||||||
(DateTime.current - recency.to_i.seconds).to_datetime.beginning_of_day
|
(DateTime.current - recency.to_i.seconds).to_datetime.beginning_of_day
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Builds count parameter with default fallback
|
||||||
|
# @param value [String, nil] count value
|
||||||
|
# @param default [Integer] default value
|
||||||
|
# @return [Integer] processed count
|
||||||
def build_count(value, default)
|
def build_count(value, default)
|
||||||
value.blank? ? default : value.to_i
|
value.blank? ? default : value.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Processes maximum clear time parameter
|
||||||
|
# @param value [String, nil] clear time value in seconds
|
||||||
|
# @return [Integer] processed maximum clear time
|
||||||
def build_max_clear_time(value)
|
def build_max_clear_time(value)
|
||||||
value.blank? ? DEFAULT_MAX_CLEAR_TIME : value.to_i
|
value.blank? ? DEFAULT_MAX_CLEAR_TIME : value.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Processes element parameter
|
||||||
|
# @param element [String, nil] element identifier
|
||||||
|
# @return [Integer, nil] processed element value
|
||||||
def build_element(element)
|
def build_element(element)
|
||||||
element.to_i unless element.blank?
|
element.to_i unless element.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Processes boolean option parameters
|
||||||
|
# @param value [String, nil] option value
|
||||||
|
# @return [Integer, nil] processed option value
|
||||||
def build_option(value)
|
def build_option(value)
|
||||||
value.to_i unless value.blank? || value.to_i == -1
|
value.to_i unless value.blank? || value.to_i == -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Query Building Helpers
|
||||||
|
|
||||||
|
# Constructs the main query for party filtering
|
||||||
|
# @param conditions [Hash] filter conditions
|
||||||
|
# @param favorites [Boolean] whether to include favorites
|
||||||
|
# @return [ActiveRecord::Relation] constructed query
|
||||||
def build_query(conditions, favorites: false)
|
def build_query(conditions, favorites: false)
|
||||||
query = Party.distinct
|
query = Party.distinct
|
||||||
.joins(weapons: [:object], summons: [:object], characters: [:object])
|
.joins(weapons: [:object], summons: [:object], characters: [:object])
|
||||||
|
|
@ -265,6 +332,10 @@ module Api
|
||||||
"(\"#{id_to_table(id)}\".\"granblue_id\" != '#{id}')"
|
"(\"#{id_to_table(id)}\".\"granblue_id\" != '#{id}')"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Applies the include conditions to query
|
||||||
|
# @param query [ActiveRecord::Relation] base query
|
||||||
|
# @param includes [String] comma-separated list of IDs to include
|
||||||
|
# @return [ActiveRecord::Relation] modified query
|
||||||
def apply_includes(query, includes)
|
def apply_includes(query, includes)
|
||||||
included = includes.split(',')
|
included = includes.split(',')
|
||||||
includes_condition = included.map { |id| includes(id) }.join(' AND ')
|
includes_condition = included.map { |id| includes(id) }.join(' AND ')
|
||||||
|
|
@ -275,12 +346,21 @@ module Api
|
||||||
characters_subquery = excluded_characters.select(1).arel
|
characters_subquery = excluded_characters.select(1).arel
|
||||||
summons_subquery = excluded_summons.select(1).arel
|
summons_subquery = excluded_summons.select(1).arel
|
||||||
weapons_subquery = excluded_weapons.select(1).arel
|
weapons_subquery = excluded_weapons.select(1).arel
|
||||||
|
# Applies the exclude conditions to query
|
||||||
|
# @param query [ActiveRecord::Relation] base query
|
||||||
|
# @param excludes [String] comma-separated list of IDs to exclude
|
||||||
|
# @return [ActiveRecord::Relation] modified query
|
||||||
|
def apply_excludes(query)
|
||||||
|
|
||||||
query.where(characters_subquery.exists.not)
|
query.where(characters_subquery.exists.not)
|
||||||
.where(weapons_subquery.exists.not)
|
.where(weapons_subquery.exists.not)
|
||||||
.where(summons_subquery.exists.not)
|
.where(summons_subquery.exists.not)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Query Filtering Helpers
|
||||||
|
|
||||||
|
# Generates subquery for excluded characters
|
||||||
|
# @return [ActiveRecord::Relation, nil] exclusion query
|
||||||
def excluded_characters
|
def excluded_characters
|
||||||
return unless params[:excludes]
|
return unless params[:excludes]
|
||||||
|
|
||||||
|
|
@ -308,16 +388,27 @@ module Api
|
||||||
.where('grid_weapons.party_id = parties.id')
|
.where('grid_weapons.party_id = parties.id')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Query Processing
|
||||||
|
|
||||||
|
# Fetches and processes parties query with pagination
|
||||||
|
# @param query [ActiveRecord::Relation] base query
|
||||||
|
# @return [ActiveRecord::Relation] processed and paginated parties
|
||||||
def fetch_parties(query)
|
def fetch_parties(query)
|
||||||
query.order(created_at: :desc)
|
query.order(created_at: :desc)
|
||||||
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
|
||||||
.each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false }
|
.each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Calculates total count for pagination
|
||||||
|
# @param query [ActiveRecord::Relation] current query
|
||||||
|
# @return [Integer] total count
|
||||||
def calculate_count(query)
|
def calculate_count(query)
|
||||||
query.count.values.sum
|
query.count.values.sum
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Calculates total pages for pagination
|
||||||
|
# @param count [Integer] total record count
|
||||||
|
# @return [Integer] total pages
|
||||||
def calculate_total_pages(count)
|
def calculate_total_pages(count)
|
||||||
count.to_f / COLLECTION_PER_PAGE > 1 ? (count.to_f / COLLECTION_PER_PAGE).ceil : 1
|
count.to_f / COLLECTION_PER_PAGE > 1 ? (count.to_f / COLLECTION_PER_PAGE).ceil : 1
|
||||||
end
|
end
|
||||||
|
|
@ -391,6 +482,9 @@ module Api
|
||||||
table
|
table
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Generates name for remixed party
|
||||||
|
# @param name [String] original party name
|
||||||
|
# @return [String] generated remix name
|
||||||
def remixed_name(name)
|
def remixed_name(name)
|
||||||
blanked_name = {
|
blanked_name = {
|
||||||
en: name.blank? ? 'Untitled team' : name,
|
en: name.blank? ? 'Untitled team' : name,
|
||||||
|
|
@ -409,6 +503,10 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Party Loading
|
||||||
|
|
||||||
|
# Loads party by shortcode for routes using :id
|
||||||
|
# @return [void]
|
||||||
def set_from_slug
|
def set_from_slug
|
||||||
@party = Party.where('shortcode = ?', params[:id]).first
|
@party = Party.where('shortcode = ?', params[:id]).first
|
||||||
if @party
|
if @party
|
||||||
|
|
@ -418,10 +516,16 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Loads party by ID for update/destroy actions
|
||||||
|
# @return [void]
|
||||||
def set
|
def set
|
||||||
@party = Party.where('id = ?', params[:id]).first
|
@party = Party.where('id = ?', params[:id]).first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Parameter Sanitization
|
||||||
|
|
||||||
|
# Sanitizes and permits party parameters
|
||||||
|
# @return [Hash, nil] permitted parameters
|
||||||
def party_params
|
def party_params
|
||||||
return unless params[:party].present?
|
return unless params[:party].present?
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue