6

我有一个带有序列化 Hash 属性的 Rails 模型类,如下所示:

class Action
  serialize :metadata, Hash
  # . . .
end

该列存储在text具有 YAML 编码的列中。问题是,当我将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。)

4

3 回答 3

3
class Action < ActiveRecord::Base
  def metadata
    self[:metadata].try :symbolize_keys
  end
end
于 2012-09-18T19:16:36.490 回答
3

我自己来回答这个问题,@Mori 的建议变体:

class Action < ActiveRecord::Base
  def metadata=(v)
    self[:metadata] = v.try(:symbolize_keys!)
  end
end

据我所知,这可以解决问题而不会破坏其他地方的界面。我想如果我想要一个键是一个字符串,这种方法会给我一个令人讨厌的惊喜,但事实并非如此,所以我更愿意接受它而不是其他提议的解决方案带来的惊喜。

顺便说一句,如果有人可以提出一个根本不需要这种解决方法的解决方案,我会很乐意接受它作为正确的答案。

于 2012-09-18T20:10:04.747 回答
0

我最终选择了另一条路线。HashWithIndifferentAccess当我访问该属性时,我确保我得到了回报:

def metadata
  return self[:metadata] if self[:metadata].is_a?(HashWithIndifferentAccess)
  self[:metadata] = HashWithIndifferentAccess.new(self[:metadata])
end

一个额外的好处是如果metadata没有设置我得到一个空的哈希而不是nil

于 2016-02-26T14:27:07.133 回答