Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
How I built a rails interface on top of the amazing IceCube ruby gem. Video of final product: http://youtu.be/F6t-USuWPag
= bootstrap_form_for @event, html: {class: 'form-horizontal', novalidate: 'novalidate'} do |f|
.row
.span6
= f.text_field :name, class: 'span4'
= f.text_area :description, class: 'span4', rows: 5
= f.select :location_id, options_from_collection_for_select(Place.all, 'id', 'name', f.object.location_id), include_blank: true
= f.select :host_id, options_from_collection_for_select(Place.all, 'id', 'name', f.object.host_id), include_blank: true
.span6
= f.check_box :is_all_day
= f.date_select :from_date, {}, {style: 'width:auto;'}
.event_time
= f.time_select :from_time, {:minute_step => 15}, {style: 'width:auto;'}
= f.date_select :to_date, {}, {style: 'width:auto;'}
.event_time
= f.time_select :to_time, {:minute_step => 15}, {style: 'width:auto;'}
.event_time
= f.time_zone_select :time_zone, ActiveSupport::TimeZone.us_zones, :default => "Central Time (US & Canada)"
= f.select :repeats, Event::RepeatsOptions
= render partial: 'repeats_daily_options', locals: {f: f}
= render partial: 'repeats_weekly_options', locals: {f: f}
= render partial: 'repeats_monthly_options', locals: {f: f}
= render partial: 'repeats_yearly_options', locals: {f: f}
#repeats_options.event_option
= f.select :repeat_ends, Event::RepeatEndsOptions
#event_repeat_ends_on
= f.date_select :repeat_ends_on, {}, {style: 'width:auto;'}
.form-actions
= f.submit 'Save'
- content_for :last_javascripts do
:javascript
$(function() {
var toggle_repeats_yearly_on = function(){
if($('#event_repeats_yearly_on').is(':checked')){
$('#event_repeats_yearly_on_options').show();
} else {
$('#event_repeats_yearly_on_options').hide();
}
}
toggle_repeats_yearly_on();
$('#event_repeats_yearly_on').on('change',function(){
toggle_repeats_yearly_on();
});
var toggle_event_times = function(){
if($('#event_is_all_day').is(':checked')){
$('.event_time').hide();
} else {
$('.event_time').show();
}
}
toggle_event_times();
$('#event_is_all_day').on('change',function(){
toggle_event_times();
});
var toggle_event_options = function(){
$('.event_option').hide();
switch ($('#event_repeats').val())
{
case 'never':
// Nothing
break;
case 'daily':
$('#repeats_options').show();
$('#repeats_daily_options').show();
break;
case 'weekly':
$('#repeats_options').show();
$('#repeats_weekly_options').show();
break;
case 'monthly':
$('#repeats_options').show();
$('#repeats_monthly_options').show();
break;
case 'yearly':
$('#repeats_options').show();
$('#repeats_yearly_options').show();
break;
}
}
toggle_event_options();
$('#event_repeats').on('change',function(){
toggle_event_options();
});
var toggle_repeat_ends_on = function(){
switch ($('#event_repeat_ends').val())
{
case 'never':
$('#event_repeat_ends_on').hide();
break;
case 'on':
$('#event_repeat_ends_on').show();
break;
}
}
toggle_repeat_ends_on();
$('#event_repeat_ends').on('change',function(){
toggle_repeat_ends_on();
});
var toggle_repeats_monthly = function(){
switch ($('#event_repeats_monthly').val())
{
case 'each':
$('#event_repeats_monthly_each').show();
$('#event_repeats_monthly_on').hide();
break;
case 'on':
$('#event_repeats_monthly_each').hide();
$('#event_repeats_monthly_on').show();
break;
}
}
toggle_repeats_monthly();
$('#event_repeats_monthly').on('change',function(){
toggle_repeats_monthly();
});
});
- content_for :first_styles do
:css
#repeats_options {display:none;}
#repeats_daily_options {display:none;}
#repeats_weekly_options {display:none;}
#repeats_monthly_options {display:none;}
#repeats_yearly_options {display:none;}
%fieldset{id: 'repeats_daily_options', class: 'event_option'}
= f.number_field :repeats_every_n_days
%fieldset{ id: 'repeats_monthly_options', class: 'event_option'}
= f.number_field :repeats_every_n_months
= f.select :repeats_monthly, Event::RepeatMonthlyOptions
#event_repeats_monthly_each.control-group
%label.control-label Each
.controls
- Event::DaysOfTheMonth.each do |day_of_the_month|
= label_tag "event_repeats_monthly_each_days_of_the_month_#{day_of_the_month}", day_of_the_month, :class => 'checkbox inline' do
= check_box_tag "event[repeats_monthly_each_days_of_the_month][#{day_of_the_month}]", day_of_the_month, f.object.repeats_monthly_each_days_of_the_month.include?(day_of_the_month), {:name => "event[repeats_monthly_each_days_of_the_month][]"}
= day_of_the_month
= hidden_field_tag "event[repeats_monthly_each_days_of_the_month][]", ""
#event_repeats_monthly_on.control-group
%label.control-label On the
.controls
- Event::Ordinals.each_with_index do |ordinal,index|
= label_tag "event_repeats_monthly_on_ordinals_#{ordinal}", ordinal, :class => 'checkbox inline' do
= check_box_tag "event[repeats_monthly_on_ordinals][#{ordinal}]", ordinal, f.object.repeats_monthly_on_ordinals.include?(ordinal), {:name => "event[repeats_monthly_on_ordinals][]"}
= Event::HumanOrdinals[index]
= hidden_field_tag "event[repeats_monthly_on_ordinals][]", ""
%hr
- Event::DaysOfTheWeek.each do |day_of_the_week|
= label_tag "event_repeats_monthly_on_days_of_the_week_#{day_of_the_week}", day_of_the_week.humanize, :class => 'checkbox inline' do
= check_box_tag "event[repeats_monthly_on_days_of_the_week][#{day_of_the_week}]", day_of_the_week, f.object.repeats_monthly_on_days_of_the_week.include?(day_of_the_week), {:name => "event[repeats_monthly_on_days_of_the_week][]"}
= day_of_the_week.humanize
= hidden_field_tag "event[repeats_monthly_on_days_of_the_week][]", ""
%fieldset{ id: 'repeats_weekly_options', class: 'event_option'}
= f.number_field :repeats_every_n_weeks
.control-group
%label.control-label Each
.controls
- Event::DaysOfTheWeek.each do |day_of_the_week|
= label_tag "event_repeats_weekly_each_days_of_the_week_#{day_of_the_week}", day_of_the_week.humanize, :class => 'checkbox inline' do
= check_box_tag "event[repeats_weekly_each_days_of_the_week][#{day_of_the_week}]", day_of_the_week, f.object.repeats_weekly_each_days_of_the_week.include?(day_of_the_week), {:name => "event[repeats_weekly_each_days_of_the_week][]"}
= day_of_the_week.humanize
= hidden_field_tag "event[repeats_weekly_each_days_of_the_week][]", ""
%fieldset{ id: 'repeats_yearly_options', class: 'event_option'}
= f.number_field :repeats_every_n_years
.control-group
%label.control-label Each
.controls
- Event::MonthsOfTheYear.each do |month_of_the_year|
= label_tag "event_repeats_yearly_each_months_of_the_year_#{month_of_the_year}", month_of_the_year.humanize, :class => 'checkbox inline' do
= check_box_tag "event[repeats_yearly_each_months_of_the_year][#{month_of_the_year}]", month_of_the_year, f.object.repeats_yearly_each_months_of_the_year.include?(month_of_the_year), {:name => "event[repeats_yearly_each_months_of_the_year][]"}
= month_of_the_year.humanize
= hidden_field_tag "event[repeats_yearly_each_months_of_the_year][]", ""
= f.check_box :repeats_yearly_on
#event_repeats_yearly_on_options.control-group
%label.control-label On the
.controls
- Event::Ordinals.each_with_index do |ordinal,index|
= label_tag "event_repeats_yearly_on_ordinals_#{ordinal}", ordinal, :class => 'checkbox inline' do
= check_box_tag "event[repeats_yearly_on_ordinals][#{ordinal}]", ordinal, f.object.repeats_yearly_on_ordinals.include?(ordinal), {:name => "event[repeats_yearly_on_ordinals][]"}
= Event::HumanOrdinals[index]
= hidden_field_tag "event[repeats_yearly_on_ordinals][]", ""
%hr
- Event::DaysOfTheWeek.each do |day_of_the_week|
= label_tag "event_repeats_yearly_on_days_of_the_week_#{day_of_the_week}", day_of_the_week.humanize, :class => 'checkbox inline' do
= check_box_tag "event[repeats_yearly_on_days_of_the_week][#{day_of_the_week}]", day_of_the_week, f.object.repeats_yearly_on_days_of_the_week.include?(day_of_the_week), {:name => "event[repeats_yearly_on_days_of_the_week][]"}
= day_of_the_week.humanize
= hidden_field_tag "event[repeats_yearly_on_days_of_the_week][]", ""
#calendar{:style => 'margin:1em 0;'}
- content_for :last_javascripts do
:javascript
$('#calendar').fullCalendar({
eventSources: [
// your event source
{
url: '/event_instances.json',
data: {
custom_param1: 'something',
custom_param2: 'somethingelse'
},
error: function() {
alert('there was an error while fetching events!');
}
}
// any other sources...
]
});
class Event < ActiveRecord::Base
include IceCubeMethods
# My custom attributes. Modify to suite your needs.
# attr_accessible :description, :name, :host_id, :location_id
# validates :name, :presence => true
# validates :host_id, :presence => true
# validates :location_id, :presence => true
# belongs_to :host, :class_name => 'Place'
# belongs_to :location, :class_name => 'Place'
end
class EventInstance
include ActiveModel::AttributeMethods
attr_accessor :title, :start, :end, :allDay, :event_id
def self.occurrences_between(begin_date,end_date)
# Using Squeel
# line 1 = Event doesn't repeat, but ends in window
# line 2 = Event doesn't repeat, but starts in window
# line 2 = Event doesn't repeat, but starts before and ends after
# line 4 = Event starts before our end date and repeats until a certain point of time, and that point of time after our begin date
# line 5 = Event repeats indefinitely, then all we care about is that it has started at somepoint in the last
results = Event.where{
(
(repeats == 'never') &
(from_date >= begin_date) &
(from_date <= end_date)
) | (
(repeats == 'never') &
(to_date >= begin_date) &
(to_date <= end_date)
) | (
(repeats == 'never') &
(from_date <= begin_date) &
(to_date >= end_date)
) | (
(repeats != 'never') &
(from_date <= end_date) &
(repeat_ends == 'on') &
(repeat_ends_on >= begin_date)
) | (
(repeats != 'never') &
(repeat_ends == 'never') &
(from_date <= end_date)
)
}
results.map { |event|
event.schedule.occurrences_between(begin_date,end_date).map { |date|
i = EventInstance.new()
i.title = event.name
i.start = date
i.end = date + event.duration
i.allDay = event.is_all_day
i.event_id = event.id
i
}
}.flatten.sort! {|x,y| x.start <=> y.start }
end
end
class EventInstancesController < ApplicationController
# GET /events
# GET /events.json
def index
@event_instances = EventInstance.occurrences_between(Date.parse('2013-01-01'),Date.parse('2013-04-30'))
respond_to do |format|
format.html # index.html.erb
format.json { render json: @event_instances }
end
end
end
# Add these two gems
gem 'ice_cube', '0.9.3'
gem 'squeel', '1.0.16'
module IceCubeMethods
def self.included(base)
base.send :attr_accessible, :from_date
base.send :attr_accessible, :from_time
base.send :attr_accessible, :to_date
base.send :attr_accessible, :to_time
base.send :attr_accessible, :is_all_day
base.send :attr_accessible, :repeat_ends
base.send :attr_accessible, :repeat_ends_on
base.send :attr_accessible, :repeats
base.send :attr_accessible, :repeats_every_n_days
base.send :attr_accessible, :repeats_every_n_weeks
base.send :attr_accessible, :repeats_weekly_each_days_of_the_week
base.send :attr_accessible, :repeats_every_n_months
base.send :attr_accessible, :repeats_monthly
base.send :attr_accessible, :repeats_monthly_each_days_of_the_month
base.send :attr_accessible, :repeats_monthly_on_days_of_the_week
base.send :attr_accessible, :repeats_monthly_on_ordinals
base.send :attr_accessible, :repeats_every_n_years
base.send :attr_accessible, :repeats_yearly_each_months_of_the_year
base.send :attr_accessible, :repeats_yearly_on
base.send :attr_accessible, :repeats_yearly_on_days_of_the_week
base.send :attr_accessible, :repeats_yearly_on_ordinals
base.send :attr_accessible, :time_zone
base.send :validates, :repeats, :presence => true
base.send :validates, :repeats_every_n_days, :presence => true, :if => lambda { |e| e.repeats == "daily" }
base.send :validates, :repeats_every_n_weeks, :presence => true, :if => lambda { |e| e.repeats == "weekly" }
base.send :validate, :must_have_at_least_one_repeats_weekly_each_days_of_the_week, :if => lambda { |e| e.repeats == "weekly" }
base.send :validates, :repeats_every_n_months, :presence => true, :if => lambda { |e| e.repeats == "monthly" }
base.send :validates, :repeats_monthly, :presence => true, :if => lambda { |e| e.repeats == "monthly" }
base.send :validate, :must_have_at_least_one_repeats_monthly_each_days_of_the_month, :if => lambda { |e| e.repeats == "monthly" && e.repeats_monthly == 'each' }
base.send :validate, :must_have_at_least_one_repeats_monthly_on_ordinals, :if => lambda { |e| e.repeats == "monthly" && e.repeats_monthly == 'on' }
base.send :validate, :must_have_at_least_one_repeats_monthly_on_days_of_the_week, :if => lambda { |e| e.repeats == "monthly" && e.repeats_monthly == 'on' }
base.send :validates, :repeats_every_n_years, :presence => true, :if => lambda { |e| e.repeats == "yearly" }
base.send :validate, :must_have_at_least_one_repeats_yearly_each_months_of_the_year, :if => lambda { |e| e.repeats == "yearly" }
base.send :validate, :must_have_at_least_one_repeats_yearly_on_ordinals, :if => lambda { |e| e.repeats == "yearly" && e.repeats_yearly_on }
base.send :validate, :must_have_at_least_one_repeats_yearly_on_days_of_the_week, :if => lambda { |e| e.repeats == "yearly" && e.repeats_yearly_on }
base.send :validate, :from_must_come_before_to
end
RepeatsOptions = ['never','daily','weekly','monthly','yearly']
RepeatEndsOptions = ['never','on']
RepeatMonthlyOptions = ['each','on']
DaysOfTheWeek = %w[sunday monday tuesday wednesday thursday friday saturday]
DaysOfTheMonth = (1..31).to_a
Ordinals = [1,2,3,4,-1]
HumanOrdinals = ['first','second','third','fourth','last']
MonthsOfTheYear = %w[january february march april may june july august september october november december]
def repeats_weekly_each_days_of_the_week=(repeats_weekly_each_days_of_the_week)
self.repeats_weekly_each_days_of_the_week_mask = (repeats_weekly_each_days_of_the_week & DaysOfTheWeek).map { |r| 2**DaysOfTheWeek.index(r) }.inject(0, :+)
end
def repeats_weekly_each_days_of_the_week
DaysOfTheWeek.reject do |r|
((repeats_weekly_each_days_of_the_week_mask || 0) & 2**DaysOfTheWeek.index(r)).zero?
end
end
def repeats_monthly_each_days_of_the_month=(repeats_monthly_each_days_of_the_month)
repeats_monthly_each_days_of_the_month.map!{|d| d.to_i} # They come in as strings, but our array is full of integers
self.repeats_monthly_each_days_of_the_month_mask = (repeats_monthly_each_days_of_the_month & DaysOfTheMonth).map { |r| 2**DaysOfTheMonth.index(r) }.inject(0, :+)
end
def repeats_monthly_each_days_of_the_month
DaysOfTheMonth.reject do |r|
((repeats_monthly_each_days_of_the_month_mask || 0) & 2**DaysOfTheMonth.index(r)).zero?
end
end
def repeats_monthly_on_ordinals=(repeats_monthly_on_ordinals)
repeats_monthly_on_ordinals.map!{|o| o.to_i} # They come in as strings, but our array is full of integers
self.repeats_monthly_on_ordinals_mask = (repeats_monthly_on_ordinals & Ordinals).map { |r| 2**Ordinals.index(r) }.inject(0, :+)
end
def repeats_monthly_on_ordinals
Ordinals.reject do |r|
((repeats_monthly_on_ordinals_mask || 0) & 2**Ordinals.index(r)).zero?
end
end
def repeats_monthly_on_days_of_the_week=(repeats_monthly_on_days_of_the_week)
self.repeats_monthly_on_days_of_the_week_mask = (repeats_monthly_on_days_of_the_week & DaysOfTheWeek).map { |r| 2**DaysOfTheWeek.index(r) }.inject(0, :+)
end
def repeats_monthly_on_days_of_the_week
DaysOfTheWeek.reject do |r|
((repeats_monthly_on_days_of_the_week_mask || 0) & 2**DaysOfTheWeek.index(r)).zero?
end
end
def repeats_yearly_each_months_of_the_year=(repeats_yearly_each_months_of_the_year)
self.repeats_yearly_each_months_of_the_year_mask = (repeats_yearly_each_months_of_the_year & MonthsOfTheYear).map { |r| 2**MonthsOfTheYear.index(r) }.inject(0, :+)
end
def repeats_yearly_each_months_of_the_year
MonthsOfTheYear.reject do |r|
((repeats_yearly_each_months_of_the_year_mask || 0) & 2**MonthsOfTheYear.index(r)).zero?
end
end
def repeats_yearly_on_ordinals=(repeats_yearly_on_ordinals)
repeats_yearly_on_ordinals.map!{|o| o.to_i} # They come in as strings, but our array is full of integers
self.repeats_yearly_on_ordinals_mask = (repeats_yearly_on_ordinals & Ordinals).map { |r| 2**Ordinals.index(r) }.inject(0, :+)
end
def repeats_yearly_on_ordinals
Ordinals.reject do |r|
((repeats_yearly_on_ordinals_mask || 0) & 2**Ordinals.index(r)).zero?
end
end
def repeats_yearly_on_days_of_the_week=(repeats_yearly_on_days_of_the_week)
self.repeats_yearly_on_days_of_the_week_mask = (repeats_yearly_on_days_of_the_week & DaysOfTheWeek).map { |r| 2**DaysOfTheWeek.index(r) }.inject(0, :+)
end
def repeats_yearly_on_days_of_the_week
DaysOfTheWeek.reject do |r|
((repeats_yearly_on_days_of_the_week_mask || 0) & 2**DaysOfTheWeek.index(r)).zero?
end
end
def from
if is_all_day
ActiveSupport::TimeZone[time_zone].parse(from_date.to_datetime.strftime('%Y-%m-%d')).beginning_of_day
else
ActiveSupport::TimeZone[time_zone].parse(from_date.to_datetime.strftime('%Y-%m-%d')).beginning_of_day + from_time.seconds_since_midnight
end
end
def to
if is_all_day
ActiveSupport::TimeZone[time_zone].parse(to_date.to_datetime.strftime('%Y-%m-%d')).end_of_day
else
ActiveSupport::TimeZone[time_zone].parse(to_date.to_datetime.strftime('%Y-%m-%d')).beginning_of_day + to_time.seconds_since_midnight
end
end
def duration
d = to - from - 1
end
def schedule(starts_at = nil, ends_at = nil)
starts_at ||= from
ends_at ||= to
s = IceCube::Schedule.new(starts_at, :ends_time => ends_at)
case repeats
when 'never'
s.add_recurrence_time(starts_at)
when 'daily'
s.add_recurrence_rule IceCube::Rule.daily(repeats_every_n_days)
when 'weekly'
days = repeats_weekly_each_days_of_the_week.map {|d| d.to_sym }
s.add_recurrence_rule IceCube::Rule.weekly(repeats_every_n_weeks).day(*days)
when 'monthly'
case repeats_monthly
when 'each'
s.add_recurrence_rule IceCube::Rule.monthly(repeats_every_n_months).day_of_month(*repeats_monthly_each_days_of_the_month)
when 'on'
h = {}
repeats_monthly_on_days_of_the_week.each do |day_of_the_week|
h[day_of_the_week.to_sym] = repeats_monthly_on_ordinals
end
s.add_recurrence_rule IceCube::Rule.monthly(repeats_every_n_months).day_of_week(h)
end
when 'yearly'
if repeats_yearly_on
h = {}
repeats_yearly_on_days_of_the_week.each do |day_of_the_week|
h[day_of_the_week.to_sym] = repeats_yearly_on_ordinals
end
months = repeats_yearly_each_months_of_the_year.map {|m| m.to_sym }
s.add_recurrence_rule IceCube::Rule.yearly(repeats_every_n_years).month_of_year(*months).day_of_week(h)
else
months = repeats_yearly_each_months_of_the_year.map {|m| m.to_sym }
s.add_recurrence_rule IceCube::Rule.yearly(repeats_every_n_years).month_of_year(*months)
end
end
return s
end
private
def must_have_at_least_one_repeats_weekly_each_days_of_the_week
if repeats_weekly_each_days_of_the_week.empty?
errors.add(:base, "You must have at least one repeats weekly each days of the week")
end
end
def must_have_at_least_one_repeats_monthly_each_days_of_the_month
if repeats_monthly_each_days_of_the_month.empty?
errors.add(:base, "You must have at least one repeats monthly each days of the month")
end
end
def must_have_at_least_one_repeats_monthly_on_ordinals
if repeats_monthly_on_ordinals.empty?
errors.add(:base, "You must have at least one repeats monthly on ordinals")
end
end
def must_have_at_least_one_repeats_monthly_on_days_of_the_week
if repeats_monthly_on_days_of_the_week.empty?
errors.add(:base, "You must have at least one repeats monthly on days of the week")
end
end
def must_have_at_least_one_repeats_yearly_each_months_of_the_year
if repeats_yearly_each_months_of_the_year.empty?
errors.add(:base, "You must have at least one repeats yearly each months of the year")
end
end
def must_have_at_least_one_repeats_yearly_on_ordinals
if repeats_yearly_on_ordinals.empty?
errors.add(:base, "You must have at least one repeats yearly on ordinals")
end
end
def must_have_at_least_one_repeats_yearly_on_days_of_the_week
if repeats_yearly_on_days_of_the_week.empty?
errors.add(:base, "You must have at least one repeats yearly on days of the week")
end
end
def from_must_come_before_to
if from > to
errors.add(:to_date, "must come after the from date")
end
end
end
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
# My custom attributes. Modify to suite your needs.
# t.string :name
# t.text :description
# t.integer :location_id
# t.integer :host_id
# The core migration
t.boolean :is_all_day
t.date :from_date
t.time :from_time
t.date :to_date
t.time :to_time
t.string :repeats
t.integer :repeats_every_n_days
t.integer :repeats_every_n_weeks
t.integer :repeats_weekly_each_days_of_the_week_mask
t.integer :repeats_every_n_months
t.string :repeats_monthly
t.integer :repeats_monthly_each_days_of_the_month_mask
t.integer :repeats_monthly_on_ordinals_mask
t.integer :repeats_monthly_on_days_of_the_week_mask
t.integer :repeats_every_n_years
t.integer :repeats_yearly_each_months_of_the_year_mask
t.boolean :repeats_yearly_on
t.integer :repeats_yearly_on_ordinals_mask
t.integer :repeats_yearly_on_days_of_the_week_mask
t.string :repeat_ends
t.date :repeat_ends_on
t.string :time_zone
t.timestamps
end
end
end
@dgilperez

