Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 3.82 KB | None | 0 0
  1. module ActiveRecord
  2.   module AttributeMethods
  3.     module Serialization
  4.       extend ActiveSupport::Concern
  5.  
  6.       included do
  7.         # Returns a hash of all the attributes that have been specified for serialization as
  8.         # keys and their class restriction as values.
  9.         class_attribute :serialized_attributes
  10.         self.serialized_attributes = {}
  11.       end
  12.  
  13.       class Attribute < Struct.new(:coder, :value, :state)
  14.         def unserialized_value
  15.           state == :serialized ? unserialize : value
  16.         end
  17.  
  18.         def serialized_value
  19.           state == :unserialized ? serialize : value
  20.         end
  21.  
  22.         def unserialize
  23.           self.state = :unserialized
  24.           self.value = coder.load(value)
  25.         end
  26.  
  27.         def serialize
  28.           self.state = :serialized
  29.           self.value = coder.dump(value)
  30.         end
  31.       end
  32.  
  33.       module ClassMethods
  34.         # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
  35.         # then specify the name of that attribute using this method and it will be handled automatically.
  36.         # The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
  37.         # class on retrieval or SerializationTypeMismatch will be raised.
  38.         #
  39.         # ==== Parameters
  40.         #
  41.         # * +attr_name+ - The field name that should be serialized.
  42.         # * +class_name+ - Optional, class name that the object type should be equal to.
  43.         #
  44.         # ==== Example
  45.         #   # Serialize a preferences attribute
  46.         #   class User < ActiveRecord::Base
  47.         #     serialize :preferences
  48.         #   end
  49.         def serialize(attr_name, class_name = Object)
  50.           coder = if [:load, :dump].all? { |x| class_name.respond_to?(x) }
  51.                     class_name
  52.                   else
  53.                     Coders::YAMLColumn.new(class_name)
  54.                   end
  55.  
  56.           # merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy
  57.           # has its own hash of own serialized attributes
  58.           self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder)
  59.         end
  60.  
  61.         def initialize_attributes(attributes, options = {}) #:nodoc:
  62.           serialized = (options.delete(:serialized) { true }) ? :serialized : :unserialized
  63.           super(attributes, options)
  64.  
  65.           serialized_attributes.each do |key, coder|
  66.             if attributes.key?(key)
  67.               attributes[key] = Attribute.new(coder, attributes[key], serialized)
  68.             end
  69.           end
  70.  
  71.           attributes
  72.         end
  73.  
  74.         private
  75.  
  76.         def attribute_cast_code(attr_name)
  77.           if serialized_attributes.include?(attr_name)
  78.             "v.unserialized_value"
  79.           else
  80.             super
  81.           end
  82.         end
  83.       end
  84.  
  85.       def type_cast_attribute_for_write(column, value)
  86.         if column && coder = self.class.serialized_attributes[column.name]
  87.           Attribute.new(coder, value, :unserialized)
  88.         else
  89.           super
  90.         end
  91.       end
  92.  
  93.       def _field_changed?(attr, old, value)
  94.         if self.class.serialized_attributes.include?(attr)
  95.           old != value
  96.         else
  97.           super
  98.         end
  99.       end
  100.  
  101.       def read_attribute_before_type_cast(attr_name)
  102.         if serialized_attributes.include?(attr_name)
  103.           super.unserialized_value
  104.         else
  105.           super
  106.         end
  107.       end
  108.  
  109.       def attributes_before_type_cast
  110.         super.dup.tap do |attributes|
  111.           self.class.serialized_attributes.each_key do |key|
  112.             if attributes.key?(key)
  113.               attributes[key] = attributes[key].unserialized_value
  114.             end
  115.           end
  116.         end
  117.       end
  118.     end
  119.   end
  120. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement