0

In my Rails 7 app, I have installed the ice_cube gem (with the following line in the Gemfile):

gem "ice_cube"

At the top of my batch model, I have added the following lines:

require "ice_cube"
require "active_support/time"
serialize :schedule, Hash

The schedule column is a text column, and I have defined the following create_schedule method in the batch model:

def create_schedule
  schedule = IceCube::Schedule.new(self.start_datetime, duration: duration(start_datetime, end_datetime))
  schedule.add_recurrence_rule(IceCube::Rule.daily)
  self.schedule = schedule.to_hash
end

I call the create_schedule method in the create action of the controller:

def create
  @batch = Batch.new(batch_params)
  @batch.create_schedule
  @batch.user = current_user
  if @batch.save
    redirect_to batch_tasks_path(@batch), notice: "Batch sucessfully created."
  else
    render :new, status: :unprocessable_entity
  end
end

This appears to work, since I can check in Rails console that the schedule attribute contains a value in the expected format, for instance:

"{:start_time=>{:time=>2022-08-05 09:33:00 UTC, :zone=>\"UTC\"}, :end_time=>{:time=>2022-08-05 10:33:00 UTC, :zone=>\"UTC\"}, :rrules=>[{:validations=>{}, :rule_type=>\"IceCube::DailyRule\", :interval=>1}], :rtimes=>[], :extimes=>[]}"

However, whenever I try to call an occurrence method on the schedule, such as batch.schedule.occurring_at?(Time.now), it returns an error like this:

undefined method `occurring_at?' for "{:start_time=>{:time=>2022-08-05 09:33:00 UTC, :zone=>\"UTC\"}, :end_time=>{:time=>2022-08-05 10:33:00 UTC, :zone=>\"UTC\"}, :rrules=>[{:validations=>{}, :rule_type=>\"IceCube::DailyRule\", :interval=>1}], :rtimes=>[], :extimes=>[]}":String (NoMethodError) 
    
b.schedule.occurring_at?(Time.now)                                                     
          ^^^^^^^^^^^    
       

I have tried other ice_cube methods, such as occurrences, occurs_on?, etc. but none seems to be defined: it's as if the ice_cube methods were not available at all in my app.

What I am missing here?

Thibaud Clement
  • 6,607
  • 10
  • 50
  • 103
  • 2
    `serialize :schedule, Hash` and `self.schedule = schedule.to_hash` suggest that you're storing the schedule as a Hash rather than an `IceCube::Schedule`. Maybe you need to recreate the `IceCube::Schedule` using your stored Hash (or not bother storing it all) before calling `occurring_at?`. – mu is too short Aug 05 '22 at 23:21
  • 1
    `IceCube::Schedule` provides `from_hash` method to generate schedule from hash => `ice_cube_schedule = IceCube::Schedule.from_hash(schedule)` and then call `occurring_at?` on it `ice_cube_schedule.occurring_at?` – Sampat Badhe Aug 05 '22 at 23:31
  • @SampatBadhe thanks for your comment. I agree, and I gave that a try prior to posting this question. When I run `ice_cube_schedule = IceCube::Schedule.from_hash(schedule)`, I get the following error: `'_match_key': undefined method 'has_key?' for "{:start_time=>{:time=>2022-08-05 09:33:00 UTC, :zone=>\"UTC\"}, :end_time=>{:time=>2022-08-05 10:33:00 UTC, :zone=>\"UTC\"}, :rrules=>[{:validations=>{}, :rule_type=>\"IceCube::DailyRule\", :interval=>1}], :rtimes=>[], :extimes=>[]}":String (NoMethodError) return key if __getobj__.has_key? key` This is puzzling. – Thibaud Clement Aug 05 '22 at 23:57
  • @muistooshort you are correct: I am storing the schedule as a hash. The reason why I am doing this is because, otherwise, the value of schedule is simply something like `"Daily"`, and then when I try to call `.occurring_at?` on it, I get another undefined method error, similar to the one specified in the question: `undefined method `occurring_at?' for "Daily":String`. This is why I came to the conclusion that the problem is related to the `occurring_at?` method rather than the value of the `schedule` attribute, but I may be completely wrong. – Thibaud Clement Aug 06 '22 at 00:01
  • 1
    Looks like schedule is returning String not Hash. – Sampat Badhe Aug 06 '22 at 00:02
  • 1
    Could you please check by moving the serialize method on top of the batch model. – Sampat Badhe Aug 06 '22 at 00:14
  • @SampatBadhe I confirm that the `serialize` method is already at the very top of the `batch` model: I have updated the code in the question to reflect it more clearly. I believe you are right to say that the schedule is returning a String, although I do not understand how that is possible given the fact that the column is serialized as a Hash and that the value in the `create_schedule` method is saved with the `to_hash` method. – Thibaud Clement Aug 06 '22 at 00:32
  • @SampatBadhe I am wondering if this could be the solution: https://github.com/ice-cube-ruby/ice_cube/wiki/IceCube-and-Rails `To save and reload your schedule in ActiveRecord with the attribute name 'schedule', you should set up a TEXT database column and add the serializer for the column name: class Task < ActiveRecord::Base serialize :schedule, IceCube::Schedule end` I am giving it a try now and will report back. – Thibaud Clement Aug 06 '22 at 00:34
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/247069/discussion-between-sampat-badhe-and-thibaud-clement). – Sampat Badhe Aug 06 '22 at 02:11

0 Answers0