0

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.

4

2 に答える 2

2

最もきれいではありませんが、この戦略は機能します。



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

于 2012-10-17T23:11:05.603 に答える
0

Romanのソリューションでは、繰り返しルールをシリアル化するための追加の手順が必要です。ルールを追加したら、インスタンス変数@scheduleを属性ハッシュに書き込む必要があります。

私のコードでは、次のようなものが使用されています。

before_save :serialize_schedule

def schedule=(s)
  super(s.to_yaml) if s.is_a?(IceCube::Schedule)
end

def schedule
  yaml = super()
  if yaml.nil?
    @schedule ||= IceCube::Schedule.new(Time.at(0))
  else
    @schedule ||= Schedule.from_yaml(yaml)
  end
end

def serialize_schedule
  self.schedule = schedule
end

フォームからparamsハッシュを送信すると、次のようになります。

def repeats_weekly_days=(day_array)
  schedule.add_recurrence_rule IceCube::Rule.weekly.day(day_array.map(&:to_sym))
  serialize_schedule
end

次のテストに合格します。

describe "#assign_attributes" do
  let(:params) {{start_time: "08:00", end_time: "12:00", repeats_weekly_days: ["monday", "thursday"]}}
  it "expect schedule to repeat on Mondays and Thursdays" do
    jc.assign_attributes(params)
    expect(jc.read_attribute(:schedule)).to include('WeeklyRule')
    expect(jc.schedule.recurrence_rules[0].to_s).to eq('Weekly on Mondays and Thursdays')
  end
end

これは特に洗練されたソリューションではありませんが、機能します。

于 2015-01-19T15:54:02.860 に答える