acts_as_event_owner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. data/.gitignore +7 -0
  2. data/LICENSE +24 -0
  3. data/README.textile +205 -0
  4. data/Rakefile +28 -0
  5. data/acts_as_event_owner.gemspec +76 -0
  6. data/generators/acts_as_event_owner_migration/USAGE +6 -0
  7. data/generators/acts_as_event_owner_migration/acts_as_event_owner_migration_generator.rb +7 -0
  8. data/generators/acts_as_event_owner_migration/templates/acts_as_event_owner_migration.rb +38 -0
  9. data/lib/acts_as_event_owner/core.rb +38 -0
  10. data/lib/acts_as_event_owner/event_occurrence.rb +6 -0
  11. data/lib/acts_as_event_owner/event_specification.rb +152 -0
  12. data/lib/acts_as_event_owner/exception.rb +4 -0
  13. data/lib/acts_as_event_owner/railtie.rb +13 -0
  14. data/lib/acts_as_event_owner/version.rb +3 -0
  15. data/lib/acts_as_event_owner.rb +17 -0
  16. data/lib/generators/acts_as_event_owner/migration/migration_generator.rb +31 -0
  17. data/lib/generators/acts_as_event_owner/migration/templates/active_record/acts_as_event_owner_migration.rb +38 -0
  18. data/lib/generators/acts_as_event_owner_migration/USAGE +6 -0
  19. data/lib/generators/acts_as_event_owner_migration/acts_as_event_owner_migration_generator.rb +7 -0
  20. data/lib/generators/acts_as_event_owner_migration/templates/acts_as_event_owner_migration.rb +38 -0
  21. data/lib/tasks/acts_as_event_owner_tasks.rake +14 -0
  22. data/rails/init.rb +1 -0
  23. data/spec/acts_as_event_owner/core_spec.rb +62 -0
  24. data/spec/acts_as_event_owner/event_specification_spec.rb +365 -0
  25. data/spec/schema.rb +43 -0
  26. data/spec/spec_helper.rb +26 -0
  27. data/spec/support/model_builders.rb +13 -0
  28. data/spec/support/user.rb +3 -0
  29. metadata +106 -0
