Giter Club home page Giter Club logo

schedulable's Introduction

schedulable

Handling recurring events in rails.

Install

Put the following into your Gemfile and run bundle install

gem 'ice_cube'
gem 'schedulable'

Install schedule migration and model

rails g schedulable:install

Basic Usage

Create an event model

rails g scaffold Event name:string

Don't forget to migrate your database at this point in order to reflect the changes: rake db:migrate

Open app/models/event.rb and add the following to configure your model to be schedulable:

# app/models/event.rb
class Event < ActiveRecord::Base
  acts_as_schedulable :schedule
end

This will add an association to the model named 'schedule' which holds the schedule information.

Schedule Model

The schedule-object respects the following attributes.

NameTypeDescription
ruleStringOne of 'singular', 'daily', 'weekly', 'monthly'
dateDateThe date-attribute is used for singular events and also as startdate of the schedule
timeTimeThe time-attribute is used for singular events and also as starttime of the schedule
dayArrayDay of week. An array of weekday-names, i.e. ['monday', 'wednesday']
day_of_weekHashDay of nth week. A hash of weekday-names, containing arrays with indices, i.e. {:monday => [1, -1]} ('every first and last monday in month')
intervalIntegerSpecifies the interval of the recurring rule, i.e. every two weeks
untilDateSpecifies the enddate of the schedule. Required for terminating events.
countIntegerSpecifies the total number of occurrences. Required for terminating events.

Forms

Use schedulable's built-in helpers to setup your form.

FormBuilder

Schedulable extends FormBuilder with a 'schedule_select'-helper and should therefore seamlessly integrate it with your existing views:

<%# app/views/events/_form.html.erb %>
<%= form_for(@event) do |f| %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  
  <div class="field">
    <%= f.label :schedule %><br>
    <%= f.schedule_select :schedule %>
  </div>
  
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Customize markup

You can customize the generated markup by providing a hash of html-attributes as style-option. For wrappers, also provide a tag-attribute.

  • field_html
  • input_html
  • input_wrapper
  • label_html
  • label_wrapper
  • number_field_html
  • number_field_wrapper
  • date_select_html
  • date_select_wrapper
  • collection_select_html
  • collection_select_wrapper
  • collection_check_boxes_item_html
  • collection_check_boxes_item_wrapper

Integrate with Bootstrap

The schedulable-formhelper has built-in-support for Bootstrap. Simply point the style-option of schedule_input to bootstrap or set it as default in config.

<%= f.schedule_select :schedule, style: :bootstrap %>

Custom inputs

Customize datetime-controls by passing FormBuilder-methods as a hash to the input_types-option. See below example for integrating date_picker with schedulable:

<%# app/views/events/_form.html.erb %>
  
<div class="field form-group">
  <%= f.label :schedule %><br>
  <%= f.schedule_select :schedule, style: :bootstrap, until: true, input_types: {date: :date_picker, time: :time_picker, datetime: :datetime_picker} %>
</div>

Options

NameTypeDescription
countBooleanSpecifies whether to show 'count'-field
input_typesHashSpecify a hash containing custom form builder methods. Defaults to `{date: :date_select, time: :time_select, datetime: :datetime_select}`. The interface of the custom form builder method must either match `date_select` or `date_field`-methods
intervalBooleanSpecifies whether to show 'interval'-field
styleHashSpecifies a hash of options to customize markup. By providing a string, you can point to a prefined set of options. Built-in styles are :bootstrap and :default.
untilBooleanSpecifies whether to show 'until'-field

SimpleForm

Also provided with the plugin is a custom input for simple_form. Make sure, you installed SimpleForm and executed rails generate simple_form:install.

rails g schedulable:simple_form
<%# app/views/events/_form.html.erb %>
<%= simple_form_for(@event) do |f| %>
  
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  
  <div class="field">
    <%= f.label :schedule %><br>
    <%= f.input :schedule, as: :schedule %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
  
<% end %>

Integrate with Bootstrap

Simple Form has built-in support for Bootstrap as of version 3.0.0. At time of writing it requires some a little extra portion of configuration to make it look as expected:

# config/initializers/simple_form_bootstrap.rb

# Inline date_select-wrapper for Bootstrap
config.wrappers :horizontal_select_date, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  b.use :html5
  b.optional :readonly
  b.use :label, class: 'control-label'
  b.wrapper tag: 'div', class: 'form-inline' do |ba|
    ba.use :input, class: 'form-control'
    ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
    ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end
