add validation and updating of existing event's expires_at values

Andrew Cantino 11 lat temu
rodzic
commit
91c82741e5
2 zmienionych plików z 94 dodań i 2 usunięć
  1. 14 0
      app/models/agent.rb
  2. 80 2
      spec/models/agent_spec.rb

+ 14 - 0
app/models/agent.rb

@@ -21,6 +21,7 @@ class Agent < ActiveRecord::Base
21 21
   attr_accessible :options, :memory, :name, :type, :schedule, :source_ids, :keep_events_for
22 22
 
23 23
   validates_presence_of :name, :user
24
+  validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last)
24 25
   validate :sources_are_owned
25 26
   validate :validate_schedule
26 27
 
@@ -29,6 +30,7 @@ class Agent < ActiveRecord::Base
29 30
   before_validation :unschedule_if_cannot_schedule
30 31
   before_save :unschedule_if_cannot_schedule
31 32
   before_create :set_last_checked_event_id
33
+  after_save :possibly_update_event_expirations
32 34
 
33 35
   belongs_to :user, :inverse_of => :agents
34 36
   has_many :events, :dependent => :delete_all, :inverse_of => :agent, :order => "events.id desc"
@@ -175,6 +177,18 @@ class Agent < ActiveRecord::Base
175 177
     end
176 178
   end
177 179
 
180
+  def possibly_update_event_expirations
181
+    update_event_expirations! if keep_events_for_changed?
182
+  end
183
+
184
+  def update_event_expirations!
185
+    if keep_events_for == 0
186
+      events.update_all :expires_at => nil
187
+    else
188
+      events.update_all "expires_at = DATE_ADD(`created_at`, INTERVAL #{keep_events_for.to_i} DAY)"
189
+    end
190
+  end
191
+
178 192
   # Class Methods
179 193
   class << self
180 194
     def cannot_be_scheduled!

+ 80 - 2
spec/models/agent_spec.rb

@@ -249,7 +249,7 @@ describe Agent do
249 249
         agent.should have(0).errors_on(:base)
250 250
       end
251 251
 
252
-      it "symbolizes options before validating" do
252
+      it "makes options symbol-indifferent before validating" do
253 253
         agent = Agents::SomethingSource.new(:name => "something")
254 254
         agent.user = users(:bob)
255 255
         agent.options["bad"] = true
@@ -258,7 +258,7 @@ describe Agent do
258 258
         agent.should have(0).errors_on(:base)
259 259
       end
260 260
 
261
-      it "symbolizes memory before validating" do
261
+      it "makes memory symbol-indifferent before validating" do
262 262
         agent = Agents::SomethingSource.new(:name => "something")
263 263
         agent.user = users(:bob)
264 264
         agent.memory["bad"] = :hello
@@ -276,7 +276,85 @@ describe Agent do
276 276
         agent.user = users(:jane)
277 277
         agent.should have(0).errors_on(:sources)
278 278
       end
279
+
280
+      it "validates keep_events_for" do
281
+        agent = Agents::SomethingSource.new(:name => "something")
282
+        agent.user = users(:bob)
283
+        agent.should be_valid
284
+        agent.keep_events_for = nil
285
+        agent.should have(1).errors_on(:keep_events_for)
286
+        agent.keep_events_for = 1000
287
+        agent.should have(1).errors_on(:keep_events_for)
288
+        agent.keep_events_for = ""
289
+        agent.should have(1).errors_on(:keep_events_for)
290
+        agent.keep_events_for = 5
291
+        agent.should be_valid
292
+        agent.keep_events_for = 0
293
+        agent.should be_valid
294
+        agent.keep_events_for = 365
295
+        agent.should be_valid
296
+
297
+        # Rails seems to call to_i on the input. This guards against future changes to that behavior.
298
+        agent.keep_events_for = "drop table;"
299
+        agent.keep_events_for.should == 0
300
+      end
301
+    end
302
+
303
+    describe "cleaning up now-expired events" do
304
+      before do
305
+        @agent = Agents::SomethingSource.new(:name => "something")
306
+        @agent.keep_events_for = 5
307
+        @agent.user = users(:bob)
308
+        @agent.save!
309
+        @event = @agent.create_event :payload => { "hello" => "world" }
310
+        @event.expires_at.to_i.should be_within(2).of(5.days.from_now.to_i)
311
+      end
312
+
313
+      describe "when keep_events_for has not changed" do
314
+        it "does nothing" do
315
+          mock(@agent).update_event_expirations!.times(0)
316
+
317
+          @agent.options[:foo] = "bar1"
318
+          @agent.save!
319
+
320
+          @agent.options[:foo] = "bar1"
321
+          @agent.keep_events_for = 5
322
+          @agent.save!
323
+        end
324
+      end
325
+
326
+      describe "when keep_events_for is changed" do
327
+        it "updates events' expires_at" do
328
+          lambda {
329
+            @agent.options[:foo] = "bar1"
330
+            @agent.keep_events_for = 3
331
+            @agent.save!
332
+          }.should change { @event.reload.expires_at }
333
+          @event.expires_at.to_i.should be_within(2).of(3.days.from_now.to_i)
334
+        end
335
+
336
+        it "updates events relative to their created_at" do
337
+          @event.update_attribute :created_at, 2.days.ago
338
+          @event.reload.created_at.to_i.should be_within(2).of(2.days.ago.to_i)
339
+
340
+          lambda {
341
+            @agent.options[:foo] = "bar2"
342
+            @agent.keep_events_for = 3
343
+            @agent.save!
344
+          }.should change { @event.reload.expires_at }
345
+          @event.expires_at.to_i.should be_within(2).of(1.days.from_now.to_i)
346
+        end
347
+
348
+        it "nulls out expires_at when keep_events_for is set to 0" do
349
+          lambda {
350
+            @agent.options[:foo] = "bar"
351
+            @agent.keep_events_for = 0
352
+            @agent.save!
353
+          }.should change { @event.reload.expires_at }.to(nil)
354
+        end
355
+      end
279 356
     end
357
+
280 358
   end
281 359
 
282 360
   describe "scopes" do