Update parties_controller.rb

Updates apply_includes and apply_excludes, along with modifying id_to_table and build_query
This commit is contained in:
Justin Edmund 2025-02-07 03:18:30 -08:00
parent fde9b08edc
commit 38f6c043bf

View file

@ -340,7 +340,12 @@ module Api
# @return [ActiveRecord::Relation] constructed query # @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 vs includes? -> reduces n+1s
.preload(
weapons: { object: %i[name_en name_jp granblue_id element] },
summons: { object: %i[name_en name_jp granblue_id element] },
characters: { object: %i[name_en name_jp granblue_id element] }
)
.group('parties.id') .group('parties.id')
.where(conditions) .where(conditions)
.where(privacy(favorites: favorites)) .where(privacy(favorites: favorites))
@ -348,38 +353,61 @@ module Api
.where(user_quality) .where(user_quality)
.where(original) .where(original)
query = query.joins(:favorites) if favorites query = query.includes(:favorites) if favorites
query query
end end
def includes(id)
"(\"#{id_to_table(id)}\".\"granblue_id\" = '#{id}')"
end
def excludes(id)
"(\"#{id_to_table(id)}\".\"granblue_id\" != '#{id}')"
end
# Applies the include conditions to query # Applies the include conditions to query
# @param query [ActiveRecord::Relation] base query # @param query [ActiveRecord::Relation] base query
# @param includes [String] comma-separated list of IDs to include # @param includes [String] comma-separated list of IDs to include
# @return [ActiveRecord::Relation] modified query # @return [ActiveRecord::Relation] modified query
def apply_includes(query, includes) def apply_includes(query, includes)
included = includes.split(',') return query unless includes.present?
includes_condition = included.map { |id| includes(id) }.join(' AND ')
query.where(includes_condition) includes.split(',').each do |id|
grid_table, object_table = grid_table_and_object_table(id)
next unless grid_table && object_table
# Build a subquery that joins the grid table to the object table.
condition = <<-SQL.squish
EXISTS (
SELECT 1
FROM #{grid_table}
JOIN #{object_table} ON #{grid_table}.#{object_table.singularize}_id = #{object_table}.id
WHERE #{object_table}.granblue_id = ?
AND #{grid_table}.party_id = parties.id
)
SQL
query = query.where(condition, id)
end
query
end end
def apply_excludes(query, _excludes)
characters_subquery = excluded_characters.select(1).arel
summons_subquery = excluded_summons.select(1).arel
weapons_subquery = excluded_weapons.select(1).arel
# Applies the exclude conditions to query # Applies the exclude conditions to query
# @param query [ActiveRecord::Relation] base query # @param query [ActiveRecord::Relation] base query
# @param excludes [String] comma-separated list of IDs to exclude
# @return [ActiveRecord::Relation] modified query # @return [ActiveRecord::Relation] modified query
def apply_excludes(query) def apply_excludes(query, excludes)
return query unless excludes.present?
excludes.split(',').each do |id|
grid_table, object_table = grid_table_and_object_table(id)
next unless grid_table && object_table
condition = <<-SQL.squish
NOT EXISTS (
SELECT 1
FROM #{grid_table}
JOIN #{object_table} ON #{grid_table}.#{object_table.singularize}_id = #{object_table}.id
WHERE #{object_table}.granblue_id = ?
AND #{grid_table}.party_id = parties.id
)
SQL
query = query.where(condition, id)
end
query.where(characters_subquery.exists.not) query.where(characters_subquery.exists.not)
.where(weapons_subquery.exists.not) .where(weapons_subquery.exists.not)
@ -524,17 +552,22 @@ module Api
end end
end end
def id_to_table(id) # == Utility Methods
# Maps ID prefixes to table names
# @param id [String] item identifier
# @return [Array(String, String)] corresponding table name
def grid_table_and_object_table(id)
case id[0] case id[0]
when '3' when '3'
table = 'characters' %w[grid_characters characters]
when '2' when '2'
table = 'summons' %w[grid_summons summons]
when '1' when '1'
table = 'weapons' %w[grid_weapons weapons]
else
[nil, nil]
end end
table
end end
# Generates name for remixed party # Generates name for remixed party