end

# Include date_select-wrapper in mappings
config.wrapper_mappings = {
  datetime: :horizontal_select_date,
  date: :horizontal_select_date,
  time: :horizontal_select_date
}

Custom inputs

You can customize datetime-controls by passing simple_form-inputs as a hash to the input_types-option. See form helper for similar example

For integrating date_picker with schedulable and simple_form, you can also run date_picker's simple_form-generator to create a default date_time-input:

rails g date_picker:simple_form date_time

Options

NameTypeDescription
countBooleanSpecifies whether to show 'count'-field
input_typesHashSpecify a hash containing custom simple form inputs. Defaults to `{date: :date_time, time: :date_time, datetime: :date_time}`.
intervalBooleanSpecifies whether to show 'interval'-field
untilBooleanSpecifies whether to show 'until'-field

Sanitize parameters

Add schedule-attributes to the list of strong parameters in your controller:

# app/controllers/event_controller.rb
def event_params
  params.require(:event).permit(:name, schedule_attributes: Schedulable::ScheduleSupport.param_names)
end

Note: If you don't use schedule as attribute name, you need to rename schedule_attributes accordingly.

Accessing IceCube

You can access ice_cube-methods directly via the schedule association:

<%# app/views/events/show.html.erb %>
<p>
  <strong>Schedule:</strong>
  <%# Prints out a human-friendly description of the schedule, such as %> 
  <%= @event.schedule %>
</p>
# Prints all occurrences of the event until one year from now
puts @event.schedule.occurrences(Time.now + 1.year)
# Export to ical
puts @event.schedule.to_ical

See IceCube for more information.

Internationalization

Schedulable is bundled with translations in english and german which will be automatically initialized with your app. You can customize these messages by running the locale generator and edit the created yml-files:

rails g schedulable:locale de

Date- and Time-Messages

Appropriate datetime translations should be included. Basic setup for many languages can be found here: https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale.

IceCube-Messages

An internationalization-branch of ice_cube can be found here: https://github.com/joelmeyerhamme/ice_cube:

gem 'ice_cube', git: 'git://github.com/joelmeyerhamme/ice_cube.git', branch: 'international' 

Persist Occurrences

Schedulable allows for persisting occurrences and associate them with your event model. The Occurrence Model model must include an attribute of type 'datetime' with name 'date' as well as a polymorphic association to the schedulable event model. Simply use the occurrence generator for setting up the appropriate model:

rails g schedulable:occurrence EventOccurrence

On the other side, pass the association to your schedulable event model by using the occurrences-option of the acts_as_schedulable-method:

# app/models/event.rb
class Event < ActiveRecord::Base
  acts_as_schedulable :schedule, occurrences: :event_occurrences
end

This will create the corresponding has_many-association and also add remaining_event_occurrences and previous_event_occurrences-methods.

Instances of remaining occurrences are persisted when the parent-model is saved. Occurrences records will be reused if their datetime matches the saved schedule. Past occurrences stay untouched.

Terminating and non-terminating events

An event is terminating if an until- or count-attribute has been specified. Since non-terminating events have infinite occurrences, we cannot build all occurrences at once ;-) So we need to limit the number of occurrences in the database. By default this will be one year from now. This can be configured via the 'build_max_count' and 'build_max_period'-options. See notes on configuration.

Automate build of occurrences

Since we cannot build an infinite amount of occurrences, we will need a task that adds occurrences as time goes by. Schedulable comes with a rake-task that performs an update on all scheduled occurrences.

rake schedulable:build_occurrences

You may add this task to crontab.

Use 'whenever' to schedule the generation of occurrences

With the 'whenever' gem this can be easily achieved.

gem 'whenever', :require => false

Generate the 'whenever'-configuration file:

wheneverize .

Open up the file 'config/schedule.rb' and add the job:

# config/schedule.rb
set :environment, "development"
set :output, {:error => "log/cron_error_log.log", :standard => "log/cron_log.log"}

every 1.day do
  rake "schedulable:build_occurrences"
end

Write to crontab:

whenever -w

Configuration

Generate the configuration file

rails g schedulable:config

Open 'config/initializers/schedulable.rb' and edit options as needed:

Schedulable.configure do |config|
  # Build occurrences
  config.max_build_count = 0
  config.max_build_period = 1.year
  # SimpleForm
  config.simple_form = {
    input_types: {
   	  date: :date_time,
   	  time: :date_time,
   	  datetime: :date_time
    }
  }
  # Generic Form helper
  config.form_helper = {
    style: :default
  }
end

Changelog

See the Changelog for recent enhancements, bugfixes and deprecations.

schedulable's People

Contributors

dcas avatar rexblack avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

schedulable's Issues

Deprecation warning with Rails 5.1

If you use that gem with Rails 5 and call Schedule.first it gives you the following deprecation warning:

DEPRECATION WARNING: Time columns will become time zone aware in Rails 5.1. This
still causes `String`s to be parsed as if they were in `Time.zone`,
and `Time`s to be converted to `Time.zone`.

To keep the old behavior, you must add the following to your initializer:

    config.active_record.time_zone_aware_types = [:datetime]

To silence this deprecation warning, add the following:

    config.active_record.time_zone_aware_types = [:datetime, :time]

What is the desired option?

Making schedule_input Render a Date Picker and a Time Picker (Simple Form)

I have date_picker_input.rb and time_picker_input.rb in app/inputs, and I'd like schedule_input.rb to use them, rather than having separate dropdowns for year, month, day, hour, and minute. It looks like I would need to modify schedule_input.rb on lines 45 & 79, but I'm having difficulty getting it to work. How would you go about making schedule_input.rb render a date picker and a time picker instead?

no implicit conversion of Symbol into Integer

I am getting error on the line acts_as_schedulable :schedule as 'no implicit conversion of Symbol into Integer'

class Event < ActiveRecord::Base
  acts_as_schedulable :schedule

end

Incorrect number of event occurrences

I created an event and then scheduled it as follows
schedule_attributes = {date: Date.today, time: Time.now + 20.minutes, rule: 'daily', count: 5)}

I am saving the occurrences in EventOccurrences table.
I am expecting 5 Event Occurrences to be saved, but instead I am getting only 4 EventOccurrences.

I went through the code, and in 'acts_as_schedulable.rb', there was a condition which said, occurrence_date.to_time < max_date,

In this case max_date will be the 5th occurrence date. But this condition fails bcos it is not less than the max_date

Any help would be appreciated, if this is the expected behaviour, or my understanding about the way it works is wrong.

input_type for schedule_select not recognized

I'm using rails default form helper along with date_picker. This is my usage of schedulable.
<%= f.schedule_select :schedule,input_types: {date: :date_picker, time: :time_picker, datetime: :datetime_picker}, style: :bootstrap, until: true, count: true%>
I'm still getting the default date and time pickers instead of bootstrap's date and time pickers. What am I doing wrong?

future maintenance

@rexblack I really love this gem and am using it in two commercial products, however it's a great pity that it is not maintained. Are you planning to get working on it... anytime in the future? Or you could let others maintain it...

EventOccurrence duplication upon editing Event

Persisting occurrences works fine. Thing is upon editing the date of an Event instance a new EventOccurrence is persisted instead of modifying an existing one. I've setup Schedulable in a new Rails 5 application and the same thing happens.

Incorrect day labels in simple_form custom input checkboxes

When creating schedules with weekly and monthly recurrence rules, the checkboxes in the simple_form custom input are incorrectly labeled. The checkbox labeled 'Sunday' has value :monday, 'Monday' has value :tuesday, etc.

Inconsistency in the start of the week returned by Time::DAYS_INTO_WEEK and I18n.t("date.day_names") is causing the problem. Changing the date.day_names translation to ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] is a quick fix but doesn't solve the issue across locales and might have effects elsewhere.

undefined method `validators_on' for OpenStruct:Class

When I add the <%= f.schedule_select :schedule, style: :bootstrap %> to my view I get the following error:
undefined method `validators_on' for OpenStruct:Class

I can not identify the cause of this error.

Thanks in advance.

undefined method `rule'?

Created a very basic app using schedulable and ice cube but ran into a strange bug.
Double checked my models for any typos or issues and didn't find any problems. Checked from the console that all my associations are correct. I'm using the generated input for simple form, unmodded. Pretty much stumped at this point but likely I am missing something obvious.

undefined method `rule' for #IceCube::Schedule:0x000001071e3c70

