Skip to content

Commit

Permalink
Refactor PastIteration mounting process
Browse files Browse the repository at this point in the history
It was full of N+1 queries, and getting the things very slow
  • Loading branch information
andrerpbts committed Sep 8, 2018
1 parent d58c745 commit 2f2a0a6
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 48 deletions.
24 changes: 12 additions & 12 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ gem 'jquery-atwho-rails'
gem 'jquery-ui-rails'
gem 'kaminari'
gem 'material_icons'
gem 'newrelic_rpm'
gem 'pg'
gem 'pg_search'
gem 'platform-api'
Expand All @@ -65,35 +66,34 @@ end
group :production do
gem 'kgio'
gem 'letsencrypt-rails-heroku'
gem 'newrelic_rpm'
gem 'rack-cache'
gem 'rack-timeout'
gem 'rails_12factor'
end

group :test do
gem 'rspec-rails'
gem 'rspec-its'
gem 'rspec-activemodel-mocks'
gem 'shoulda-matchers'
gem 'capybara'
gem 'poltergeist'
gem 'capybara-screenshot'
gem 'codeclimate-test-reporter', require: nil
gem 'database_cleaner'
gem 'factory_girl_rails'
gem 'codeclimate-test-reporter', require: nil
gem 'poltergeist'
gem 'rspec-activemodel-mocks'
gem 'rspec-its'
gem 'rspec-rails'
gem 'shoulda-matchers'
gem 'simplecov'
gem 'timecop'
gem 'vcr'
gem 'webmock'
gem 'timecop'
gem 'simplecov'
end

group :development do
gem 'better_errors'
gem 'binding_of_caller'
gem 'bullet'
gem 'letter_opener'
gem 'letter_opener_web', '~> 1.2.0'
gem "better_errors"
gem "binding_of_caller"
gem "bullet"
gem 'rubocop', '0.49.1'
end

Expand Down
22 changes: 7 additions & 15 deletions app/models/iterations/past_iteration.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
module Iterations
class PastIteration
attr_reader :start_date, :end_date, :points, :iteration_number
include Virtus.model

def initialize(start_date:, end_date:, project:, iteration_number: nil)
@start_date = start_date
@end_date = end_date
@project = project
@points = points
@iteration_number = iteration_number
end
attribute :start_date, DateTime
attribute :end_date, DateTime
attribute :iteration_number, Integer
attribute :stories, Array[Story]
attribute :points, Integer

def points
@points ||= stories.sum(:estimate)
end

def stories
@stories ||= @project.stories.where(
'accepted_at >= ? AND accepted_at <= ?', @start_date, @end_date
)
@points ||= stories.to_a.map(&:estimate).compact.sum
end
end
end
38 changes: 30 additions & 8 deletions app/models/iterations/project_iterations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,49 @@ def current_iteration_start

def past_iterations
(0...length).map do |iteration_number|
start_date = start_date(iteration_number)
end_date = end_date(start_date)
PastIteration.new(start_date: start_date,
end_date: end_date,
project: @project,
iteration_number: iteration_number + 1)
start_at = start_date(iteration_number)
end_at = end_date(start_at)

PastIteration.new(
start_date: start_at,
end_date: end_at,
stories: stories_for(start_at, end_at),
iteration_number: iteration_number + 1
)
end
end

private

attr_reader :project

def stories_for(start_at, end_at)
stories.select do |story|
story.accepted_at >= start_at && story.accepted_at <= end_at
end
end

def stories
@stories ||= begin
project
.stories
.with_dependencies
.where(state: 'accepted')
.where.not(accepted_at: nil)
.order(:accepted_at)
end
end

def length
(days_since_project_start / iteration_length_in_days).floor
end

def iteration_length_in_days
@project.iteration_length * 7
project.iteration_length * 7
end

def project_start_date
@project.start_date
project.start_date
end

def start_date(iteration_number)
Expand Down
21 changes: 17 additions & 4 deletions app/operations/iteration_operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,29 @@ def initialize(start_date:, end_date:, project:)

def run
{
stories: stories
stories: past_iteration.stories
}
end

private

attr_reader :project, :start_date, :end_date

def past_iteration
Iterations::PastIteration.new(
start_date: start_date,
end_date: end_date,
stories: stories
)
end

def stories
Iterations::PastIteration.new(start_date: @start_date,
end_date: @end_date,
project: @project).stories
@stories ||= begin
project
.stories
.with_dependencies
.where('accepted_at >= ? AND accepted_at <= ?', start_date, end_date)
end
end
end
end
24 changes: 15 additions & 9 deletions app/operations/story_operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,40 @@ class Destroy < BaseOperations::Destroy; end
class DestroyAll < BaseOperations::DestroyAll; end

class ReadAll
delegate :past_iterations, :current_iteration_start, to: :iterations

def self.call(*args)
new(*args).run
end

def initialize(project:)
@story_scope = project.stories.with_dependencies
@project = project
@iterations = Iterations::ProjectIterations.new(project: project)
end

def run
{
active_stories: active_stories,
past_iterations: @iterations.past_iterations
past_iterations: past_iterations
}
end

private

attr_reader :project

def active_stories
order(@story_scope.where("state != 'accepted' OR
accepted_at >= ?", @iterations.current_iteration_start))
@active_stories ||= begin
project
.stories
.with_dependencies
.where("state != 'accepted' OR accepted_at >= ?", current_iteration_start)
.order('updated_at DESC')
.limit(ENV['STORIES_CEILING'].presence)
end
end

def order(query)
query.order('updated_at DESC').tap do |relation|
relation.limit(ENV['STORIES_CEILING']) if ENV['STORIES_CEILING']
end
def iterations
@iterations ||= Iterations::ProjectIterations.new(project: project)
end
end
end

0 comments on commit 2f2a0a6

Please sign in to comment.