Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize db queries on the front page #420

Merged
merged 7 commits into from
Jun 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ gem 'cancancan'
gem 'doorkeeper'

# db
gem 'active_record_union'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow nice, hadn't heard of this before. This seems sick, and can definitely clean up a lot.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the other spot I noticed that had something similar was the game search, where we find game IDs from both games and game aliases. It seemed useful for the long term for some more advanced things.

gem 'activerecord-import'
gem 'arel'
gem 'aws-sdk-rails'
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ GEM
activemodel (>= 4.1, < 6)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
active_record_union (1.3.0)
activerecord (>= 4.0)
activejob (5.2.0)
activesupport (= 5.2.0)
globalid (>= 0.3.6)
Expand Down Expand Up @@ -436,6 +438,7 @@ PLATFORMS

DEPENDENCIES
active_model_serializers
active_record_union
activerecord-import
administrate
api-pagination (= 4.7)
Expand Down
2 changes: 1 addition & 1 deletion app/models/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Game < ApplicationRecord

validates :name, presence: true

has_many :categories
has_many :categories, dependent: :destroy
has_many :runs, through: :categories
has_many :users, -> { distinct }, through: :runs
has_many :runners, -> { distinct }, through: :runs, class_name: 'User'
Expand Down
7 changes: 3 additions & 4 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def self.search(term)

# avatar returns the user's avatar, or a default avatar if the user has not set one. It cannot return nil.
def avatar
return "https://splits.io/logo.svg" if read_attribute(:avatar).nil?
return 'https://splits.io/logo.svg' if read_attribute(:avatar).nil?

URI.parse(read_attribute(:avatar) || '').tap do |uri|
uri.scheme = 'https'
Expand All @@ -63,9 +63,8 @@ def previous_upload_for(category)
end

def pbs
runs.where(
id: categories.map { |category| pb_for(category).id10 } | runs.where(category: nil).pluck(:id)
)
runs.where.not(category: nil).select('DISTINCT ON (category_id) *').order('category_id, realtime_duration_ms ASC')
.union_all(runs.by_category(nil))
end

def runs?(category)
Expand Down
4 changes: 2 additions & 2 deletions app/views/runs/index.slim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
span Splits I/O
- else
h2 Splits I/O
- if logged_in? && current_user.runs.present?
- if logged_in? && current_user.runs.any?
h5 Want some jelly with these PBs?
- else
h5
Expand All @@ -20,7 +20,7 @@ article
.row
.col-lg-12
- if logged_in?
- if current_user.runs.present?
- if current_user.runs.any?
.card.shadow
= render partial: 'shared/run_table', locals: { \
runs: current_user.pbs, \
Expand Down
8 changes: 5 additions & 3 deletions app/views/shared/_follows.slim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
h4 Recent PBs By People You Follow
.card.col-md-6.p-0
.list-group
- Run.includes(:game, :category, :user).where(user: current_user.twitch_followed_users).where.not(games: {name: [nil, ""]}).order('runs.created_at DESC').limit(10).each do |run|
- followed_runs = Run.includes(:game, :category, :user).where(user: current_user.twitch_followed_users).where.not(games: {name: [nil, ""]}).order('runs.created_at DESC').limit(10)
- user_runs = current_user.pbs.where(category_id: followed_runs.map(&:category_id))
- followed_runs.each do |run|
= link_to(run, class: 'list-group-item list-group-item-action flex-column align-items-start')
.media
= image_tag(run.user.avatar, size: '70x70', class: 'mr-3')
Expand All @@ -14,8 +16,8 @@
= "#{run.game} #{run.category}"
div
= format_ms(run.duration_ms(Run::REAL))
- if current_user.runs?(run.category)
- user_pb = current_user.pb_for(run.category)
- user_pb = user_runs.detect { |r| r.category_id == run.category_id }
- if user_pb.present?
= " ("
= pretty_difference(user_pb.duration_ms(Run::REAL), run.duration_ms(Run::REAL))
= ")"
12 changes: 6 additions & 6 deletions app/views/shared/_run_table.slim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
- description ||= nil
- cols ||= [:runner, :time, :name, :rival, :uploaded]
- runs = order_runs(runs).page(params[:page])
- if runs.empty?
- if runs.blank?
center
i No runs matched!
- else
Expand All @@ -24,7 +24,7 @@
- if cols.include?(:uploaded)
th.align-right = th_sorter('Uploaded', 'created_at')
tbody
- runs.includes(:user).each do |run|
- runs.includes(:user, :game, :category).each do |run|
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When ctrl+f'ing the project, every single call to the partial had the name col, so it seemed fine to just include these always.

tr id="run_#{run.id36}"
- if cols.include?(:owner_controls)
td.align-right
Expand All @@ -43,13 +43,13 @@
- if cols.include?(:rival)
td.align-right
small
- rival = run.user.rival_for(run.category)
- if rival.present? && rival.runs?(run.category)
- rival_run = rival.pb_for(run.category)
- rivalry = run.user.rivalries.includes(:to_user).detect { |r| r.category_id == run.category_id }
- if rivalry.present? && rivalry.to_user.pb_for(run.category).present?
- rival_run = rivalry.to_user.pb_for(run.category)
= link_to compare_path(run, rival_run), class: 'run-link stealth-link' do
= pretty_difference(run.duration_ms(Run::REAL), rival_run.duration_ms(Run::REAL))
' against
= user_badge(rival)
= user_badge(rivalry.to_user)
- elsif run.category.present?
= link_to new_rivalry_path(category: run.category)
.text-success = icon('fas', 'plus')
Expand Down