@@ -0,0 +1,38 @@
1
+ class ActsAsEventOwnerMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :event_specifications do |t|
4
+ t.integer :owner_id
5
+ t.string :owner_type
6
+ t.string :description
7
+ t.datetime :start_at
8
+ t.datetime :end_at
9
+ t.string :repeat # daily, weekly, monthly, yearly
10
+ t.integer :frequency, :default => 1 # every 'n' days, weeks, months, or years
11
+ t.string :on # su, mo, tu, we, th, fr, sa, 1-31, jan-dec
12
+ t.string :on_the # first, second, third, fourth, last
13
+ t.string :target # su, mo, tu, we, th, fr, sa, day, wkday, wkend
14
+ t.datetime :until
15
+ t.timestamps
16
+ end
17
+
18
+ add_index :event_specifications, [:owner_id, :owner_type]
19
+
20
+ create_table :event_occurrences do |t|
21
+ t.integer :owner_id
22
+ t.string :owner_type
23
+ t.integer :event_specification_id
24
+ t.datetime :start_at
25
+ t.datetime :end_at
26
+ t.string :description
27
+ t.timestamps
28
+ end
29
+
30
+ add_index :event_occurrences, [:owner_id, :owner_type]
31
+ add_index :event_occurrences, :event_specification_id
32
+ end
33
+
34
+ def self.down
35
+ drop_table :event_specifications
36
+ drop_table :event_occurrences
37
+ end
38
+ end
@@ -0,0 +1,6 @@
1
+ Usage:
2
+
3
+ script/generate acts_as_event_owner_migration
4
+
5
+ This will create a migration that will add the acts_as_event_owner tables to your database
6
+
@@ -0,0 +1,7 @@
1
+ class ActsAsEventOwnerMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'acts_as_event_owner_migration.rb', File.join('db', 'migrate'), :migration_file_name => "acts_as_event_owner_migration"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ class ActsAsEventOwnerMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :event_specifications do |t|
4
+ t.integer :owner_id
5
+ t.string :owner_type
6
+ t.string :description
7
+ t.datetime :start_at
8
+ t.datetime :end_at
9
+ t.string :repeat # daily, weekly, monthly, yearly
10
+ t.integer :frequency, :default => 1 # every 'n' days, weeks, months, or years
11
+ t.string :on # su, mo, tu, we, th, fr, sa, 1-31, jan-dec
12
+ t.string :on_the # first, second, third, fourth, last
13
+ t.string :target # su, mo, tu, we, th, fr, sa, day, wkday, wkend
14
+ t.datetime :until
15
+ t.timestamps
16
+ end
17
+
18
+ add_index :event_specifications, [:owner_id, :owner_type]
19
+
20
+ create_table :event_occurrences do |t|
21
+ t.integer :owner_id
22
+ t.string :owner_type
23
+ t.integer :event_specification_id
24
+ t.datetime :start_at
25
+ t.datetime :end_at
26
+ t.string :description
27
+ t.timestamps
28
+ end
29
+
30
+ add_index :event_occurrences, [:owner_id, :owner_type]
31
+ add_index :event_occurrences, :event_specification_id
32
+ end
33
+
34
+ def self.down
35
+ drop_table :event_specifications
36
+ drop_table :event_occurrences
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ namespace :acts_as_event_owner do
2
+ task :require_from do
3
+ raise "Set FROM to something understandable by Time.parse" if !ENV['FROM']
4
+ end
5
+
6
+ task :require_to do
7
+ raise "Set TO to something understandable by Time.parse" if !ENV['TO']
8
+ end
9
+
10
+ desc "Generate all events within a certain time window"
11
+ task :generate_events => [:environment, :require_from, :require_to] do
12
+ ActsAsEventOwner::EventSpecification.all(:conditions => "until IS NULL OR until >= '#{Time.now.utc.to_s(:db)}'").each {|spec| spec.generate_events(options)}
13
+ end
14
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'acts_as_event_owner'
@@ -0,0 +1,62 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ActsAsEventOwner::Core do
4
+ before(:each) do
5
+ clean_database!
6
+ @user = User.create :name => 'dude'
7
+ @now = Time.now.utc
8
+ @bod = Date.today.to_time.utc
9
+ end
10
+
11
+ it "adds associations to the host object" do
12
+ lambda {
13
+ @user.events
14
+ @user.event_specifications
15
+ }.should_not raise_error
16
+ end
17
+
18
+ it "adds event specifications to the host object" do
19
+ lambda {
20
+ @user.event_specifications.create :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 1
21
+ }.should change(EventSpecification, :count).by(1)
22
+
23
+ specs = @user.reload.event_specifications
24
+ specs.size.should == 1
25
+ end
26
+
27
+ it "adds events to the host object" do
28
+ @user.event_specifications.create :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 1, :generate => false
29
+ @user.event_specifications.create :description => 'go to the gym', :start_at => @now, :repeat => :daily, :frequency => 2, :generate => false
30
+
31
+ lambda {
32
+ @user.events.generate :from => @bod, :to => @bod + 1.week
33
+ }.should change(EventOccurrence, :count).by(11)
34
+ end
35
+
36
+ it "injects events into the association immediately" do
37
+ @user.event_specifications.create :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 1, :generate => false
38
+ @user.events.should be_empty
39
+ @user.events.generate :from => @bod, :to => @bod + 1.week
40
+ @user.events.should be_present
41
+ @user.events.size.should == 7
42
+ end
43
+
44
+ describe "events association" do
45
+ before(:each) do
46
+ @new_event = EventOccurrence.new
47
+ @new_event.should be_valid
48
+ end
49
+
50
+ it "raises an exception if #<< is called" do
51
+ lambda { @user.events << @new_event }.should raise_error(ActsAsEventOwner::Exception)
52
+ end
53
+
54
+ it "raises an exception is #build is called" do
55
+ lambda { @user.events.build @new_event.attributes }.should raise_error(ActsAsEventOwner::Exception)
56
+ end
57
+
58
+ it "raises an exception if #create is called" do
59
+ lambda { @user.events.create @new_event.attributes }.should raise_error(ActsAsEventOwner::Exception)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,365 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ActsAsEventOwner::EventSpecification do
4
+ before(:each) do
5
+ clean_database!
6
+ end
7
+
8
+ describe "defaults" do
9
+ it "defaults start_at to now" do
10
+ now = Time.now
11
+ Time.stub!(:now).and_return(now)
12
+ spec = new_event_specification
13
+ spec.should be_valid
14
+ spec.start_at.should == now
15
+ end
16
+
17
+ it "defaults duration to one hour" do
18
+ spec = new_event_specification
19
+ spec.should be_valid
20
+ spec.end_at.should == spec.start_at + 1.hour
21
+ end
22
+
23
+ it "defaults repeat until forever" do
24
+ spec = new_event_specification(:repeat => :daily)
25
+ spec.should be_valid
26
+ spec.until.should be_nil
27
+ end
28
+ end
29
+
30
+ describe "validations" do
31
+ it "requires a valid repeat interval" do
32
+ spec = new_event_specification(:repeat => :bogus)
33
+ spec.should_not be_valid
34
+ spec.errors[:repeat].should be_present
35
+ end
36
+
37
+ it "requires a description" do
38
+ spec = new_event_specification(:description => nil)
39
+ spec.should_not be_valid
40
+ spec.errors[:description].should be_present
41
+ end
42
+ end
43
+
44
+ describe "non-recurring events" do
45
+ it "passes validations" do
46
+ new_event_specification.should be_valid
47
+ end
48
+
49
+ it "does not generate an RRULE" do
50
+ new_event_specification.to_rrule.should be_nil
51
+ end
52
+ end
53
+
54
+ describe "events recurring daily" do
55
+ it "passes validations" do
56
+ new_event_specification(:repeat => :daily).should be_valid
57
+ new_event_specification(:repeat => :daily, :frequency => 4).should be_valid
58
+ end
59
+
60
+ it "does not support invalid recurrence specifications" do
61
+ spec = new_event_specification(:repeat => :daily, :frequency => 'foo')
62
+ spec.should_not be_valid
63
+ spec.errors[:frequency].should be_present
64
+
65
+ spec = new_event_specification(:repeat => :daily, :on => [1, 2])
66
+ spec.should_not be_valid
67
+ spec.errors[:on].should be_present
68
+
69
+ spec = new_event_specification(:repeat => :daily, :on_the => :first)
70
+ spec.should_not be_valid
71
+ spec.errors[:on_the].should be_present
72
+
73
+ spec = new_event_specification(:repeat => :daily, :on_the => :first, :target => :wkday)
74
+ spec.should_not be_valid
75
+ spec.errors[:target].should be_present
76
+ end
77
+
78
+ it "defaults frequency to 1" do
79
+ new_event_specification(:repeat => :daily).frequency.should == 1
80
+ end
81
+
82
+ it "generates an RRULE" do
83
+ # every day
84
+ new_event_specification(:repeat => :daily).to_rrule.should == "FREQ=DAILY;INTERVAL=1"
85
+ # every four days
86
+ new_event_specification(:repeat => :daily, :frequency => 4).to_rrule.should == "FREQ=DAILY;INTERVAL=4"
87
+ end
88
+ end
89
+
90
+ describe "events recurring weekly" do
91
+ it "passes validations" do
92
+ new_event_specification(:repeat => :weekly).should be_valid
93
+ new_event_specification(:repeat => :weekly, :frequency => 2).should be_valid
94
+ new_event_specification(:repeat => :weekly, :on => [:mo, :we, :fr]).should be_valid
95
+ new_event_specification(:repeat => :weekly, :frequency => 2, :on => [:mo, :we, :fr]).should be_valid
96
+ new_event_specification(:repeat => :weekly, :frequency => 2, :on => [:mo, :we, :fr], :until => Time.parse("12/31/2010")).should be_valid
97
+ end
98
+
99
+ it "does not support invalid recurrence specifications" do
100
+ spec = new_event_specification(:repeat => :weekly, :frequency => 'foo')
101
+ spec.should_not be_valid
102
+ spec.errors[:frequency].should be_present
103
+
104
+ spec = new_event_specification(:repeat => :weekly, :on_the => :first, :target => :wkend)
105
+ spec.should_not be_valid
106
+ spec.errors[:on_the].should be_present
107
+ spec.errors[:target].should be_present
108
+
109
+ spec = new_event_specification(:repeat => :weekly, :on => '2')
110
+ spec.should_not be_valid
111
+ spec.errors[:on].should be_present
112
+ end
113
+
114
+ it "generates an RRULE" do
115
+ # every week
116
+ new_event_specification(:repeat => :weekly).to_rrule.should == "FREQ=WEEKLY;INTERVAL=1"
117
+ # every two weeks
118
+ new_event_specification(:repeat => :weekly, :frequency => 2).to_rrule.should == "FREQ=WEEKLY;INTERVAL=2"
119
+ # every monday, wednesday, and friday
120
+ new_event_specification(:repeat => :weekly, :on => [:mo, :we, :fr]).to_rrule.should == "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR"
121
+ # every other monday, wednesday, and friday
122
+ new_event_specification(:repeat => :weekly, :frequency => 2, :on => [:mo, :we, :fr]).to_rrule.should == "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR"
123
+ # every other monday, wednesday, and friday, until 12/31/2010
124
+ new_event_specification(:repeat => :weekly, :frequency => 2, :on => [:mo, :we, :fr], :until => Time.parse("12/31/2010")).to_rrule.should == "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR;UNTIL=20101231T000000Z"
125
+ end
126
+ end
127
+
128
+ describe "events recurring monthly" do
129
+ it "passes validations" do
130
+ new_event_specification(:repeat => :monthly).should be_valid
131
+ new_event_specification(:repeat => :monthly, :frequency => 2).should be_valid
132
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on => [1, 15, 20]).should be_valid
133
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on_the => :third, :target => :wkday).should be_valid
134
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on_the => :third, :target => [:mo, :we], :until => Time.parse("12/31/2010")).should be_valid
135
+ end
136
+
137
+ it "does not support invalid recurrence specification" do
138
+ spec = new_event_specification(:repeat => :monthly, :frequency => 'foo')
139
+ spec.should_not be_valid
140
+ spec.errors[:frequency].should be_present
141
+
142
+ spec = new_event_specification(:repeat => :monthly, :on => 2)
143
+ spec.should_not be_valid
144
+ spec.errors[:on].should be_present
145
+
146
+ spec = new_event_specification(:repeat => :monthly, :on => [2], :on_the => :first, :target => :wkday)
147
+ spec.should_not be_valid
148
+ spec.errors[:on].should be_present
149
+
150
+ spec = new_event_specification(:repeat => :monthly, :on_the => 2)
151
+ spec.should_not be_valid
152
+ spec.errors[:on_the].should be_present
153
+
154
+ spec = new_event_specification(:repeat => :monthly, :on_the => :first, :target => :we)
155
+ spec.should_not be_valid
156
+ spec.errors[:target].should be_present
157
+
158
+ spec = new_event_specification(:repeat => :monthly, :on_the => :first, :on => [2])
159
+ spec.should_not be_valid
160
+ spec.errors[:on].should be_present
161
+ end
162
+
163
+ it "generates an RRULE" do
164
+ # every month
165
+ new_event_specification(:repeat => :monthly).to_rrule.should == "FREQ=MONTHLY;INTERVAL=1"
166
+ # every two months
167
+ new_event_specification(:repeat => :monthly, :frequency => 2).to_rrule.should == "FREQ=MONTHLY;INTERVAL=2"
168
+ # every other month, on the 1st, 15th, and 20th
169
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on => [1, 15, 20]).to_rrule.should == "FREQ=MONTHLY;INTERVAL=2;BYMONTHDAY=1,15,20"
170
+ # every other month, on the third weekday of the month
171
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on_the => :third, :target => :wkday).to_rrule.should == "FREQ=MONTHLY;INTERVAL=2;BYSETPOS=3;BYDAY=MO,TU,WE,TH,FR"
172
+ # every other month, on the third monday and third wednesday, until 12/31/2010
173
+ new_event_specification(:repeat => :monthly, :frequency => 2, :on_the => :third, :target => [:mo, :we], :until => Time.parse("12/31/2010")).to_rrule.should == "FREQ=MONTHLY;INTERVAL=2;BYSETPOS=3;BYDAY=MO,WE;UNTIL=20101231T000000Z"
174
+ end
175
+ end
176
+
177
+ describe "events recurring yearly" do
178
+ it "passes validations" do
179
+ new_event_specification(:repeat => :yearly, :on => [1,7]).should be_valid
180
+ new_event_specification(:repeat => :yearly, :frequency => 2, :on => [1,7]).should be_valid
181
+ new_event_specification(:repeat => :yearly, :on => [1,7], :on_the => :first, :target => :wkend).should be_valid
182
+ new_event_specification(:repeat => :yearly, :frequency => 2, :on => [1,7], :on_the => :first, :target => :wkday, :until => Time.parse("12/31/2010")).should be_valid
183
+ end
184
+
185
+ it "does not support invalid recurrence rules" do
186
+ spec = new_event_specification(:repeat => :yearly)
187
+ spec.should_not be_valid
188
+ spec.errors[:on].should be_present
189
+
190
+ spec = new_event_specification(:repeat => :yearly, :frequency => 3)
191
+ spec.should_not be_valid
192
+ spec.errors[:on].should be_present
193
+
194
+ spec = new_event_specification(:repeat => :yearly, :frequency => 'foo')
195
+ spec.should_not be_valid
196
+ spec.errors[:frequency].should be_present
197
+
198
+ spec = new_event_specification(:repeat => :yearly, :on => 2)
199
+ spec.should_not be_valid
200
+ spec.errors[:on].should be_present
201
+
202
+ spec = new_event_specification(:repeat => :yearly, :on => [2], :on_the => 'first')
203
+ spec.should_not be_valid
204
+ spec.errors[:on_the].should be_present
205
+
206
+ spec = new_event_specification(:repeat => :yearly, :on => [2], :on_the => :first, :target => 2)
207
+ spec.should_not be_valid
208
+ spec.errors[:target].should be_present
209
+ end
210
+
211
+ it "generates an RRULE" do
212
+ # every year in january and july
213
+ new_event_specification(:repeat => :yearly, :on => [1,7]).to_rrule.should == "FREQ=YEARLY;INTERVAL=1;BYMONTH=1,7"
214
+ # every other year, in january and july
215
+ new_event_specification(:repeat => :yearly, :frequency => 2, :on => [1,7]).to_rrule.should == "FREQ=YEARLY;INTERVAL=2;BYMONTH=1,7"
216
+ # every year, on the first weekend day in january and july
217
+ new_event_specification(:repeat => :yearly, :on => [1,7], :on_the => :first, :target => :wkend).to_rrule.should == "FREQ=YEARLY;INTERVAL=1;BYMONTH=1,7;BYSETPOS=1;BYDAY=SU,SA"
218
+ # every other year, on the first weekday in january and july, until 12/31/2010
219
+ new_event_specification(:repeat => :yearly, :frequency => 2, :on => [1,7], :on_the => :first, :target => :wkday, :until => Time.parse("12/31/2010")).to_rrule.should == "FREQ=YEARLY;INTERVAL=2;BYMONTH=1,7;BYSETPOS=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=20101231T000000Z"
220
+ end
221
+ end
222
+
223
+ describe "#generate_events" do
224
+ before(:each) do
225
+ @now = Time.now.utc
226
+ @bod = Date.today.to_time.utc
227
+ end
228
+
229
+ describe "non-recurring events" do
230
+ before(:each) do
231
+ @spec = create_event_specification :start_at => @now, :added_string => 'foo', :added_boolean => true, :added_datetime => Date.yesterday.to_time, :generate => false
232
+ end
233
+
234
+ it "generates a single event" do
235
+ lambda {
236
+ @spec.generate_events
237
+ }.should change(EventOccurrence, :count).by(1)
238
+ end
239
+
240
+ it "copies added columns from event_specifications to event_occurrences" do
241
+ @spec.generate_events
242
+ @spec.event_occurrences.first.added_string.should == @spec.added_string
243
+ @spec.event_occurrences.first.added_boolean.should == @spec.added_boolean
244
+ @spec.event_occurrences.first.added_datetime.should == @spec.added_datetime
245
+ end
246
+
247
+ it "allows attribute overrides" do
248
+ @spec.generate_events :attributes => { :description => 'something new', :added_string => 'something else new'}
249
+ @spec.event_occurrences.first.description.should == 'something new'
250
+ @spec.event_occurrences.first.added_string.should == 'something else new'
251
+ end
252
+ end
253
+
254
+ describe "recurring events" do
255
+ before(:each) do
256
+ @spec = create_event_specification :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 1, :generate => false
257
+ end
258
+
259
+ it "generates recurring events according to the rrule" do
260
+ lambda {
261
+ @spec.generate_events :from => @bod, :to => @bod + 1.week
262
+ }.should change(EventOccurrence, :count).by(7)
263
+ end
264
+
265
+ it "does not generate events before the specified :from" do
266
+ lambda {
267
+ @spec.generate_events :from => @bod + 1.day, :to => @bod + 1.week
268
+ }.should change(EventOccurrence, :count).by(6)
269
+ end
270
+
271
+ it "does not generate events after the specified :to" do
272
+ lambda {
273
+ @spec.generate_events :from => @bod + 1.day, :to => @bod + 6.days
274
+ }.should change(EventOccurrence, :count).by(5)
275
+ end
276
+
277
+ it "does not generate more events than the specified :count" do
278
+ lambda {
279
+ @spec.generate_events :from => @bod, :to => @bod + 1.week, :count => 3
280
+ }.should change(EventOccurrence, :count).by(3)
281
+ end
282
+
283
+ it "returns the new events" do
284
+ events = @spec.generate_events :from => @bod, :to => @bod + 1.week
285
+ events.should be_present
286
+ events.first.class.should == EventOccurrence
287
+ end
288
+
289
+ it "returns but does not persist duplicate events" do
290
+ lambda {
291
+ @spec.generate_events :from => @bod, :to => @bod + 1.week
292
+ }.should change(EventOccurrence, :count).by(7)
293
+
294
+ lambda {
295
+ events = @spec.generate_events :from => @bod, :to => @bod + 1.week
296
+ events.should be_present
297
+ events.size.should == 7
298
+ }.should_not change(EventOccurrence, :count)
299
+ end
300
+
301
+ it "raises an exception if the event specification is invalid" do
302
+ spec = new_event_specification(:description => nil)
303
+ spec.should_not be_valid
304
+ lambda {
305
+ spec.generate_events :from => @bod
306
+ }.should raise_error(ActsAsEventOwner::Exception)
307
+ end
308
+
309
+ it "does not generate events for specifications that are past their end_at" do
310
+ @spec.update_attributes! :start_at => @now - 1.week, :until => @now - 2.days
311
+ lambda {
312
+ @spec.generate_events :from => @bod, :to => @bod + 1.week
313
+ }.should_not change(EventOccurrence, :count)
314
+ end
315
+ end
316
+ end
317
+
318
+ describe "autogeneration" do
319
+ before(:each) do
320
+ @now = Time.now.utc
321
+ @bod = Date.today.to_time.utc
322
+ end
323
+
324
+ def create_daily_event(generate=nil)
325
+ create_event_specification :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 2, :generate => generate
326
+ end
327
+
328
+ it "generates 30 days worth of events by default" do
329
+ lambda {
330
+ create_daily_event
331
+ }.should change(EventOccurrence, :count).by(15)
332
+ end
333
+
334
+ it "does not generate any events if the :generate attribute is set to false" do
335
+ lambda {
336
+ create_daily_event(false)
337
+ }.should_not change(EventOccurrence, :count)
338
+ end
339
+
340
+ it "generates events according the :generate attribute" do
341
+ lambda {
342
+ create_daily_event(:to => @now + 15.days)
343
+ }.should change(EventOccurrence, :count).by(8)
344
+
345
+ lambda {
346
+ create_daily_event(:count => 5)
347
+ }.should change(EventOccurrence, :count).by(5)
348
+ end
349
+ end
350
+
351
+ describe "self.generate_events" do
352
+ before(:each) do
353
+ @now = Time.now.utc
354
+ @bod = Date.today.to_time.utc
355
+ @walking_the_dog = create_event_specification :description => 'walk the dog', :start_at => @now, :repeat => :daily, :frequency => 1, :generate => false
356
+ @taking_out_the_trash = create_event_specification :description => 'take out the trash', :start_at => @now, :repeat => :daily, :frequency => 3, :generate => false
357
+ end
358
+
359
+ it "generates events for all event specifications" do
360
+ lambda {
361
+ ActsAsEventOwner::EventSpecification.generate_events :from => @bod, :to => @bod + 1.week
362
+ }.should change(EventOccurrence, :count).by(10)
363
+ end
364
+ end
365
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,43 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+ create_table "event_occurrences", :force => true do |t|
3
+ t.integer "owner_id"
4
+ t.string "owner_type"
5
+ t.integer "event_specification_id"
6
+ t.datetime "start_at"
7
+ t.datetime "end_at"
8
+ t.string "description"
9
+ t.datetime "created_at"
10
+ t.datetime "updated_at"
11
+ t.string "added_string"
12
+ t.boolean "added_boolean"
13
+ t.datetime "added_datetime"
14
+ end
15
+ add_index "event_occurrences", ["event_specification_id"], :name => "index_event_occurrences_on_event_specification_id"
16
+ add_index "event_occurrences", ["owner_id", "owner_type"], :name => "index_event_occurrences_on_owner_id_and_owner_type"
17
+
18
+ create_table "event_specifications", :force => true do |t|
19
+ t.integer "owner_id"
20
+ t.string "owner_type"
21
+ t.string "description"
22
+ t.datetime "start_at"
23
+ t.datetime "end_at"
24
+ t.string "repeat"
25
+ t.integer "frequency", :default => 1
26
+ t.string "on"
27
+ t.string "on_the"
28
+ t.string "target"
29
+ t.datetime "until"
30
+ t.datetime "created_at"
31
+ t.datetime "updated_at"
32
+ t.string "added_string"
33
+ t.boolean "added_boolean"
34
+ t.datetime "added_datetime"
35
+ end
36
+ add_index "event_specifications", ["owner_id", "owner_type"], :name => "index_event_specifications_on_owner_id_and_owner_type"
37
+
38
+ create_table "users", :force => true do |t|
39
+ t.string "name"
40
+ t.datetime "created_at"
41
+ t.datetime "updated_at"
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'pp'
4
+
5
+ ActiveRecord::Base.establish_connection({
6
+ :adapter => 'sqlite3',
7
+ :database => ':memory:'
8
+ })
9
+ # ActiveRecord::Base.logger = Logger.new(STDOUT)
10
+
11
+ require File.expand_path('../../lib/acts_as_event_owner', __FILE__)
12
+ include ActsAsEventOwner
13
+
14
+ require 'support/model_builders'
15
+ require 'support/user'
16
+
17
+ ActiveRecord::Base.silence do
18
+ ActiveRecord::Migration.verbose = false
19
+ load(File.dirname(__FILE__) + '/schema.rb')
20
+ end
21
+
22
+ def clean_database!
23
+ [ActsAsEventOwner::EventSpecification, ActsAsEventOwner::EventOccurrence, User].each do |model|
24
+ ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ def attributes_for_event_specification(overrides={})
2
+ {
3
+ :description => 'do something'
4
+ }.merge(overrides)
5
+ end
6
+
7
+ def new_event_specification(overrides={})
8
+ ActsAsEventOwner::EventSpecification.new(attributes_for_event_specification(overrides))
9
+ end
10
+
11
+ def create_event_specification(overrides={})
12
+ ActsAsEventOwner::EventSpecification.create(attributes_for_event_specification(overrides))
13
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ acts_as_event_owner
3
+ end