Rails 4.1 / 活动记录 data_store 哈希未初始化/序列化



绕过rails提供的数据存储的东西,我有一些困扰我的东西

假设我有一个简单的帖子模型,带有title,并且出于某种原因,我想以某种方式将动态属性存储在另一个字段中,称为" post_garbage

在后期模型中,我有简单的序列化程序:

class Post < ActiveRecord::Base
  serialize :post_garbage
end

正如我所说,除了 rails 文档解释的内容外,在此post_garbage字段中没有设置命名访问器

在控制台中播放:

p = Post.first
p.post_garbage["the_stuff"] = "something"
p.save

显然,我得到了一个错误。"the_stuff"未知。停在这里,你想转储这个data_store的东西,更安全,更容易创建一个新字段来完成工作(如果你必须在data_store字段上设置访问器,我不明白它的实用性)。

*但*

如果首先在此post_garbage字段中保存一个空哈希:

p = Post.first
p.post_garbage = {}
p.save

以下情况成为可能:

p = Post.first
p.post_garbage["whatever_i_have_in_mind"] = "some value"
p.save

紧接着:

p.post_garbage["it_then_get_dynamic"] = "and that's pretty cool"
p.save

它变得无模式,不需要指定访问器;有点提供预期的东西。所以我想知道:许多人会期望数据存储有一个无模式的东西,但文档并没有这样使用它。但它有效,看起来像一个糟糕的把戏。奇迹。。。

相反,serialize :post_garbage有什么用,如果当为空时,它不返回空哈希?

真的很感激对此的一些经验丰富的反馈,因为我觉得我错过了一些东西

多谢

这可能与对象初始化时p.post_garbage中没有值的事实有关。

p.post_garbage["the_stuff"] = "something"

试图隐式地将post_garbage视为哈希。最终将类似于

unset_variable = nil
unset_variable['hash_key'] = 'hash_value'

对属性使用序列化方法告诉 Rails 它应该期望将对象压缩为键值映射,并将其作为文本存储在数据库中。但这并不一定意味着您的对象是将其实例化为哈希的。它可以是任何特定的对象。但是,需要先将该对象分配给属性,然后才能对其进行序列化。序列化可能会解决在加载时存储和重构它的魔术,但如果未初始化,它不会对该对象的形式做出任何假设。因此,在没有任何指示的情况下,Ruby post_garbage不会期望它是一个哈希。

至于为什么空的时候不返回空的有? 空对象和缺失对象之间存在差异。(即:{} vs nil)。它们不是一回事,通常丢失的对象被视为空对象。但是这种区别是有价值的,我希望 Rails 在加载序列化属性时会保留它。

也许您应该尝试在创建时使用这样的东西初始化它?

class Post < ActiveRecord::Base
  serialize :post_garbage
  after_initialize :default_values
  private
    def default_values
      self.post_garbage ||= {}
    end
end