Class Event
In: app/models/event.rb
Parent: Document

 Clase para los eventos. Es subclase de Document, por lo que su tabla es documents

Methods

Included Modules

Geokit::Geocoders Tools::Calendar::InstanceMethods

Attributes

schedule_id  [RW] 

Public Class methods

Dependiendo de la sección donde se muestra un evento en Irekia, al evento le corresponde un Tag u otro. Esta función devuelve la lista con los tags que corresponden al evento.

[Source]

     # File app/models/event.rb, line 429
429:   def self.irekia_tags
430:     self.show_in_opts.map {|opt| Tag.find_by_name_es("Irekia::#{opt.capitalize}")}.compact
431:   end

El nombre de la agenda para los eventos compartidos es "Agenda compartida".

[Source]

     # File app/models/event.rb, line 522
522:   def self.schedule_name
523:     I18n.translate('sadmin.events.agenda_compartida')
524:   end

Los eventos que se muestran en Irekia corresponden a una de las tres secciones: actos, acciones y eventos. Esta función devuelve la lista con los nombres de estas secciones.

[Source]

     # File app/models/event.rb, line 423
423:   def self.show_in_opts
424:     ["actos", "acciones", "eventos"]
425:   end

Public Instance methods

Los miembros de departamento tienen restrigido el lugar donde pueden publicar eventos (privados, irekia o agencia). Aunque el formulario sólo les muestra las opciones que les corresponden, nos aseguramos que no añaden eventos donde no pueden.

[Source]

     # File app/models/event.rb, line 200
200:   def check_user_can_create_this_type_of_event
201:     yes_he_can = false
202:     current_user = User.find(UserActionObserver.current_user)
203:     if (self.is_private? && current_user.can?("create_private", "events")) || \
204:       (self.show_in_irekia? && current_user.can?("create_irekia", "events")) || \
205:       (self.show_in_agencia? && current_user.can?("create_agencia", "events"))
206:         yes_he_can = true
207:     end
208:     if yes_he_can
209:       return true
210:     else
211:       errors.add_to_base "No puedes crear eventos de este tipo"
212:       return false
213:     end
214:   end

Indica si el estado del evento es ‘confirmado’.

[Source]

     # File app/models/event.rb, line 390
390:   def confirmed
391:     self.state.eql?('confirmado')
392:   end

Asigna el valor del campo state. Si val = true el evento es confirmado. y el valor del campo state es confirmado. En el caso contrario, el valor del campo state es previsto.

Este método se llama cuando se reciben los datos de un formulario. En el formulario se usa un check_box para indicar si el evento es confirmado o no y por lo tanto el valor del val es 0 o 1.

[Source]

     # File app/models/event.rb, line 400
400:   def confirmed=(val)
401:     case val
402:       when true
403:         self.state = 'confirmado'
404:       when false
405:         self.state = 'previsto'
406:     else
407:       self.state = val.to_i.eql?(1) ? 'confirmado' : 'previsto'
408:     end
409:   end

Indica si el evento está confirmado o no.

[Source]

     # File app/models/event.rb, line 385
385:   def confirmed?
386:     self.confirmed
387:   end

Copia los datos del evt a self.

[Source]

     # File app/models/event.rb, line 550
550:   def copy_from(evt)
551:     evt_attr = evt.attributes
552:     evt_attr.delete('id')
553:     evt_attr.each do |at, value|
554:       if self.respond_to?("#{at}=")
555:         self.send("#{at}=", value)
556:       end
557:     end
558:   
559:     if evt.is_a?(ScheduleEvent)
560:       # self.is_private = true
561:       
562:       # By default the event goes to schedule department if present or to Lehendakaritza.
563:       self.organization_id = evt.organization_id || Organization.find_by_internal_id(1).id
564:     end
565:   
566:     self
567:   end

Descripción formateada para ical

[Source]

     # File app/models/event.rb, line 491
491:   def description_for_ics
492:     description = "#{self.organization.name}.\n"
493:     description << "#{self.speaker}.\n" if self.speaker.present?
494:     description << self.body.strip_html
495:     return description
496:   end

No todas las columnas de la tabla documents se utilizan en los eventos, por lo que nos aseguramos de que están vacías. Se llama desde before_save

[Source]

     # File app/models/event.rb, line 111
111:   def disable_unnecessary_fields
112:     self.has_comments = false
113:     self.comments_closed = true
114:     self.has_comments_with_photos = false
115:     self.has_ratings = false
116:     self.comments_count = 0    
117:     self.cover_photo_file_name = nil
118:     self.cover_photo_content_type = nil
119:     self.cover_photo_file_size = nil
120:     self.cover_photo_updated_at = nil
121:   end

Comprueba que la fecha de finalización es posterior a la de inicio. Se llama en validate

[Source]

    # File app/models/event.rb, line 60
60:   def ends_later_than_it_starts
61:     errors.add_to_base "La fecha de fin debe ser posterior a la de inicio" if self.ends_at < self.starts_at
62:   end

Averigua las coordenadas geográficas donde ocurrirá el evento para poder mostrarlo en el mapa. Se llama desde before_save

[Source]

     # File app/models/event.rb, line 125
125:   def fill_lat_lng_data
126:     if location_for_gmaps_changed? 
127:       if "#{location_for_gmaps} #{city}".blank?
128:         self.lat = self.lng = nil
129:       else
130:         full_location = "#{location_for_gmaps}, #{city}, Spain"
131:         loc = MultiGeocoder.geocode("#{full_location}")
132:         unless loc.success
133:           loc = MultiGeocoder.geocode(location_for_gmaps)
134:         end
135:   
136:         if loc.success
137:           self.lat, self.lng = loc.lat, loc.lng
138:         end
139:       end
140:     end
141:   end

Devuelve el Tag relacionado con la sección de Irekia donde sale en evento.

[Source]

     # File app/models/event.rb, line 444
444:   def irekia_tag
445:     for i in Event.show_in_opts
446:       res = self.tags.detect {|t| t.name_es.eql?("Irekia::#{i.capitalize}") }
447:       return res unless res.nil?
448:     end    
449:     nil
450:   end

El evento puede eliminarse por completo si no hay que notificar sobre su eliminación

[Source]

     # File app/models/event.rb, line 499
499:   def is_destroyable?
500:     if (!self.deleted? && self.alerts.sent.count > 0) || (self.deleted? && self.alerts.unsent.count > 0)
501:       false
502:     else
503:       true
504:     end
505:   end

Si el valor de val es false el evento es privado y por lo tanto se asigna false como valor de los campos show_in_irekia y show_in_agencia.

[Source]

    # File app/models/event.rb, line 88
88:   def is_private=(val)
89:     if val
90:       self.show_in_irekia = false
91:       self.show_in_agencia = false
92:     end
93:   end

Devuelve true si el evento es privado y false si no lo es.

[Source]

    # File app/models/event.rb, line 82
82:   def is_private?
83:     !show_in_irekia? && !show_in_agencia?
84:   end

Método auxiliar. Un evento es púbico si no es privado.

[Source]

     # File app/models/event.rb, line 313
313:   def is_public?
314:     !self.is_private?
315:   end

Devuelve el cuerpo del evento en microformato

[Source]

     # File app/models/event.rb, line 357
357:   def microformat_body
358:     m = body.to_s.match(/(.+)<p.*>###<\/p>(.+)/m)
359:     # m = body.match(/((.+?)<\/p>)/m)
360:     if m 
361:       b = "<div class='description'>#{m[1]}</div>
362:         #{m[2]}"
363:     else
364:       b = body
365:     end
366:     return b
367:   end

Formatea las fechas para mostrar al público

[Source]

     # File app/models/event.rb, line 318
318:   def pretty_dates(locale=I18n.locale)
319:     if starts_at.eql?(ends_at)
320:       if starts_at.strftime('%H%M') == "0000"
321:         # Remove hour if it is scheduled for midnight
322:         I18n.localize(starts_at.to_date, :format => :long, :locale => locale)
323:       else
324:         I18n.localize(starts_at, :format => :long, :locale => locale)
325:       end
326:     elsif starts_at.to_date.eql?(ends_at.to_date)
327:       # Same day, different hours
328:       "#{I18n.localize(starts_at.to_date, :format => :long, :locale => locale)}, #{starts_at.strftime('%H:%M')} - #{ends_at.strftime('%H:%M')}" 
329:     else
330:       # Different dates
331:       start_date = starts_at.strftime('%H%M') == "0000" ? I18n.localize(starts_at.to_date, :format => :long, :locale => locale) : I18n.localize(starts_at, :format => :long, :locale => locale)
332:       end_date = ends_at.strftime('%H%M') == "0000" ? I18n.localize(ends_at.to_date, :format => :long, :locale => locale) : I18n.localize(ends_at, :format => :long, :locale => locale)
333:       "#{start_date} - #{end_date}"
334:     end
335:   end

Formatea las horas para mostrar en la vista semanal de la administración de la agenda

[Source]

     # File app/models/event.rb, line 338
338:   def pretty_hours(locale=I18n.locale)
339:     if starts_at.to_date.eql?(ends_at.to_date)
340:       # Same day, different hours
341:       "#{starts_at.strftime('%H:%M')} - #{ends_at.strftime('%H:%M')}" 
342:     else
343:       # Different dates
344:       start_date = starts_at.strftime('%H%M') == "0000" ? I18n.localize(starts_at.to_date, :format => :long, :locale => locale) : I18n.localize(starts_at, :format => :long, :locale => locale)
345:       end_date = ends_at.strftime('%H%M') == "0000" ? I18n.localize(ends_at.to_date, :format => :long, :locale => locale) : I18n.localize(ends_at, :format => :long, :locale => locale)
346:       "#{start_date} - #{end_date}"
347:     end    
348:   end

Formatea el lugar donde ocurre el evento

[Source]

     # File app/models/event.rb, line 351
351:   def pretty_place
352:     full_info = [self.place, self.city].map {|e| e.blank? ? nil : e }.compact
353:     full_info.empty? ? "" : full_info.join(", ")
354:   end

Devuelve 1 si el evento es privado y 0 en el caso contrario.

[Source]

     # File app/models/event.rb, line 412
412:   def private_event
413:     self.is_private? ? 1 : 0
414:   end

 Llama el método is_private con argumento val.

[Source]

     # File app/models/event.rb, line 417
417:   def private_event=(val)
418:     self.is_private = val.to_i.eql?(1)
419:   end

Indica si el evento está publicado en Irekia

[Source]

     # File app/models/event.rb, line 370
370:   def published?
371:     (!self.draft?) && (self.show_in_irekia || self.show_in_agencia) && self.confirmed? && (published_at <= Time.zone.now)
372:   end

Indica si el evento está publicado en Irekia

[Source]

     # File app/models/event.rb, line 375
375:   def published_in_agencia?
376:      self.published? && self.show_in_agencia && (self.starts_at <= (Time.zone.now + 3.days))
377:   end

Programa las alertas que se deberán enviar relativas a este evento. Hay dos tipos de alertas

  • Alertas para periodistas: Cada vez que un campo relevante del evento de la agencia cambia (fecha, lugar, visibilidad…), se envía un email notificándolo. Se envían 3 días antes de su comienzo
  • Alertas para operadores de streaming y responsables de salas: Cuando se confirma el streaming para un evento, se envían alertas a los operadores de streaming, responsables de sala, y creador del evento para que preparen lo necesario para el streaming. Se envian 1 día antes de que comiencen

[Source]

     # File app/models/event.rb, line 224
224:   def schedule_alerts
225:     if self.starts_at_changed? || self.ends_at_changed? || self.place_changed? || self.state_changed?  || self.show_in_agencia_changed? || deleted_changed?
226:       self.journalist_alert_version += 1
227:       
228:       EventAlert.delete_all(["spammable_type = ? AND event_id= ? AND sent_at IS NULL", 'Journalist', self.id])
229:       event_department_id = self.organization.is_a?(Department) ? self.organization_id : self.organization.department.id
230:       Subscription.active.with_alerts.find(:all, :conditions => "subscriptions.department_id = #{event_department_id}").each do |subscription|
231:         create_alert = false
232:         last_sent_alert = EventAlert.find(:first, 
233:           :conditions => ["event_id = ? AND spammable_id = ? AND spammable_type = ?", self.id, subscription.user_id, "Journalist"], 
234:           :order => "sent_at DESC")
235:         if !last_sent_alert 
236:           if self.confirmed? && self.published_in_agencia?
237:             create_alert = true
238:             alert_send_at = self.starts_at - 3.days
239:           end
240:         else
241:           create_alert = true
242:           if self.draft?
243:             alert_send_at = self.starts_at - 3.days 
244:           else
245:             alert_send_at = Time.zone.now
246:           end
247:         end
248:         if create_alert
249:           # logger.info "Creando alerta para periodista"
250:           self.alerts.build(:spammable_id => subscription.user_id, :spammable_type => "Journalist", :version => self.journalist_alert_version, :send_at => alert_send_at)
251:         end
252:       end
253:     end
254:     
255:     if self.starts_at_changed? || self.ends_at_changed? || self.place_changed? || self.state_changed? || streaming_live_changed? || deleted_changed?
256:       self.staff_alert_version += 1
257:       
258:       EventAlert.delete_all(["spammable_type <> ? AND event_id= ? AND sent_at IS NULL", 'Journalist', self.id])
259:       this_event_alert_recipients = StreamingOperator.find(:all)
260:       this_event_alert_recipients << User.find(self.created_by) if self.created_by
261:       if self.stream_flow
262:         this_event_alert_recipients = this_event_alert_recipients + self.stream_flow.room_managers
263:       end
264:       this_event_alert_recipients.each do |recipient|
265:         create_alert = false
266:         last_sent_alert = EventAlert.find(:first, :conditions => ["event_id = ? AND spammable_id = ? AND spammable_type = ?", self.id, recipient.id, recipient.class.to_s], :order => "sent_at DESC")
267:         if !last_sent_alert
268:           if self.confirmed? && self.published_in_agencia? && self.streaming_live?
269:             create_alert = true
270:             alert_send_at = self.starts_at - 1.day
271:           end
272:         else
273:           create_alert = true
274:           if self.draft?
275:             alert_send_at = self.starts_at - 1.days 
276:           else
277:             alert_send_at = Time.zone.now
278:           end
279:         end
280:         if create_alert
281:           # logger.info "Creando alerta para #{recipient.class.to_s}"
282:           self.alerts.build(:spammable_id => recipient.id, :spammable_type => recipient.class.to_s, :version => self.staff_alert_version, :send_at => alert_send_at)
283:         end
284:       end
285:     end
286:   end

El schedule_id es nil para los evento compartidos.

[Source]

     # File app/models/event.rb, line 531
531:   def schedule_id
532:     nil
533:   end

Aunque se le asigne un valor desde el formulario, un evento comprtido siempre tiene schedule_id = nil

[Source]

     # File app/models/event.rb, line 536
536:   def schedule_id=(val)
537:     @schedule_id = nil
538:     true
539:   end

[Source]

     # File app/models/event.rb, line 526
526:   def schedule_name
527:     Event.schedule_name
528:   end

Programa el tweet referente a este evento, si está publicado y se muestra en Irekia. Se tweetea 3 días antes de su comienzo.

[Source]

     # File app/models/event.rb, line 291
291:   def schedule_tweets
292:     # Primero borramos los tweets pendientes de este evento, por si ha cambiado la fecha
293:     DocumentTweet.delete_all(["document_id= ? AND tweeted_at IS NULL", self.id])
294: 
295:     Event::LANGUAGES.each do |l|
296:       if self.published? && self.show_in_irekia? && self.translated_to?(l) && !DocumentTweet.exists?(:document_id => self.id, :tweet_locale => l)
297:         self.tweets.build(:tweet_account => "irekia_agenda", :tweet_at => self.starts_at - 3.days, :tweet_locale => l)
298:       end
299:     end
300:   end

Asigna el valor del campo draft. Si el evento es privado, draft = true. Si el evento es público, el valor de draft es true si el evento no está confirmado y false si el evento está confirmado.

[Source]

     # File app/models/event.rb, line 176
176:   def set_draft_value
177:     if self.is_private?
178:       self.draft = true
179:     else
180:       self.draft = !self.state.eql?("confirmado")
181:     end
182:     return true
183:   end

 Asigna el valor por defecto del campo l_attends si este no tiene ningún valor asignado.

[Source]

     # File app/models/event.rb, line 167
167:   def set_l_attends
168:     self.l_attends ||= false
169:     true
170:   end

Pone el valor correcto para publication_date a partir del valor de otros atributos. Se llama desde before_save

[Source]

     # File app/models/event.rb, line 148
148:   def set_publication_date
149:     if self.is_private?
150:       self.published_at = nil
151:     else
152:       if self.show_in_agencia? && !self.show_in_irekia?
153:         self.published_at = self.starts_at - 3.days
154:       else
155:         if self.show_in_irekia? && self.confirmed?
156:           self.published_at = Time.zone.now
157:         else
158:           self.published_at = nil
159:         end
160:       end
161:     end
162:     return true
163:   end

Los eventos no se pueden eliminar completamente si se han enviado alertas sobre su presencia, hasta que no se envia otra alerta sobre su eliminación. Cuando se marca como eliminado, se pasa a borrador para que deje de aparecer en la parte pública. Se llama desde before_save

[Source]

     # File app/models/event.rb, line 190
190:   def set_to_draft_if_deleted
191:     # asi nos aseguramos de que no aparecera en la parte publica
192:     self.draft = true if self.deleted?
193:     return true
194:   end

Devuelve el nombre de la sección donde sale el evento en Irekia.

[Source]

     # File app/models/event.rb, line 434
434:   def show_in
435:     res = ""
436:     for i in Event.show_in_opts
437:       res = i if self.tag_list.include?("Irekia::#{i.capitalize}")
438:     end    
439:     res
440:   end

Asigna el Tag correspondiente a la sección de Irekia donde sale el evento. El valor que se pasa tiene que ser alguna de las opciones que devuelve el método show_in_opts.

[Source]

     # File app/models/event.rb, line 454
454:   def show_in=(val)
455:     if Event.show_in_opts.include?(val)
456:       self.tag_list = self.tag_list - Event.show_in_opts.map {|opt| "Irekia::#{opt.capitalize}"}
457:       self.tag_list << "Irekia::#{val.capitalize}"
458:     end
459:   end

 Fecha de inicio del evento para Ferret. Los eventos en la agencia se pueden ver 3 dias antes de que empiecen,  por eso ponemos como fecha de inicio, 3 días antes.

[Source]

     # File app/models/event.rb, line 509
509:   def starts_at_in_agencia_for_ferret
510:     (self.starts_at - 3.days).to_s(:number)
511:   end

Comprueba que se que especifica la sala de streaming, en caso de que vaya a haberlo

[Source]

    # File app/models/event.rb, line 66
66:   def streaming_room
67:     if self.streaming_live && !self.stream_flow_id
68:       errors.add :streaming_live, "Debes elegir la sala"
69:     end
70:   end

Asegura que no tiene sala de streaming si no hay streaming

[Source]

     # File app/models/event.rb, line 304
304:   def sync_streaming_and_room
305:     if !self.streaming_live
306:       self.stream_flow_id = nil
307:     else
308:       return true
309:     end
310:   end

Devuelve el evento en formato ical

[Source]

     # File app/models/event.rb, line 462
462:   def to_ics(cal, &block)
463:     if self.deleted?
464:       cal.add_x_property('METHOD', 'CANCEL')
465:     else
466:       cal.add_x_property('METHOD', 'REQUEST')
467:     end
468:     cal.event do |event|
469:       event.uid = "uid_" + self.id.to_s + "irekia_euskadi_net"
470:       event.sequence = self.staff_alert_version
471:       event.summary = self.title
472:       event.description = self.description_for_ics
473:       event.dtstart =  self.starts_at.getutc.strftime("%Y%m%dT%H%M%SZ")
474:       event.dtend = self.ends_at.getutc.strftime("%Y%m%dT%H%M%SZ")
475:       event.location = self.pretty_place
476:       event.url = yield[:url] if block.present?
477:       event.created = self.created_at.getutc.strftime("%Y%m%dT%H%M%SZ")
478:       event.last_modified = self.updated_at.getutc.strftime("%Y%m%dT%H%M%SZ")
479:       event.dtstamp = Time.now.getutc.strftime("%Y%m%dT%H%M%SZ")
480:       if self.deleted?
481:         event.status = "CANCELLED"
482:       elsif self.confirmed?
483:         event.status = "TENTATIVE"
484:       else
485:         event.status = "CONFIRMED"
486:       end
487:     end
488:   end

Indica si el evento está traducido a lang_code Los idiomas disponibles son Document::LANGUAGES

[Source]

     # File app/models/event.rb, line 97
 97:   def translated_to?(lang_code)
 98:     translated = self.send("title_#{lang_code}").present? 
 99:     unless self.send("body_#{I18n.default_locale}").blank?
100:       # Los eventos pueden no tener body en ningun idioma
101:       translated = translated && self.send("body_#{lang_code}").present?
102:     end
103:     return translated
104:   end

Indica si el evento se puede cambiar de privado a público y vice versa.

[Source]

     # File app/models/event.rb, line 544
544:   def visibility_can_change?
545:     true
546:   end

Crea una lista con los sitios donde este evento es visible.

[Source]

    # File app/models/event.rb, line 73
73:   def visible_in
74:     show_in = []
75:     show_in << "private" if self.is_private?
76:     show_in << "irekia" if self.show_in_irekia?
77:     show_in << "agencia" if self.show_in_agencia?
78:     return show_in
79:   end

[Validate]