Patch #43933 ยป optimize-load_visible_total_spent_hours.patch
| app/models/issue.rb | ||
|---|---|---|
| 1243 | 1243 | |
| 1244 | 1244 |
# Preloads visible total spent time for a collection of issues |
| 1245 | 1245 |
def self.load_visible_total_spent_hours(issues, user=User.current) |
| 1246 |
if issues.any? |
|
| 1246 |
return if issues.empty? |
|
| 1247 | ||
| 1248 |
# For leaf issues, `total_spent_hours` equals `spent_hours`, so reuse |
|
| 1249 |
# the preloaded visible spent hours to avoid the expensive query below. |
|
| 1250 |
optimizable_leaf_issues, remaining_issues = issues.partition do |issue| |
|
| 1251 |
issue.leaf? && |
|
| 1252 |
issue.instance_variable_defined?(:@spent_hours) && |
|
| 1253 |
!issue.instance_variable_get(:@spent_hours).nil? |
|
| 1254 |
end |
|
| 1255 | ||
| 1256 |
optimizable_leaf_issues.each do |issue| |
|
| 1257 |
issue.instance_variable_set :@total_spent_hours, issue.spent_hours |
|
| 1258 |
end |
|
| 1259 | ||
| 1260 |
if remaining_issues.any? |
|
| 1247 | 1261 |
hours_by_issue_id = TimeEntry.visible(user).joins(:issue). |
| 1248 | 1262 |
joins("JOIN #{Issue.table_name} parent ON parent.root_id = #{Issue.table_name}.root_id" +
|
| 1249 | 1263 |
" AND parent.lft <= #{Issue.table_name}.lft AND parent.rgt >= #{Issue.table_name}.rgt").
|
| 1250 |
where("parent.id IN (?)", issues.map(&:id)).group("parent.id").sum(:hours)
|
|
| 1251 |
issues.each do |issue| |
|
| 1264 |
where("parent.id IN (?)", remaining_issues.map(&:id)).group("parent.id").sum(:hours)
|
|
| 1265 |
remaining_issues.each do |issue|
|
|
| 1252 | 1266 |
issue.instance_variable_set :@total_spent_hours, (hours_by_issue_id[issue.id] || 0.0) |
| 1253 | 1267 |
end |
| 1254 | 1268 |
end |
| test/unit/issue_test.rb | ||
|---|---|---|
| 222 | 222 |
assert_include 'Parent task is invalid', issue.errors.full_messages |
| 223 | 223 |
end |
| 224 | 224 | |
| 225 |
def test_load_visible_total_spent_hours_should_use_loaded_spent_hours_for_leaf_issues |
|
| 226 |
issue = Issue.find(1) |
|
| 227 |
assert issue.leaf? |
|
| 228 |
# preloaded visible spent hours value is stored in @spent_hours instance variable |
|
| 229 |
issue.instance_variable_set(:@spent_hours, 3.5) |
|
| 230 |
TimeEntry.expects(:visible).never |
|
| 231 | ||
| 232 |
Issue.load_visible_total_spent_hours([issue]) |
|
| 233 | ||
| 234 |
assert_equal 3.5, issue.instance_variable_get(:@total_spent_hours) |
|
| 235 |
end |
|
| 236 | ||
| 225 | 237 |
def assert_visibility_match(user, issues) |
| 226 | 238 |
assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
|
| 227 | 239 |
end |