我有一个带有序列化Hash属性的Rails模型类,如下所示:
class Action
serialize :metadata, Hash
# . . .
end
该列存储在具有YAML编码的text
列中。问题是当我将metadata
值传递给create!
方法时,散列键会从符号转换为字符串,但该转换不会在其他时间发生。例如:
$ rails console
> a = Action.create!(:metadata => {:foo => "bar"})
> a.metadata
=> {"foo"=>"bar"}
> a.metadata[:fizz] = "buzz"
> a.metadata
=> {"foo"=>"bar", :fizz=>"buzz"}
现在,当我保存模型时,数据库将具有此文本值:
---
foo: bar
:fizz: buzz
有任何建议如何解决这个问题?
(这是使用Rails 3.0.16。)
答案 0 :(得分:3)
我自己回答这个问题,并提出@ Mori建议的变体:
class Action < ActiveRecord::Base
def metadata=(v)
self[:metadata] = v.try(:symbolize_keys!)
end
end
据我所知,这可以在不破坏其他地方界面的情况下解决问题。我想如果我想要一个键成为一个字符串,这个方法会让我感到讨厌,但事实并非如此,所以我比其他人提出的意外更愿意接受它。的解决方案。
不过,如果有人可以提出一个根本不需要这种解决方法的解决方案,我很乐意接受这个作为正确的答案。答案 1 :(得分:2)
class Action < ActiveRecord::Base
def metadata
self[:metadata].try :symbolize_keys
end
end
答案 2 :(得分:0)
我最后走了另一条路。当我访问属性时,我确保得到HashWithIndifferentAccess
:
def metadata
return self[:metadata] if self[:metadata].is_a?(HashWithIndifferentAccess)
self[:metadata] = HashWithIndifferentAccess.new(self[:metadata])
end
额外的好处是,如果metadata
未设置,我将获得空哈希而不是nil