我发现这篇文章:Override a Mongoid model's setters 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
上设置属性之前在局部变量event
上调用它,我可以查看哈希并看到规则不会保留。
在Ruby或Mongoid中做这种事情的正确方法是否存在我缺少的东西?
我尝试使用write_attribute和read_attribute,但这同样无济于事。
答案 0 :(得分: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
答案 1 :(得分: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
这不是一个特别优雅的解决方案,但它有效。