acts_as_event_owner 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
data/README.textile
CHANGED
@@ -110,6 +110,15 @@ h3. One-time event
|
|
110
110
|
:start_at => Time.parse("4:00pm")
|
111
111
|
</pre>
|
112
112
|
|
113
|
+
h3. Every day at 08:00, 13:00, and 18:00
|
114
|
+
|
115
|
+
<pre>
|
116
|
+
EventSpecification.create :description => 'walk the dog',
|
117
|
+
:start_at => Time.parse("8:00am"),
|
118
|
+
:repeat => :per_hour,
|
119
|
+
:target => [8,13,18]
|
120
|
+
</pre>
|
121
|
+
|
113
122
|
h3. Every day
|
114
123
|
|
115
124
|
<pre>
|
data/acts_as_event_owner.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{acts_as_event_owner}
|
8
|
-
s.version = "1.1.
|
8
|
+
s.version = "1.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Danny Burkes"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-18}
|
13
13
|
s.description = %q{Simple calendar events for any ActiveRecord model}
|
14
14
|
s.email = %q{dburkes@netable.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -15,17 +15,22 @@ module ActsAsEventOwner
|
|
15
15
|
|
16
16
|
before_validation :set_defaults
|
17
17
|
validates_presence_of :description
|
18
|
-
validates_inclusion_of :repeat, :in => [:daily,:weekly,:monthly,:yearly], :allow_nil => true
|
18
|
+
validates_inclusion_of :repeat, :in => [:by_hour,:daily,:weekly,:monthly,:yearly], :allow_nil => true
|
19
19
|
validates_inclusion_of :on_the, :in => ON_THE.keys, :allow_nil => true
|
20
20
|
validates_numericality_of :frequency, :allow_nil => true
|
21
21
|
validates_presence_of :start_at
|
22
22
|
validate :validate_recurrence_rules
|
23
|
+
after_validation :set_defaults_after_validation
|
23
24
|
|
24
25
|
attr_accessor :generate
|
25
26
|
after_create :auto_generate_events
|
26
27
|
|
27
28
|
def validate_recurrence_rules
|
28
29
|
case self.repeat
|
30
|
+
when :by_hour
|
31
|
+
errors.add(:target, "must be an array") if !self.target.present? || !self.target.is_a?(Array)
|
32
|
+
[:on, :on_the].each {|v| errors.add(v, :present) if self.send(v)}
|
33
|
+
|
29
34
|
when :daily
|
30
35
|
[:on, :on_the, :target].each {|v| errors.add(v, :present) if self.send(v)}
|
31
36
|
|
@@ -58,8 +63,15 @@ module ActsAsEventOwner
|
|
58
63
|
return nil if !self.valid? || self.repeat.nil?
|
59
64
|
|
60
65
|
components = []
|
66
|
+
repeat = self.repeat
|
67
|
+
frequency = self.frequency
|
61
68
|
|
62
69
|
case self.repeat
|
70
|
+
when :by_hour
|
71
|
+
repeat = "DAILY"
|
72
|
+
components << "BYHOUR=#{self.target.join(',')}"
|
73
|
+
frequency = nil
|
74
|
+
|
63
75
|
when :daily
|
64
76
|
|
65
77
|
when :weekly
|
@@ -77,8 +89,8 @@ module ActsAsEventOwner
|
|
77
89
|
components << "BYSETPOS=#{ON_THE[self.on_the]};BYDAY=#{byday}" if self.on_the
|
78
90
|
end
|
79
91
|
|
80
|
-
components.unshift "INTERVAL=#{
|
81
|
-
components.unshift "FREQ=#{
|
92
|
+
components.unshift "INTERVAL=#{frequency}" if frequency
|
93
|
+
components.unshift "FREQ=#{repeat.to_s.upcase}"
|
82
94
|
components << "UNTIL=#{self.until.strftime("%Y%m%dT%H%M%SZ")}" if self.until
|
83
95
|
components.join(';')
|
84
96
|
end
|
@@ -139,6 +151,19 @@ module ActsAsEventOwner
|
|
139
151
|
self.generate = { :from => self.start_at, :to => self.start_at + 30.days } if self.generate.nil?
|
140
152
|
end
|
141
153
|
|
154
|
+
def set_defaults_after_validation
|
155
|
+
if self.errors.empty? && self.repeat == :by_hour
|
156
|
+
current_start_hour = self.start_at.hour
|
157
|
+
closest_repeat_hour = self.target.detect {|h| h > current_start_hour}
|
158
|
+
if closest_repeat_hour
|
159
|
+
self.start_at = Time.utc(self.start_at.year, self.start_at.month, self.start_at.day, closest_repeat_hour)
|
160
|
+
else
|
161
|
+
tomorrow = self.start_at + 24.hours
|
162
|
+
self.start_at = Time.utc(tomorrow.year, tomorrow.month, tomorrow.day, self.target.first)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
142
167
|
def byday
|
143
168
|
self.target.is_a?(Array) ? self.target.join(',').upcase : BYDAYS[self.target]
|
144
169
|
end
|
@@ -51,6 +51,45 @@ describe ActsAsEventOwner::EventSpecification do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
describe "events recurring multiple times per day" do
|
55
|
+
it "passes validations" do
|
56
|
+
new_event_specification(:repeat => :by_hour, :target => [8, 12, 16]).should be_valid
|
57
|
+
end
|
58
|
+
|
59
|
+
it "defaults start_at to the first occurrence" do
|
60
|
+
now = Time.now
|
61
|
+
Time.stub!(:now).and_return(Time.utc(2011, 1, 15, 8, 23))
|
62
|
+
create_event_specification(:repeat => :by_hour, :target => [8, 12, 16], :generate => false).start_at.utc.should == Time.utc(2011, 1, 15, 12, 00)
|
63
|
+
|
64
|
+
Time.stub!(:now).and_return(Time.utc(2011, 1, 15, 23, 23))
|
65
|
+
create_event_specification(:repeat => :by_hour, :target => [8, 12, 16], :generate => false).start_at.utc.should == Time.utc(2011, 1, 16, 8, 00)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "does not support invalid recurrence specifications" do
|
69
|
+
spec = new_event_specification(:repeat => :by_hour)
|
70
|
+
spec.should_not be_valid
|
71
|
+
spec.errors[:target].should be_present
|
72
|
+
|
73
|
+
spec = new_event_specification(:repeat => :by_hour, :on_the => :first)
|
74
|
+
spec.should_not be_valid
|
75
|
+
spec.errors[:on_the].should be_present
|
76
|
+
|
77
|
+
spec = new_event_specification(:repeat => :by_hour, :on => [1,2])
|
78
|
+
spec.should_not be_valid
|
79
|
+
spec.errors[:on].should be_present
|
80
|
+
|
81
|
+
spec = new_event_specification(:repeat => :by_hour, :target => 8)
|
82
|
+
spec.should_not be_valid
|
83
|
+
spec.errors[:target].should be_present
|
84
|
+
end
|
85
|
+
|
86
|
+
it "generates an RRULE" do
|
87
|
+
# every day at 08:00, 12:00, and 16:00
|
88
|
+
new_event_specification(:repeat => :by_hour, :target => [8,12,16]).to_rrule.should == "FREQ=DAILY;BYHOUR=8,12,16"
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
54
93
|
describe "events recurring daily" do
|
55
94
|
it "passes validations" do
|
56
95
|
new_event_specification(:repeat => :daily).should be_valid
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 1.1.
|
8
|
+
- 3
|
9
|
+
version: 1.1.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Danny Burkes
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-18 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|