Fix count filters and refactor apply_filters
This commit is contained in:
parent
82fa291398
commit
86287ec10a
2 changed files with 123 additions and 16 deletions
|
|
@ -46,15 +46,11 @@ class PartyQueryBuilder
|
||||||
# Example edge case: If the request does not specify 'characters_count',
|
# Example edge case: If the request does not specify 'characters_count',
|
||||||
# then the default (e.g. 3) will be used, with the upper bound coming from a constant.
|
# then the default (e.g. 3) will be used, with the upper bound coming from a constant.
|
||||||
def apply_filters(query)
|
def apply_filters(query)
|
||||||
conditions = build_filters
|
query = apply_base_filters(query)
|
||||||
query = query.where(conditions)
|
query = apply_name_quality_filter(query)
|
||||||
# If name_quality filtering is enabled via params, apply it.
|
query = apply_count_filters(query)
|
||||||
query = query.where(name_quality) if @params[:name_quality].present?
|
|
||||||
query.where(
|
query
|
||||||
weapons_count: build_count(@params[:weapons_count], default_weapons_count)..max_weapons,
|
|
||||||
characters_count: build_count(@params[:characters_count], default_characters_count)..max_characters,
|
|
||||||
summons_count: build_count(@params[:summons_count], default_summons_count)..max_summons
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Example callback method: if no explicit status filter is provided, we may want
|
# Example callback method: if no explicit status filter is provided, we may want
|
||||||
|
|
@ -148,6 +144,63 @@ class PartyQueryBuilder
|
||||||
query
|
query
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Applies base filtering conditions from build_filters to the query.
|
||||||
|
# @param query [ActiveRecord::QueryMethods::WhereChain] The current query.
|
||||||
|
# @return [ActiveRecord::Relation] The query with base filters applied.
|
||||||
|
def apply_base_filters(query)
|
||||||
|
query.where(build_filters)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Applies the name quality filter to the query if the parameter is present.
|
||||||
|
# @param query [ActiveRecord::QueryMethods::WhereChain] The current query.
|
||||||
|
# @return [ActiveRecord::Relation] The query with the name quality filter applied.
|
||||||
|
def apply_name_quality_filter(query)
|
||||||
|
@params[:name_quality].present? ? query.where(name_quality) : query
|
||||||
|
end
|
||||||
|
|
||||||
|
# Applies count filters to the query based on provided parameters or default options.
|
||||||
|
# If apply_defaults is set in options, default ranges are applied.
|
||||||
|
# Otherwise, count ranges are built from provided parameters.
|
||||||
|
# @param query [ | ActiveRecord::QueryMethods::WhereChain] The current query.
|
||||||
|
# @return [ActiveRecord::Relation] The query with count filters applied.
|
||||||
|
def apply_count_filters(query)
|
||||||
|
if @options[:apply_defaults]
|
||||||
|
query.where(
|
||||||
|
weapons_count: default_weapons_count..max_weapons,
|
||||||
|
characters_count: default_characters_count..max_characters,
|
||||||
|
summons_count: default_summons_count..max_summons
|
||||||
|
)
|
||||||
|
elsif count_filter_provided?
|
||||||
|
query.where(build_count_conditions)
|
||||||
|
else
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Determines if any count filter parameters have been provided.
|
||||||
|
# @return [Boolean] True if any count filters are provided, false otherwise.
|
||||||
|
def count_filter_provided?
|
||||||
|
@params.key?(:weapons_count) || @params.key?(:characters_count) || @params.key?(:summons_count)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Builds a hash of count conditions based on the count filter parameters.
|
||||||
|
# @return [Hash] A hash with keys :weapons_count, :characters_count, and :summons_count.
|
||||||
|
def build_count_conditions
|
||||||
|
{
|
||||||
|
weapons_count: build_range(@params[:weapons_count], max_weapons),
|
||||||
|
characters_count: build_range(@params[:characters_count], max_characters),
|
||||||
|
summons_count: build_range(@params[:summons_count], max_summons)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Constructs a range for a given count parameter.
|
||||||
|
# @param param_value [String, nil] The count filter parameter value.
|
||||||
|
# @param max_value [Integer] The maximum allowed value for the count.
|
||||||
|
# @return [Range] A range from the provided count (or 0 if blank) to the max_value.
|
||||||
|
def build_range(param_value, max_value)
|
||||||
|
param_value.present? ? param_value.to_i..max_value : 0..max_value
|
||||||
|
end
|
||||||
|
|
||||||
# Maps an ID’s first character to the corresponding grid table and object table names.
|
# Maps an ID’s first character to the corresponding grid table and object table names.
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
|
|
@ -170,27 +223,27 @@ class PartyQueryBuilder
|
||||||
|
|
||||||
# Default values and maximum limits for counts.
|
# Default values and maximum limits for counts.
|
||||||
def default_weapons_count
|
def default_weapons_count
|
||||||
@options[:default_weapons_count] || 5;
|
@options[:default_weapons_count] || 5
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_characters_count
|
def default_characters_count
|
||||||
@options[:default_characters_count] || 3;
|
@options[:default_characters_count] || 3
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_summons_count
|
def default_summons_count
|
||||||
@options[:default_summons_count] || 2;
|
@options[:default_summons_count] || 2
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_weapons
|
def max_weapons
|
||||||
@options[:max_weapons] || 13;
|
@options[:max_weapons] || 13
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_characters
|
def max_characters
|
||||||
@options[:max_characters] || 5;
|
@options[:max_characters] || 5
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_summons
|
def max_summons
|
||||||
@options[:max_summons] || 8;
|
@options[:max_summons] || 8
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stub method for name quality filtering.
|
# Stub method for name quality filtering.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ RSpec.describe PartyQueryBuilder, type: :model do
|
||||||
it 'returns an ActiveRecord::Relation with filters applied' do
|
it 'returns an ActiveRecord::Relation with filters applied' do
|
||||||
query = subject.build
|
query = subject.build
|
||||||
sql = query.to_sql
|
sql = query.to_sql
|
||||||
|
|
||||||
# Expect the element filter to be applied (converted to integer)
|
# Expect the element filter to be applied (converted to integer)
|
||||||
expect(sql).to include('"parties"."element" = 3')
|
expect(sql).to include('"parties"."element" = 3')
|
||||||
# Expect the raid filter to be applied
|
# Expect the raid filter to be applied
|
||||||
|
|
@ -192,6 +191,61 @@ RSpec.describe PartyQueryBuilder, type: :model do
|
||||||
expect(sql).not_to include('NOT EXISTS (')
|
expect(sql).not_to include('NOT EXISTS (')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when apply_defaults option is true' do
|
||||||
|
subject do
|
||||||
|
described_class.new(
|
||||||
|
base_query,
|
||||||
|
params: params,
|
||||||
|
current_user: current_user,
|
||||||
|
options: { apply_defaults: true }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds count filters to the query' do
|
||||||
|
query = subject.build
|
||||||
|
sql = query.to_sql
|
||||||
|
expect(sql).to include('"weapons_count" BETWEEN')
|
||||||
|
expect(sql).to include('"characters_count" BETWEEN')
|
||||||
|
expect(sql).to include('"summons_count" BETWEEN')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when apply_defaults option is false (or not provided)' do
|
||||||
|
let(:blanked_params) do
|
||||||
|
{
|
||||||
|
element: '3',
|
||||||
|
raid: '123e4567-e89b-12d3-a456-426614174000',
|
||||||
|
recency: '3600',
|
||||||
|
full_auto: '1',
|
||||||
|
auto_guard: '0',
|
||||||
|
charge_attack: '1',
|
||||||
|
weapons_count: '', # blank => should use default
|
||||||
|
characters_count: '',
|
||||||
|
summons_count: '',
|
||||||
|
includes: '300001,200002',
|
||||||
|
excludes: '100003',
|
||||||
|
name_quality: '1' # dummy flag for testing name_quality clause
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
subject do
|
||||||
|
described_class.new(
|
||||||
|
base_query,
|
||||||
|
params: blanked_params,
|
||||||
|
current_user: current_user,
|
||||||
|
options: {}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not add count filters to the query' do
|
||||||
|
query = subject.build
|
||||||
|
sql = query.to_sql
|
||||||
|
expect(sql).not_to include('weapons_count BETWEEN')
|
||||||
|
expect(sql).not_to include('characters_count BETWEEN')
|
||||||
|
expect(sql).not_to include('summons_count BETWEEN')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue