ruby-on-rails ActiveRecord在序列化散列时将符号键转换为字符串

enxuqcxy  于 2023-01-03  发布在  Ruby
关注(0)|答案(3)|浏览(147)

我有一个带有序列化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

有什么建议可以解决这个问题吗?
(This与Rails 3.0.16一起使用。)

neekobn8

neekobn81#

class Action < ActiveRecord::Base
  def metadata
    self[:metadata].try :symbolize_keys
  end
end
4c8rllxm

4c8rllxm2#

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

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

据我所知,这个方法解决了这个问题,而且没有破坏其他地方的接口。我想如果我 * 希望 * 键是字符串,这个方法会给我带来很大的惊喜,但事实并非如此,所以我更愿意接受它,而不是其他解决方案带来的惊喜。
顺便说一句,如果有人能提出一个根本不需要这种变通办法的解决方案,我会很高兴地接受它作为正确的答案。

mmvthczy

mmvthczy3#

最后我走了另一条路。我确保在访问属性时返回一个HashWithIndifferentAccess

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

另外一个好处是,如果没有设置metadata,我将得到一个空哈希值,而不是nil

相关问题