Stack trace:
schedulable (0.0.6) lib/schedulable/schedule_support.rb:15:in method_missing' schedulable (0.0.6) lib/schedulable/schedule_support.rb:37:ininit_schedule'
activesupport (4.1.1) lib/active_support/callbacks.rb:424:in block in make_lambda' activesupport (4.1.1) lib/active_support/callbacks.rb:221:incall'
activesupport (4.1.1) lib/active_support/callbacks.rb:221:in block in halting_and_conditional' activesupport (4.1.1) lib/active_support/callbacks.rb:86:incall'
activesupport (4.1.1) lib/active_support/callbacks.rb:86:in run_callbacks' activerecord (4.1.1) lib/active_record/core.rb:201:ininitialize'
activerecord (4.1.1) lib/active_record/inheritance.rb:30:in new' activerecord (4.1.1) lib/active_record/inheritance.rb:30:innew'
activerecord (4.1.1) lib/active_record/reflection.rb:207:in build_association' activerecord (4.1.1) lib/active_record/associations/association.rb:247:inbuild_record'
activerecord (4.1.1) lib/active_record/associations/singular_association.rb:29:in build' activerecord (4.1.1) lib/active_record/associations/builder/singular_association.rb:18:inbuild_schedule'
app/inputs/schedule_input.rb:14:in input' simple_form (3.1.0) lib/simple_form/components/label_input.rb:26:incall'
simple_form (3.1.0) lib/simple_form/components/label_input.rb:26:in deprecated_component' simple_form (3.1.0) lib/simple_form/components/label_input.rb:14:inlabel_input'
simple_form (3.1.0) lib/simple_form/wrappers/leaf.rb:19:in call' simple_form (3.1.0) lib/simple_form/wrappers/leaf.rb:19:inrender'
simple_form (3.1.0) lib/simple_form/wrappers/many.rb:28:in block in render' simple_form (3.1.0) lib/simple_form/wrappers/many.rb:26:ineach'
simple_form (3.1.0) lib/simple_form/wrappers/many.rb:26:in render' simple_form (3.1.0) lib/simple_form/wrappers/root.rb:15:inrender'
simple_form (3.1.0) lib/simple_form/form_builder.rb:115:in input' app/views/jobs/_form.html.erb:10:inblock in _app_views_jobs__form_html_erb___3237886738178548600_2159188600'
actionview (4.1.1) lib/action_view/helpers/capture_helper.rb:38:in block in capture' actionview (4.1.1) lib/action_view/helpers/capture_helper.rb:200:inwith_output_buffer'
actionview (4.1.1) lib/action_view/helpers/capture_helper.rb:38:in capture' actionview (4.1.1) lib/action_view/helpers/form_helper.rb:434:inform_for'
simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:26:in block in simple_form_for' simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:45:inwith_simple_form_field_error_proc'
simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:25:in simple_form_for' app/views/jobs/_form.html.erb:1:in_app_views_jobs__form_html_erb___3237886738178548600_2159188600'
actionview (4.1.1) lib/action_view/template.rb:145:in block in render' activesupport (4.1.1) lib/active_support/notifications.rb:161:ininstrument'
actionview (4.1.1) lib/action_view/template.rb:339:in instrument' actionview (4.1.1) lib/action_view/template.rb:143:inrender'
actionview (4.1.1) lib/action_view/renderer/partial_renderer.rb:306:in render_partial' actionview (4.1.1) lib/action_view/renderer/partial_renderer.rb:279:inblock in render'
actionview (4.1.1) lib/action_view/renderer/abstract_renderer.rb:38:in block in instrument' activesupport (4.1.1) lib/active_support/notifications.rb:159:inblock in instrument'
activesupport (4.1.1) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.1.1) lib/active_support/notifications.rb:159:ininstrument'
actionview (4.1.1) lib/action_view/renderer/abstract_renderer.rb:38:in instrument' actionview (4.1.1) lib/action_view/renderer/partial_renderer.rb:278:inrender'
actionview (4.1.1) lib/action_view/renderer/renderer.rb:47:in render_partial' actionview (4.1.1) lib/action_view/helpers/rendering_helper.rb:35:inrender'
app/views/jobs/new.html.erb:5:in _app_views_jobs_new_html_erb___4550522753965688097_2158955920' actionview (4.1.1) lib/action_view/template.rb:145:inblock in render'
activesupport (4.1.1) lib/active_support/notifications.rb:161:in instrument' actionview (4.1.1) lib/action_view/template.rb:339:ininstrument'
actionview (4.1.1) lib/action_view/template.rb:143:in render' actionview (4.1.1) lib/action_view/renderer/template_renderer.rb:55:inblock (2 levels) in render_template'
actionview (4.1.1) lib/action_view/renderer/abstract_renderer.rb:38:in block in instrument' activesupport (4.1.1) lib/active_support/notifications.rb:159:inblock in instrument'
activesupport (4.1.1) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.1.1) lib/active_support/notifications.rb:159:ininstrument'
actionview (4.1.1) lib/action_view/renderer/abstract_renderer.rb:38:in instrument' actionview (4.1.1) lib/action_view/renderer/template_renderer.rb:54:inblock in render_template'
actionview (4.1.1) lib/action_view/renderer/template_renderer.rb:62:in render_with_layout' actionview (4.1.1) lib/action_view/renderer/template_renderer.rb:53:inrender_template'
actionview (4.1.1) lib/action_view/renderer/template_renderer.rb:17:in render' actionview (4.1.1) lib/action_view/renderer/renderer.rb:42:inrender_template'
actionview (4.1.1) lib/action_view/renderer/renderer.rb:23:in render' actionview (4.1.1) lib/action_view/rendering.rb:99:in_render_template'
actionpack (4.1.1) lib/action_controller/metal/streaming.rb:217:in _render_template' actionview (4.1.1) lib/action_view/rendering.rb:82:inrender_to_body'
actionpack (4.1.1) lib/action_controller/metal/rendering.rb:32:in render_to_body' actionpack (4.1.1) lib/action_controller/metal/renderers.rb:32:inrender_to_body'
actionpack (4.1.1) lib/abstract_controller/rendering.rb:25:in render' actionpack (4.1.1) lib/action_controller/metal/rendering.rb:16:inrender'
actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:41:in block (2 levels) in render' activesupport (4.1.1) lib/active_support/core_ext/benchmark.rb:12:inblock in ms'
/Users/scott/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/benchmark.rb:294:in realtime' activesupport (4.1.1) lib/active_support/core_ext/benchmark.rb:12:inms'
actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:41:in block in render' actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:84:incleanup_view_runtime'
activerecord (4.1.1) lib/active_record/railties/controller_runtime.rb:25:in cleanup_view_runtime' actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:40:inrender'
actionpack (4.1.1) lib/action_controller/metal/implicit_render.rb:10:in default_render' actionpack (4.1.1) lib/action_controller/metal/implicit_render.rb:5:insend_action'
actionpack (4.1.1) lib/abstract_controller/base.rb:189:in process_action' actionpack (4.1.1) lib/action_controller/metal/rendering.rb:10:inprocess_action'
actionpack (4.1.1) lib/abstract_controller/callbacks.rb:20:in block in process_action' activesupport (4.1.1) lib/active_support/callbacks.rb:113:incall'
activesupport (4.1.1) lib/active_support/callbacks.rb:113:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:166:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:229:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:229:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:229:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:229:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:166:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:166:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:166:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:166:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:166:inblock in halting'
activesupport (4.1.1) lib/active_support/callbacks.rb:86:in call' activesupport (4.1.1) lib/active_support/callbacks.rb:86:inrun_callbacks'
actionpack (4.1.1) lib/abstract_controller/callbacks.rb:19:in process_action' actionpack (4.1.1) lib/action_controller/metal/rescue.rb:29:inprocess_action'
actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:31:in block in process_action' activesupport (4.1.1) lib/active_support/notifications.rb:159:inblock in instrument'
activesupport (4.1.1) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.1.1) lib/active_support/notifications.rb:159:ininstrument'
actionpack (4.1.1) lib/action_controller/metal/instrumentation.rb:30:in process_action' actionpack (4.1.1) lib/action_controller/metal/params_wrapper.rb:250:inprocess_action'
activerecord (4.1.1) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (4.1.1) lib/abstract_controller/base.rb:136:inprocess'
actionview (4.1.1) lib/action_view/rendering.rb:30:in process' actionpack (4.1.1) lib/action_controller/metal.rb:195:indispatch'
actionpack (4.1.1) lib/action_controller/metal/rack_delegation.rb:13:in dispatch' actionpack (4.1.1) lib/action_controller/metal.rb:231:inblock in action'
actionpack (4.1.1) lib/action_dispatch/routing/route_set.rb:80:in call' actionpack (4.1.1) lib/action_dispatch/routing/route_set.rb:80:indispatch'
actionpack (4.1.1) lib/action_dispatch/routing/route_set.rb:48:in call' actionpack (4.1.1) lib/action_dispatch/journey/router.rb:71:inblock in call'
actionpack (4.1.1) lib/action_dispatch/journey/router.rb:59:in each' actionpack (4.1.1) lib/action_dispatch/journey/router.rb:59:incall'
actionpack (4.1.1) lib/action_dispatch/routing/route_set.rb:676:in call' warden (1.2.3) lib/warden/manager.rb:35:inblock in call'
warden (1.2.3) lib/warden/manager.rb:34:in catch' warden (1.2.3) lib/warden/manager.rb:34:incall'
rack (1.5.2) lib/rack/etag.rb:23:in call' rack (1.5.2) lib/rack/conditionalget.rb:25:incall'
rack (1.5.2) lib/rack/head.rb:11:in call' actionpack (4.1.1) lib/action_dispatch/middleware/params_parser.rb:27:incall'
actionpack (4.1.1) lib/action_dispatch/middleware/flash.rb:254:in call' rack (1.5.2) lib/rack/session/abstract/id.rb:225:incontext'
rack (1.5.2) lib/rack/session/abstract/id.rb:220:in call' actionpack (4.1.1) lib/action_dispatch/middleware/cookies.rb:560:incall'
activerecord (4.1.1) lib/active_record/query_cache.rb:36:in call' activerecord (4.1.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:incall'
activerecord (4.1.1) lib/active_record/migration.rb:380:in call' actionpack (4.1.1) lib/action_dispatch/middleware/callbacks.rb:29:inblock in call'
activesupport (4.1.1) lib/active_support/callbacks.rb:82:in run_callbacks' actionpack (4.1.1) lib/action_dispatch/middleware/callbacks.rb:27:incall'
actionpack (4.1.1) lib/action_dispatch/middleware/reloader.rb:73:in call' actionpack (4.1.1) lib/action_dispatch/middleware/remote_ip.rb:76:incall'
actionpack (4.1.1) lib/action_dispatch/middleware/debug_exceptions.rb:17:in call' actionpack (4.1.1) lib/action_dispatch/middleware/show_exceptions.rb:30:incall'
railties (4.1.1) lib/rails/rack/logger.rb:38:in call_app' railties (4.1.1) lib/rails/rack/logger.rb:20:inblock in call'
activesupport (4.1.1) lib/active_support/tagged_logging.rb:68:in block in tagged' activesupport (4.1.1) lib/active_support/tagged_logging.rb:26:intagged'
activesupport (4.1.1) lib/active_support/tagged_logging.rb:68:in tagged' railties (4.1.1) lib/rails/rack/logger.rb:20:incall'
actionpack (4.1.1) lib/action_dispatch/middleware/request_id.rb:21:in call' rack (1.5.2) lib/rack/methodoverride.rb:21:incall'
rack (1.5.2) lib/rack/runtime.rb:17:in call' activesupport (4.1.1) lib/active_support/cache/strategy/local_cache_middleware.rb:26:incall'
rack (1.5.2) lib/rack/lock.rb:17:in call' actionpack (4.1.1) lib/action_dispatch/middleware/static.rb:64:incall'
rack (1.5.2) lib/rack/sendfile.rb:112:in call' railties (4.1.1) lib/rails/engine.rb:514:incall'
railties (4.1.1) lib/rails/application.rb:144:in call' rack (1.5.2) lib/rack/lock.rb:17:incall'
rack (1.5.2) lib/rack/content_length.rb:14:in call' rack (1.5.2) lib/rack/handler/webrick.rb:60:inservice'
/Users/scott/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/httpserver.rb:138:in service' /Users/scott/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/httpserver.rb:94:inrun'
/Users/scott/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/webrick/server.rb:295:in `block in start_thread'

job.rb:
class Job < ActiveRecord::Base
acts_as_schedulable occurrences: :job_occurrences
end

schedule.rb:
class Schedule < ActiveRecord::Base

include Schedulable::ScheduleSupport

serialize :days
serialize :day_of_week, Hash

belongs_to :schedulable, polymorphic: true

after_initialize :init_schedule
after_save :init_schedule
end

Different name other than schedule

Is there any way to use a name other than schedule
i.e I want some thing like this

class Employee < ActiveRecord::Base
    acts_as_schedulable :leave_schedule
end

When I am trying this it doesn't work as the following part of code in the file acts_as_schedulable.rb doesnt have class name mentioned

# Line number 16 in acts_as_schedulable.rb
has_one name, as: :schedulable, dependent: :destroy
# The above line doesnt have class name

Is this gem still maintained?

It looks like there hasn't been a commit since 2016 or a gem release since 2015 and there's been little movement on #38.

Is there anything the community can do to help the maintainers?

NoMethodError: undefined method `rule=' for nil:NilClass

