Search code examples
ruby-on-railsmongoidice-cube

serializing an IceCube object for Mongoid


I found this article: Override a Mongoid model's setters and getters to help me, but behavior's still not what I am looking for.

My model is like so:

class Event
  include Mongoid::Document
  include IceCube

  validates_presence_of :title
  field :title, type: String
  field :description, type: String
  field :schedule, type: Hash

  attr_protected :schedule_hash

  def schedule=(new_schedule)
    super(new_schedule.to_hash)
  end

  def schedule
    Schedule.from_hash(super())
  end
end

This works more or less as I'd expect, in that it serializes and deserializes the IceCube object, but what I noticed is that while I can do this:

s = Schedule.new(Time.now)
s.add_recurrence_rule Rule.daily
e = Event.new
e.schedule = s

it seems to serialize and deseralize as I would expect, and I can call things like

e.schedule.occurs_at?(Date.today + 1.day) 

and get the expected response. However, if I try:

e.schedule.add_recurrence_rule Rule.daily

instead of calling it on the local variable s before setting the property on event, I can look at the hash and see the rule is not persisted.

Is there something I'm missing on the right way of doing this sort of thing in Ruby or Mongoid?

I tried using write_attribute and read_attribute, but that was likewise to no avail.


Solution

  • While not the most pretty, this strategy will work:

    
    
    class Event
      include Mongoid::Document
    
      validates_presence_of :title
      field :title, type: String
      field :description, type: String
      field :schedule
    
      before_save do
        write_attribute(:schedule, @schedule.to_yaml)
      end
    
      def schedule=(s)
        @schedule = s
      end
    
      def schedule
        @schedule ||= begin
          yaml = read_attribute(:schedule)
          yaml ? IceCube::Schedule.from_yaml(yaml) : IceCube::Schedule.new
        end
      end
    end