Migrating solution to Rails 3.1 #2

Closed
foncho opened this Issue Nov 29, 2011 · 2 comments

Comments

Projects
None yet
2 participants

foncho commented Nov 29, 2011

Hi dudes!

I'm tryin' to migrate your amazing solution to Rails 3.1, but I've found a problem when I want to create a recurring event: is not creating the events, but yes is creating the event_series.

I think that the issue is in the create.js.erb (I have had to migrate it in order to use jQuery properly) mixed with the events#create controller, and I think the solution is use a loop, but it's also extremely not efficient, so I only need some guideline to migrate properly this issue in particular.

Thanks folks! This calendar really rules!

FoN

Any luck with this?

foncho commented Jan 11, 2012

Oh! Yes, sorry for not answering before...

Rails 3.1 allows you to insert only one item at once into your database, so you need to manually tell him that not passed the nested validation through self.events.new(:some_attributes).save(:validate => false). Four days to figure it out, because the nested insertion ban is a new feature in this version, due to security reasons (via Rails 3.1 specifications).

I also have got to integrate your solution with IceCube gem (great solution for recurrence calculations). Here I put the code I develop for that, I hope you find it useful:

# encoding: UTF-8

class EventSeries < ActiveRecord::Base
  include IceCube
  attr_accessor :title, :description, :event_series_id, :commit_button
  attr_accessible :id, :title, :description, :frequency, :period, :starts_at, :ends_at, :event_series_id, :commit_button

  validates :frequency, :presence => :true
  validates :period, :presence => true
  validates :starts_at, :presence => true
  validates :ends_at, :presence => true
  validates :title, :presence => true
  validates :description, :presence => true

  has_many :events, :dependent => :destroy
  accepts_nested_attributes_for :events

  before_save :generate_recurrence

  def generate_recurrence
    days = number_of_days
    if period.to_i == days.count
      create_events_until(END_TIME)
    else
      self.errors.add :period, "Repeats and number of days selected are not the same. Please, fix it and try it out again."
    end
  end

  def create_events_until(end_time)
    start = starts_at
    final = ends_at
    new_starts_at, new_ends_at = start, final
    schedule = IceCube::Schedule.new(start.to_time, :end_time => end_time)

    # Generate the schedule and the recurrence rules
    number_of_days.each do |day|
      if day.downcase.include?('mon') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(1) end
      if day.downcase.include?('tue') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(2) end
      if day.downcase.include?('wed') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(3) end
      if day.downcase.include?('thu') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(4) end
      if day.downcase.include?('fri') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(5) end
      if day.downcase.include?('sat') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(6) end
      if day.downcase.include?('sun') then schedule.add_recurrence_rule IceCube::Rule.weekly.day(7) end
    end

    # Insert all the occurrence into the database individually, passing over the Rails-3.1's nested insertions ban
    occurrences = schedule.all_occurrences
    occurrences.each do |occurrence|
      self.events.new(
        :title => title,
        :description => description,
        :event_series_id => id,
        :starts_at => occurrence,
        :ends_at => occurrence + 1.hour
      ).save(:validate => false)
    end
  end

  def number_of_days
    days = []
    frequency.each do |item|
      # Taking out only the not null elements
      unless item.nil? or item == '' 
        days << item
      end
    end
    return days
  end
end

Thx...

foncho closed this Feb 3, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment