Implement PartyQueryBuilder in controllers

This commit is contained in:
Justin Edmund 2025-02-12 23:12:13 -08:00
parent 924767457e
commit 412a99a6c7
2 changed files with 67 additions and 28 deletions

View file

@ -105,16 +105,20 @@ module Api
# Lists parties based on query parameters.
def index
query = build_parties_query
query = build_filtered_query(build_common_base_query)
@parties = query.paginate(page: params[:page], per_page: COLLECTION_PER_PAGE)
render_paginated_parties(@parties)
end
# Lists parties favorited by the current user.
# GET /api/v1/parties/favorites
def favorites
raise Api::V1::UnauthorizedError unless current_user
ap "Total favorites in DB: #{Favorite.count}"
query = build_parties_query(favorites: true)
base_query = build_common_base_query
.joins(:favorites)
.where(favorites: { user_id: current_user.id })
.distinct
query = build_filtered_query(base_query)
@parties = query.paginate(page: params[:page], per_page: COLLECTION_PER_PAGE)
render_paginated_parties(@parties)
end

View file

@ -55,34 +55,39 @@ module Api
if @user.nil?
render_not_found_response('user')
else
conditions = build_conditions
conditions[:user_id] = @user.id
favorites_query = "EXISTS (SELECT 1 FROM favorites WHERE favorites.party_id = parties.id AND favorites.user_id = #{current_user&.id || 'NULL'}) AS is_favorited"
parties = Party.where(conditions)
.where(name_quality)
.where(user_quality)
.where(original)
.where(privacy)
.includes(:favorites)
.select(Party.arel_table[Arel.star])
.select(
Arel.sql(favorites_query)
)
.order(created_at: :desc)
.paginate(page: request.params[:page], per_page: COLLECTION_PER_PAGE)
count = Party.where(conditions).count
base_query = Party.includes(
{ raid: :group },
:job,
:user,
:skill0,
:skill1,
:skill2,
:skill3,
:guidebook1,
:guidebook2,
:guidebook3,
{ characters: :character },
{ weapons: :weapon },
{ summons: :summon }
)
# Restrict to parties belonging to the profile owner
base_query = base_query.where(user_id: @user.id)
skip_privacy = (current_user&.id == @user.id)
query = PartyQueryBuilder.new(
base_query,
params: params,
current_user: current_user,
options: { skip_privacy: skip_privacy }
).build
parties = query.paginate(page: params[:page], per_page: PartyConstants::COLLECTION_PER_PAGE)
count = query.count
render json: UserBlueprint.render(@user,
view: :profile,
root: 'profile',
parties: parties,
meta: {
count: count,
total_pages: count.to_f / COLLECTION_PER_PAGE > 1 ? (count.to_f / COLLECTION_PER_PAGE).ceil : 1,
per_page: COLLECTION_PER_PAGE
})
meta: { count: count, total_pages: (count.to_f / PartyConstants::COLLECTION_PER_PAGE).ceil, per_page: PartyConstants::COLLECTION_PER_PAGE },
current_user: current_user
)
end
end
@ -98,6 +103,36 @@ module Api
private
def build_profile_query(profile_user)
query = Party.includes(
{ raid: :group },
:job,
:user,
:skill0,
:skill1,
:skill2,
:skill3,
:guidebook1,
:guidebook2,
:guidebook3,
{ characters: :character },
{ weapons: :weapon },
{ summons: :summon }
)
# Restrict to parties belonging to the profiles owner.
query = query.where(user_id: profile_user.id)
# Then apply the additional filters that we normally use:
query = query.where(name_quality)
.where(user_quality)
.where(original)
.where(privacy)
# And if there are any request-supplied filters, includes, or excludes:
query = apply_filters(query) if params[:filters].present?
query = apply_includes(query, params[:includes]) if params[:includes].present?
query = apply_excludes(query, params[:excludes]) if params[:excludes].present?
query.order(created_at: :desc)
end
def build_conditions
params = request.params