Class MultiDayEvent
In: app/models/multi_day_event.rb
Parent: Event

Event that spans more than one day: stage races, six days, omniums MultiDayEvents represent events that occur on concurrent days, and Series and WeeklySeries subclasses represent events that do not occur on concurrent days, though this is just a convention.

Calculate start_date, end_date, and date from children. date = start_date

Cannot have a parent event

New child event should populate child event with parent data, but they don‘t

Methods

Public Class methods

Create MultiDayEvent from several SingleDayEvents. Use first SingleDayEvent to populate date, name, promoter, etc. Guess subclass (MultiDayEvent, Series, WeeklySeries) from SingleDayEvent dates

[Source]

     # File app/models/multi_day_event.rb, line 81
 81:   def MultiDayEvent.create_from_children(children)
 82:     raise ArgumentError.new("children cannot be empty") if children.empty?
 83:     
 84:     first_event = children.first
 85:     new_event_attributes = {
 86:       :city => first_event.city,
 87:       :discipline => first_event.discipline,
 88:       :email => first_event.email,
 89:       :flyer => first_event.flyer,
 90:       :name => first_event.name,
 91:       :phone => first_event.phone,
 92:       :promoter => first_event.promoter,
 93:       :prize_list => first_event.prize_list,
 94:       :sanctioned_by => first_event.sanctioned_by,
 95:       :state => first_event.state,
 96:       :team => first_event.team,
 97:       :velodrome => first_event.velodrome
 98:     }
 99:     
100:     new_multi_day_event_class = MultiDayEvent.guess_type(children)
101:     multi_day_event = new_multi_day_event_class.create!(new_event_attributes)
102:     multi_day_event.disable_notification!
103: 
104:     children.each do |child|
105:       multi_day_event.children << child
106:     end
107: 
108:     multi_day_event.enable_notification!
109:     multi_day_event
110:   end

[Source]

    # File app/models/multi_day_event.rb, line 64
64:   def MultiDayEvent.find_all_by_conditions(conditions, discipline = nil)
65:     if RacingAssociation.current.show_only_association_sanctioned_races_on_calendar
66:       conditions.first << " and sanctioned_by = ?"
67:       conditions << RacingAssociation.current.default_sanctioned_by
68:     end
69: 
70:     if discipline
71:       conditions.first << " and discipline = ?"
72:       conditions << discipline.name
73:     end
74: 
75:     MultiDayEvent.find(:all, :conditions => conditions, :order => "date")
76:   end

[Source]

    # File app/models/multi_day_event.rb, line 59
59:   def MultiDayEvent.find_all_by_unix_dates(start_date, end_date,  discipline = nil)
60:     conditions = ["date between ? and ?", "#{Time.at(start_date.to_i).strftime('%Y-%m-%d')}", "#{Time.at(end_date.to_i).strftime('%Y-%m-%d')}"]
61:     MultiDayEvent.find_all_by_conditions(conditions, discipline)
62:   end

[Source]

    # File app/models/multi_day_event.rb, line 54
54:   def MultiDayEvent.find_all_by_year(year, discipline = nil)
55:     conditions = ["date between ? and ?", "#{year}-01-01", "#{year}-12-31"]
56:     MultiDayEvent.find_all_by_conditions(conditions, discipline)
57:   end

This fails if a stage race spans more than one day but has more events than days we could look for events that span contiguous days...but a long stage race could have a rest day…

[Source]

     # File app/models/multi_day_event.rb, line 119
119:   def MultiDayEvent.guess_type(events)
120:     length = events.last.date - events.first.date
121:     if events.size - 1 == length
122:      MultiDayEvent
123:     else
124:       if events.first.date.wday == 0 or events.first.date.wday == 6
125:         Series
126:       else
127:         WeeklySeries
128:       end
129:     end
130:   end

[Source]

     # File app/models/multi_day_event.rb, line 112
112:   def MultiDayEvent.guess_type(name, date)
113:     events = SingleDayEvent.find(:all, :conditions => ['name = ? and extract(year from date) = ?', name, date])
114:     MultiDayEvent.guess_type(events)
115:   end

[Source]

     # File app/models/multi_day_event.rb, line 132
132:   def MultiDayEvent.same_name_and_year(event)
133:     raise ArgumentError, "'event' cannot be nil" if event.nil?
134:     MultiDayEvent.find(:first, :conditions => ['name = ? and extract(year from date) = ?', event.name, event.date.year])
135:   end

Public Instance methods

All children have results?

[Source]

     # File app/models/multi_day_event.rb, line 230
230:   def completed?(reload = false)
231:     children.count(reload) > 0 && (children_with_results(reload).size == children.count)
232:   end

[Source]

    # File app/models/multi_day_event.rb, line 41
41:              def create(attributes = {})
42:                attributes[:parent_id] = @owner.id
43:                attributes[:parent] = @owner
44:                Event::PROPOGATED_ATTRIBUTES.each { |attr| attributes[attr] = @owner[attr] }               
45:                event = SingleDayEvent.new(attributes)
46:                (event.date = @owner.date) unless  attributes[:date]
47:                event.parent = @owner
48:                event.save
49:                @owner.children << event
50:                event
51:              end