Hi,

I'm trying out your gem and I'm getting an undefined method error with the following code (leaving recurring events aside for the moment):

event = calendar.events.where(uid: ical_event.uid.to_s).first_or_create
event.summary = ical_event.summary.to_s
event.description = ical_event.description.to_s

event.schedule.rule = "singular"
event.schedule.date = ical_event.dtstart
event.schedule.until = ical_event.dtend

event.save

These are my models:

class Event < ApplicationRecord
  acts_as_schedulable :schedule
end
class Schedule < Schedulable::Model::Schedule
end

Do I have to instantiate the schedule by myself - anything else that might be wrong?

Best

Sebastian

PS: That's my environment

ruby 2.2.2
Rails 5.0.0.1

RESTful API

I am trying to use schedule with JSON but I am having issues creating a schedule via a JSON request. Has anybody managed to accomplish this?

rake schedulable:build_occurrences failing

In my app I have a jobs model which is schedulable and has occurrences. When I create a new job the occurrences are correctly created but when I run rake schedulable:build_occurrences it fails. Totally stumped by this one. Trace below.

rake schedulable:build_occurrences --trace
** Invoke schedulable:build_occurrences (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute schedulable:build_occurrences
rake aborted!
ArgumentError: wrong number of arguments (1 for 0)
/Users/scott/.rvm/gems/ruby-2.1.0/gems/activerecord-4.2.0/lib/active_record/scoping/named.rb:24:in all' /Users/scott/.rvm/gems/ruby-2.1.0/gems/schedulable-0.0.7/lib/tasks/schedulable_tasks.rake:5:inblock (2 levels) in <top (required)>'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:240:in call' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:240:inblock in execute'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:235:in each' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:235:inexecute'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:179:in block in invoke_with_call_chain' /Users/scott/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/monitor.rb:211:inmon_synchronize'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:172:in invoke_with_call_chain' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/task.rb:165:ininvoke'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:150:in invoke_task' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:106:inblock (2 levels) in top_level'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:106:in each' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:106:inblock in top_level'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:115:in run_with_threads' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:100:intop_level'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:78:in block in run' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:176:instandard_exception_handling'
/Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/lib/rake/application.rb:75:in run' /Users/scott/.rvm/gems/ruby-2.1.0/gems/rake-10.4.2/bin/rake:33:in<top (required)>'
/Users/scott/.rvm/gems/ruby-2.1.0/bin/rake:23:in load' /Users/scott/.rvm/gems/ruby-2.1.0/bin/rake:23:in

'
/Users/scott/.rvm/gems/ruby-2.1.0/bin/ruby_executable_hooks:15:in eval' /Users/scott/.rvm/gems/ruby-2.1.0/bin/ruby_executable_hooks:15:in'
Tasks: TOP => schedulable:build_occurrences

Rails dependency

Is there a reason why the gem depends on the version 4.0.3 of Rails? I had to remove this dependency to make it work.

Batching vs all for build_event_occurrences

Here is the sample code I thinking off for this. Please give your suggestions. This also includes unique occurrences by adding index to db.

  def self.build_event_occurrences
    # build occurrences for all events
    # TODO: only invalid events
    schedulables = self
    # schedulables.each do |schedulable|

    schedulables = schedulables.includes(:schedule)

    schedulables.find_each(batch_size: 100) do |schedulable|
      begin
        schedulable.build_event_occurrences
      rescue ActiveRecord::RecordNotUnique
        # Ignore it
        next
      rescue Exception => ex
        throw ex
      end
    end
  end

First day of month?

Can this library support a schedule such as first day of a month? Trying to do so but keep getting validation errors for missing day_of_week fields.

Event has_many :event_occurrences. How to?

With the default setup,
the Event can call the = event.schedule
&
the EventOccurrence can call the = event_occurrence.schedulable_id
=>
How do we call the parent Event from EventOccurrence?
Like = event_occurrence.schedule.event.name

schedule between hours

In schedulable I see you can create a schedule with a set time, but in ice_cube you can do something like

s=IceCube::Schedule.new(Time.now, duration: IceCube::ONE_HOUR)

which will set up a schedule (singular) between now and 1h

after which you can also do

s.add_recurrence_rule IceCube::Rule.daily

which will make it daily recurring in the interval of that hour

Is this possible in schedulable ?

Error running rake schedulable:build_occurrences

When running:
rake schedulable:build_occurrences

i get:
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "schedules.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "schedules".* FROM "schedules" GROUP BY "schedules"."...
^
: SELECT "schedules".* FROM "schedules" GROUP BY "schedules"."schedulable_type"
/Users/thomas/.rbenv/versions/2.2.3/bin/bundle:22:in load' /Users/thomas/.rbenv/versions/2.2.3/bin/bundle:22:in

'
PG::GroupingError: ERROR: column "schedules.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "schedules".* FROM "schedules" GROUP BY "schedules"."...

Event model:
class Event < ActiveRecord::Base

SCHEDULABLE

acts_as_schedulable :schedule, occurrences: :event_occurrences

has_many :bookings, as: :bookable
end

Singular select date

When implementing the bootstrap form for selecting the recurrence - Singular, the date is always the current date. No matter if I select another month or day. (from the Master Branch)

Updating the ReadMe!

First and foremost, Thanks for creating this gem, It's really useful!

I ran into a little trouble getting my occurrences working properly so I thought I'd share the steps here incase it was worth updating on the Readme. I've had to discover, by looking at your demo project, that it's necessary to create the following code changes:

The first is that your _occurrence model belongs to :scheduable and not your model as the current Readme indicates. The snippet below works!

class EventOccurrence < ActiveRecord::Base
  belongs_to :schedulable, polymorphic: true
end

The next is that a migration is required that adds a schedulable reference to your _occurrence table.

def change
  add_reference :event_occurrences, :schedulable, polymorphic: true, index: true
end

And the last is that sometimes your table name is too long to create an index automatically and you receive an error message that states "Index name on table 'event_occurrences' is too long; the limit is 63 characters".

In these instances it's better if you drop the "index: true" and create a separate migration to add the index with a shorter name.

class AddReferencesIndex < ActiveRecord::Migration
  add_index "event_occurrences", ["schedulable_type", "schedulable_id"], name: "index_event_occurrences_on_schedulable_type_schedulable_id"
end

I hope this helps save someone else some time.

All Schedule attributes value nil rails 4.1.12

I am using schedule 0.0.10. No matter whatever values I assign to schedule object it does not takes any value and all attributes are nil.

schedule = Schedule.create(schedulable: Activity.last, rule: 'weekly', interval: 2, date: Date.today, time: (Time.now + 1000)

Above line does not saves schedule and gives error that rule can't be blank and time can't be blank and all values of schedule object are nil.

Any help will be great.
Thanks.

Subset of rules possible?

If I'm only looking to have the "singular" and "weekly" options appear in the rules, is that possible?

TimeZone Issues.

When the system timezone is UTC, and I schedule a recurring event at 9:00 AM IST(+5.30), the time entry in schedule table time field is correct.
But the event occurrence -> date field is saved as 9:00 AM UTC.

This happens only in recurring event, and not in singular type of events

Schedule occurrences since_date

It would be nice to use the date rule for Daily/Weekly/Monthly schedule to generate event_occurrences as of date, not as of Time.now. Any plans to implement it?

Implement proper unit tests

One thing which makes this gem difficult to maintain is that it's lacking of proper unit tests, particularly in regard to the complexity of its requirements.

Since there's lots of different aspects involved ranging from tricky calendar stuff, advanced forms, ui components, database topics and lots more, some help on the topic would be highly appreciated.

Besides implementing the actual tests, an outline of the specs would also be a very helpful starting point. Contributions welcome!

Gem release

Could you release a new gem version please?
Seems like there are a lot of fixes and new features since the last release in November 2015.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.