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

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

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

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

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

【问题讨论】:

    标签: ruby-on-rails ruby serialization


    【解决方案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,序列化会自动发生。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 2017-02-04
        • 2018-06-27
        • 1970-01-01
        • 2010-11-27
        • 2015-01-27
        • 2020-07-19
        • 1970-01-01
        相关资源
        最近更新 更多