Rails 中字段的自定义序列化

Posted

技术标签:

【中文标题】Rails 中字段的自定义序列化【英文标题】:Custom serialization for fields in Rails 【发布时间】:2011-05-27 05:27:31 【问题描述】:

有没有办法对 rails 中的字段进行自定义序列化,这是一种在保存和加载字段时运行的方法,以转换/转换为最终保存在数据库中的字符串。

具体来说,我想要做的是有一个类型为符号的字段,如性别,可能的值 :male 和 :female 在数据库中存储“男性”和“女性”。有一些解决方法,例如:

def gender
  read_attribute(:gender).try(:to_sym)
end

但是 obj.attributes 没有改变,所以它是一个泄漏的抽象。

【问题讨论】:

【参考方案1】:

您可以为模型定义模型 to_xml,它会这样做 http://api.rubyonrails.org/classes/ActiveRecord/Serialization.html

它可以定义 Marshall.dump 并以我认为的方式放置,但它需要研究

【讨论】:

我说的不是将整个模型序列化为字符串,而是将单个字段序列化为字符串以存储在数据库中。【参考方案2】:

您可以在模型中使用serialize 方法。请参考此链接: http://api.rubyonrails.org/classes/ActiveRecord/Base.html (ps。在该页面中搜索关键字“序列化”;D)

简而言之,您可以这样做:

class YourModel < ActiveRecord::Base
  serialize :db_field
end

Rails 会在保存到数据库之前自动序列化字段,并在从数据库中获取后反序列化。

【讨论】:

这样做的问题是它会转换为 yaml,这使得数据在查询中更难使用,而只是将直接符号保存到字符串转换就可以了。这就是我在数据库中保存“男性”和“女性”的意思,也就是说,而不是“--- :male”和“--- :female”)。【参考方案3】:

对于男性/女性来说,你可以像男性一样做一个布尔列,如果它是错误的,假设这意味着女性,为它添加包装方法

def female? 
  return !self.male?
end

【讨论】:

这只是一个例子,我想存储两个以上的符号。尝试与男性,女性,未知和隐藏。【参考方案4】:
def whachamacallit
  read_attribute("whachamacallit").to_sym
end
def whachamacallit=(name)
  write_attribute("whachamacallit", name.to_s)
end

将它们作为字符串存储在数据库中,但在将它们拉出时将它们作为符号提取,然后在保存之前转换回来。 可以使用任意数量或任意组合的字符串/符号。

将其限制在少数几个

validates_inclusion_of :whachamacallit, :in => [ :male, :female, :unknown, :hidden ]

【讨论】:

我已经考虑过这个解决方案,但我不喜欢它的是,如果我查看 obj.attributes 该字段显然是一个字符串而不是一个字段,我知道它会回来在我不那么期待的时候咬我。【参考方案5】:

你可以在 Rails 3.1 中做到这一点。要序列化的对象必须回复loaddump 方法。

这是一个在 Base64 中序列化字符串的示例。

class User < ActiveRecord::Base
  class Base64
    def load(text)
      return unless text
      text.unpack('m').first
    end

    def dump(text)
      [text].pack 'm'
    end
  end

  serialize :bank_account_number, Base64.new
end

更多详情见:http://archives.edgerails.info/articles/what-s-new-in-edge-rails/2011/03/09/custom-activerecord-attribute-serialization/index.html

【讨论】:

详细信息链接现在似乎已失效,不幸的是。您将dumpload 定义为实例方法并将新实例传递给serialize 是否有原因?而不是将它们定义为类方法并将类传递给serialize?只是想了解一下,谢谢! 我在这里在黑暗中拍摄,但看起来 ActiveRecord 序列化将使用任何响应 :dump:load 的对象。所以不行。没有理由为什么这些是实例方法而不是类方法。【参考方案6】:

来自http://blog.quov.is/2012/05/01/custom-activerecord-attribute-serializers/

class Recipe < ActiveRecord::Base
  serialize :ingredients, IngredientsList
end

class IngredientsList < Array
  def self.dump(ingredients)
    ingredients ? ingredients.join("\n") : nil
  end

  def self.load(ingredients)
    ingredients ? new(ingredients.split("\n")) : nil
  end
end

【讨论】:

【参考方案7】:

我们刚刚发布了一个可以做到这一点的 gem (AttributeHelpers)。免责声明:我是 gem 的维护者。

它允许您在类定义中调用attr_symbol :gender,序列化会自动发生。

【讨论】:

以上是关于Rails 中字段的自定义序列化的主要内容,如果未能解决你的问题,请参考以下文章

与 Django 序列化程序上的自定义字段的 Swagger 兼容性?

序列化 DRF 中的自定义相关字段

Django Rest Framework 序列化程序中的自定义错误消息

如何在表单中编辑 Rails 序列化字段?

DRF中ManyToManyField的自定义序列化器和ViewSet [重复]

Golang中的自定义json序列化