Commit d6f2faeb0a3891181fbcade42dc1ec5f3f656f39

Authored by Robert Lail
Committed by Nathan Broadbent
1 parent e4c691d2
Exists in master and in 1 other branch production

validate Problem#last_notice_at; ensure that it isn't nil

resolves the apparent sorting fail on problems by last notice timestamp
app/helpers/errs_helper.rb
1 module ErrsHelper 1 module ErrsHelper
2 - def last_notice_at(problem)  
3 - problem.last_notice_at || problem.created_at  
4 - end  
5 -  
6 def err_confirm 2 def err_confirm
7 Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?' 3 Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?'
8 end 4 end
app/models/problem.rb
@@ -6,8 +6,8 @@ class Problem @@ -6,8 +6,8 @@ class Problem
6 include Mongoid::Document 6 include Mongoid::Document
7 include Mongoid::Timestamps 7 include Mongoid::Timestamps
8 8
9 - field :last_notice_at, :type => DateTime  
10 - field :first_notice_at, :type => DateTime 9 + field :last_notice_at, :type => DateTime, :default => Proc.new { Time.now }
  10 + field :first_notice_at, :type => DateTime, :default => Proc.new { Time.now }
11 field :last_deploy_at, :type => Time 11 field :last_deploy_at, :type => Time
12 field :resolved, :type => Boolean, :default => false 12 field :resolved, :type => Boolean, :default => false
13 field :resolved_at, :type => Time 13 field :resolved_at, :type => Time
@@ -45,6 +45,8 @@ class Problem @@ -45,6 +45,8 @@ class Problem
45 scope :unresolved, where(:resolved => false) 45 scope :unresolved, where(:resolved => false)
46 scope :ordered, order_by(:last_notice_at.desc) 46 scope :ordered, order_by(:last_notice_at.desc)
47 scope :for_apps, lambda {|apps| where(:app_id.in => apps.all.map(&:id))} 47 scope :for_apps, lambda {|apps| where(:app_id.in => apps.all.map(&:id))}
  48 +
  49 + validates_presence_of :last_notice_at, :first_notice_at
48 50
49 51
50 def self.in_env(env) 52 def self.in_env(env)
@@ -132,17 +134,22 @@ class Problem @@ -132,17 +134,22 @@ class Problem
132 end 134 end
133 135
134 def cache_notice_attributes(notice=nil) 136 def cache_notice_attributes(notice=nil)
135 - notice ||= notices.first  
136 - attrs = {:last_notice_at => notices.order_by([:created_at, :asc]).last.try(:created_at), :first_notice_at => notices.order_by([:created_at, :asc]).first.try(:created_at)} 137 + first_notice = notices.order_by([:created_at, :asc]).first
  138 + last_notice = notices.order_by([:created_at, :asc]).last
  139 + notice ||= first_notice
  140 +
  141 + attrs = {}
  142 + attrs[:first_notice_at] = first_notice.created_at if first_notice
  143 + attrs[:last_notice_at] = last_notice.created_at if last_notice
137 attrs.merge!( 144 attrs.merge!(
138 - :message => notice.message, 145 + :message => notice.message,
139 :environment => notice.environment_name, 146 :environment => notice.environment_name,
140 :error_class => notice.error_class, 147 :error_class => notice.error_class,
141 - :where => notice.where, 148 + :where => notice.where,
142 :messages => attribute_count_increase(:messages, notice.message), 149 :messages => attribute_count_increase(:messages, notice.message),
143 :hosts => attribute_count_increase(:hosts, notice.host), 150 :hosts => attribute_count_increase(:hosts, notice.host),
144 :user_agents => attribute_count_increase(:user_agents, notice.user_agent_string) 151 :user_agents => attribute_count_increase(:user_agents, notice.user_agent_string)
145 - ) if notice 152 + ) if notice
146 update_attributes!(attrs) 153 update_attributes!(attrs)
147 end 154 end
148 155
app/views/errs/_table.html.haml
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 - if comment.user 33 - if comment.user
34 %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":" 34 %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":"
35 %em= truncate(comment.body, :length => 100, :separator => ' ') 35 %em= truncate(comment.body, :length => 100, :separator => ' ')
36 - %td.latest #{time_ago_in_words(last_notice_at problem)} ago 36 + %td.latest #{time_ago_in_words(problem.last_notice_at)} ago
37 %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a' 37 %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a'
38 %td.count= link_to problem.notices_count, app_err_path(problem.app, problem) 38 %td.count= link_to problem.notices_count, app_err_path(problem.app, problem)
39 - if any_issue_links 39 - if any_issue_links
app/views/errs/show.html.haml
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 %strong Environment: 10 %strong Environment:
11 = @problem.environment 11 = @problem.environment
12 %strong Last Notice: 12 %strong Last Notice:
13 - = last_notice_at(@problem).to_s(:precise) 13 + = @problem.last_notice_at.to_s(:precise)
14 - content_for :action_bar do 14 - content_for :action_bar do
15 - if @problem.unresolved? 15 - if @problem.unresolved?
16 %span= link_to 'resolve', resolve_app_err_path(@app, @problem), :method => :put, :data => { :confirm => err_confirm }, :class => 'resolve' 16 %span= link_to 'resolve', resolve_app_err_path(@app, @problem), :method => :put, :data => { :confirm => err_confirm }, :class => 'resolve'
db/migrate/20120829034812_ensure_that_problems_last_notice_at_is_not_nil.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +class EnsureThatProblemsLastNoticeAtIsNotNil < Mongoid::Migration
  2 + def self.up
  3 + Problem.where("$or" => [{:last_notice_at => nil}, {:first_notice_at => nil}]).each do |problem|
  4 + first_notice = problem.notices.order_by([:created_at, :asc]).first
  5 +
  6 + # Destroy problems with no notices
  7 + if first_notice.nil?
  8 + problem.destroy
  9 + next
  10 + end
  11 +
  12 + last_notice = problem.notices.order_by([:created_at, :asc]).last
  13 +
  14 + problem.update_attributes!({
  15 + :first_notice_at => first_notice.created_at,
  16 + :last_notice_at => last_notice.created_at
  17 + })
  18 + end
  19 + end
  20 +
  21 + def self.down
  22 + end
  23 +end
spec/models/problem_spec.rb
@@ -24,14 +24,13 @@ describe Problem do @@ -24,14 +24,13 @@ describe Problem do
24 end 24 end
25 end 25 end
26 end 26 end
  27 +
27 context '#last_notice_at' do 28 context '#last_notice_at' do
28 it "returns the created_at timestamp of the latest notice" do 29 it "returns the created_at timestamp of the latest notice" do
29 err = Fabricate(:err) 30 err = Fabricate(:err)
30 problem = err.problem 31 problem = err.problem
31 problem.should_not be_nil 32 problem.should_not be_nil
32 33
33 - problem.last_notice_at.should be_nil  
34 -  
35 notice1 = Fabricate(:notice, :err => err) 34 notice1 = Fabricate(:notice, :err => err)
36 problem.last_notice_at.should == notice1.created_at 35 problem.last_notice_at.should == notice1.created_at
37 36
@@ -46,8 +45,6 @@ describe Problem do @@ -46,8 +45,6 @@ describe Problem do
46 problem = err.problem 45 problem = err.problem
47 problem.should_not be_nil 46 problem.should_not be_nil
48 47
49 - problem.first_notice_at.should be_nil  
50 -  
51 notice1 = Fabricate(:notice, :err => err) 48 notice1 = Fabricate(:notice, :err => err)
52 problem.first_notice_at.should == notice1.created_at 49 problem.first_notice_at.should == notice1.created_at
53 50