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 中做到这一点。要序列化的对象必须回复load
和dump
方法。
这是一个在 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
【讨论】:
详细信息链接现在似乎已失效,不幸的是。您将dump
和load
定义为实例方法并将新实例传递给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 兼容性?
Django Rest Framework 序列化程序中的自定义错误消息