[Source]

    # File app/models/multi_day_event.rb, line 29
29:              def create!(attributes = {})
30:                attributes[:parent_id] = @owner.id
31:                attributes[:parent] = @owner
32:                Event::PROPOGATED_ATTRIBUTES.each { |attr| attributes[attr] = @owner[attr] }               
33:                event = SingleDayEvent.new(attributes)
34:                (event.date = @owner.date) unless attributes[:date]
35:                event.parent = @owner
36:                event.save!
37:                @owner.children << event
38:                event
39:              end

Create child events automatically, if we‘ve got enough info to do so

[Source]

     # File app/models/multi_day_event.rb, line 138
138:   def create_children
139:     return unless start_date && @end_date && @every
140:     
141:     _start_date = start_date
142:     until @every.include?(_start_date.wday)
143:       _start_date = _start_date.next 
144:     end
145:     
146:     _start_date.step(@end_date, 1) do |date|
147:       children.create!(:date => date) if @every.include?(date.wday)
148:     end
149:   end

[Source]

     # File app/models/multi_day_event.rb, line 211
211:   def date_range_long_s
212:     start_date_s = start_date.strftime('%a, %B %d')
213:     if start_date == end_date
214:       start_date_s
215:     else
216:       "#{start_date_s} to #{end_date.strftime('%a, %B %d, %Y')}"
217:     end
218:   end

format:

  • :short: 6/7-6/12
  • :long: 6/7/2010-6/12/2010

[Source]

     # File app/models/multi_day_event.rb, line 192
192:   def date_range_s(format = :short)
193:     if format == :long
194:       if start_date == end_date
195:         date.strftime('%m/%d/%Y')
196:       else
197:         "#{start_date.strftime('%m/%d/%Y')}-#{end_date.strftime('%m/%d/%Y')}"
198:       end
199:     else
200:       start_date_s = "#{start_date.month}/#{start_date.day}"
201:       if start_date == end_date
202:         start_date_s
203:       elsif start_date.month == end_date.month
204:           "#{start_date_s}-#{end_date.day}"
205:       else
206:         "#{start_date_s}-#{end_date.month}/#{end_date.day}"
207:       end
208:     end
209:   end

end_date is calculated from child events, and not saved to the DB. If there are no child events, end_date is set to start date. This value is stored in @end_date in memory, and is used to create a new MultiDayEvent with children. Example: MultiDayEvent.create!(:start_date => Date.new(2009, 4), :end_date => Date.new(2009, 10), :every => "Monday")

[Source]

     # File app/models/multi_day_event.rb, line 169
169:   def end_date=(value)
170:     @end_date = value
171:   end

[Source]

     # File app/models/multi_day_event.rb, line 173
173:   def end_date_s
174:     "#{end_date.month}/#{end_date.day}"
175:   end

Expects a value from Date::DAYNAMES: Monday, Tuesday, etc., or an array of same. Example: ["Saturday", "Sunday"]

[Source]

     # File app/models/multi_day_event.rb, line 178
178:   def every=(value)
179:     _every = value
180:     _every = [_every] unless value.respond_to?(:each)
181:     
182:     _every.each do |day|
183:       raise "'#{day}' must be in #{Date::DAYNAMES.join(', ')}" unless Date::DAYNAMES.index(day)
184:     end
185: 
186:     @every = _every.map { |day| Date::DAYNAMES.index(day) }
187:   end

Unassociated events with same name in same year

[Source]

     # File app/models/multi_day_event.rb, line 221
221:   def missing_children
222:     return [] unless name && date
223:     
224:     @missing_children ||= SingleDayEvent.find(:all, 
225:                           :conditions => ['parent_id is null and name = ? and extract(year from date) = ?', 
226:                                           name, date.year])
227:   end

Synch Races with children. More accurately: create a new Race on each child Event for each Race on the parent.

[Source]

     # File app/models/multi_day_event.rb, line 235
235:   def propagate_races
236:     children.each do |event|
237:       races.map(&:category).each do |category|
238:         unless event.races.map(&:category).include?(category)
239:           event.races.create!(:category => category)
240:         end
241:       end
242:     end
243:   end

[Source]

     # File app/models/multi_day_event.rb, line 245
245:   def to_s
246:     "<#{self.class} #{id} #{discipline} #{name} #{date} #{children.size}>"
247:   end

Uses SQL query to set date from child events

[Source]

     # File app/models/multi_day_event.rb, line 152
152:   def update_date(child = nil)
153:     return true if new_record?
154:     
155:     minimum_date = Event.minimum(:date, :conditions => { :parent_id => id, :cancelled => false, :postponed => false })
156:     unless minimum_date.blank?
157:       self.date = minimum_date
158:       if date_changed?
159:         # Don't trigger callbacks
160:         MultiDayEvent.update_all ["date = ?", date], ["id = ?", id]
161:       end
162:     end
163:     true
164:   end

[Validate]