This comment has been minimized.

Copy link

commented Mar 8, 2013

Man, thanks for sharing this! Awesome work!

@rpearce

This comment has been minimized.

Copy link

commented Apr 24, 2013

well done and thanks for sharing

@mzaragoza

This comment has been minimized.

Copy link

commented Jun 12, 2013

Any chance of adding a license for this... I am adding it to a sample project I want to share on heroku and here

@mzaragoza

This comment has been minimized.

Copy link

commented Jun 12, 2013

Created a Demo of this
http://rails-fullcalendar-icecube.herokuapp.com/

Github
https://github.com/mzararagoza/rails-fullcalendar-icecube

There are some problems with repeat-ends feature not adding an exception to the schedule
Can you foward me an updated module IceCubeMethods

@jbat

This comment has been minimized.

Copy link

commented Dec 3, 2013

This is totally awesome. Great work!
+1 to the repeat-ends feature not adding an exception

Has anyone made any improvements to this?

@kleinjm

This comment has been minimized.

Copy link

commented Jul 3, 2014

Really really great work. You saved me hours of time here. Thanks a bunch!

@findchris

This comment has been minimized.

Copy link

commented Jul 16, 2014

I'd recommend you all check out this gem, which I've used. It hides most of this complexity and adds a slick UI: https://github.com/GetJobber/recurring_select

