acts_as_event_owner 1.1.2 → 1.1.3

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.
@@ -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>
@@ -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.2"
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{2010-12-27}
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=#{self.frequency}" if self.frequency
81
- components.unshift "FREQ=#{self.repeat.to_s.upcase}"
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
@@ -1,3 +1,3 @@
1
1
  module ActsAsEventOwner
2
- VERSION = "1.1.2" unless defined? ActsAsEventOwner::VERSION
2
+ VERSION = "1.1.3" unless defined? ActsAsEventOwner::VERSION
3
3
  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
- - 2
9
- version: 1.1.2
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: 2010-12-27 00:00:00 -08:00
17
+ date: 2011-01-18 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency