Homework: Ruby Block

Submitted by swarut on Mon, 07/02/2012 - 17:14

Here is a comment on the branch I was working on a few weeks ago.

RiCal.Calendar et al use instance_eval, so calling to_ics methods from such contexts resulted in idiomatic usage of opts.delete(:foo) bleeding the mutation into the calling scope. This meant that calling in a loop such as opts = { user: user } items.each { item.to_ics(opts) } resulted in the user k/v being absent after the first iteration.

I did not understand it much, especially it is about the block which is the concept that I do not understand it well.

  1. # Provides an iCalendar VEVENT representation of the decorated Event, by way
  2.   # of RiCal.
  3.   #
  4.   # @param opts [Hash] A customizable set of options.
  5.   # @options opts [User] :user The user for whom the ICS is being rendered, so
  6.   #   we can only set a VALARM if he or she has submitted an affirmative RSVP
  7.   #   for the Event.
  8.   #
  9.   # @return [RiCal::Component::Event] the Event represented as an RiCal
  10.   #   component object. You may call {RiCal::Compenent#export} on the resulting
  11.   #   object in order to get a String representation that includes requisite
  12.   #   wrappers for iCalendar spec compliance, such as a VCALENDAR.
  13.   #
  14.   # TODO: add test to check for rsvp event
  15.   def to_ics(opts={})
  16.     opts = opts.dup
  17.     user = opts.delete(:user)
  18.  
  19.     RiCal.Event do |ev|
  20.       ev.uid              = ical_uid
  21.       ev.created          = event.created_at.to_date
  22.       ev.last_modified    = event.updated_at.to_date
  23.       ev.description      = event.description if event.description
  24.       ev.dtstart          = event.starts_at
  25.       ev.dtend            = event.ends_at
  26.       ev.location         = event.decorate.location
  27.  
  28.       # TODO: format correctly if speaker/speaker title missing
  29.       if event.has_speaker?
  30.         ev.summary        = "#{event.title} by #{event.speaker_title} #{event.speaker_name}"
  31.       else
  32.         ev.summary        = event.title
  33.       end
  34.  
  35.       # TODO: move this RSVP check to a model method
  36.       if user && user.wants_ical_reminders? && event.rsvps.where{user_id.eq(user.id) & joining.in(['Y', 'M'])}.any?
  37.         ev.alarm do |alarm|
  38.           alarm.description           = "#{event.title}"
  39.           alarm.trigger               = ":-PT#{user.decorate.ical_reminder_offset}"
  40.           alarm.action                = "DISPLAY"
  41.         end
  42.       end
  43.     end
  44.   end

Must research this more.