0

我找到了这篇文章:Override a Mongoid model's setter and getters来帮助我,但行为仍然不是我想要的。

我的模型是这样的:

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

这或多或少像我预期的那样工作,因为它序列化和反序列化 IceCube 对象,我注意到虽然我可以这样做:

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

它似乎像我期望的那样序列化和反序列化,我可以称之为

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

并得到预期的响应。但是,如果我尝试:

e.schedule.add_recurrence_rule Rule.daily

s而不是在将属性设置为 on 之前在局部变量上调用它event,我可以查看哈希并查看规则未保留。

在 Ruby 或 Mongoid 中做这种事情的正确方法上我是否缺少一些东西?

我尝试使用 write_attribute 和 read_attribute,但这同样无济于事。

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

当我从表单中发送参数哈希时:

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 回答