@lulalala

This comment has been minimized.

Copy link

commented Sep 5, 2014

Nice interface! Will you ever package this as a gem?

@kcollignon

This comment has been minimized.

Copy link

commented Apr 24, 2015

@jbat or @mzaragoza did you ever by chance get updated code to handle adding an exception to schedules? thanks

@Frank004

This comment has been minimized.

Copy link

commented Oct 1, 2015

this great thank you

@rramsden

This comment has been minimized.

Copy link

commented Apr 20, 2016

@nathancolgate Thanks, this really saved me a lot of time.

@kleinjm

This comment has been minimized.

Copy link

commented Jun 5, 2016

Has anyone ported this to Rails 4? Not sure how send :attr_accessible is supposed to work in IceCubeMethods in Rails 4

@jonathan-nye

This comment has been minimized.

Copy link

commented Aug 21, 2016

@kcollignon, @jbat, @mzaragoza: the documentation for IceCube::Schedule#new shows that the param should be :end_time and not :ends_time. However, when I changed to that, it still did not fix the repeat-ends problem. So, I worked around it by adding the following change in EventInstance#occurrences_between:

    results.map { |event|
      schedule_end_date = end_date
      if event.repeat_ends == 'on' && event.repeat_ends_on < end_date
        schedule_end_date = event.repeat_ends_on
      end
      event.schedule.occurrences_between(begin_date,schedule_end_date).map { |date|
        ...
@jonathan-nye

This comment has been minimized.

Copy link

commented Aug 21, 2016

@kleinjm, I removed the :attr_accessible lines from IceCubeMethods since ActiveRecord will create those by default based on the DB columns. Also, I'm using this on Rails 5, but I had to use baby_squeel since squeel doesn't support Rails 5 (baby_squeel supports Rails 4/5). To port to baby_squeel, just use Event.where.has{ in EventInstance instead of Event.where{.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.