Active Record Attribute Serialization with Custom Class
When we were porting our old application to a brand new ruby stack keeping the underlying database intact. We could use rails active record serialization feature quite intensely. Here is a simple example -
We had a string attribute "width" which was expecting value something like this "10 Inches" or "20 Cm".
Previously it was manually taking two separate inputs and concatenating them together and store them in a single string attribute.
We have remade the same thing but in bit better way using ActiveRecord serialization, here goes the code -
class SomeModel < ActiveRecord::Base
serialize :width, ValueAndUnit
end
Serializer class which dumps and loads the data based on our expected format -
class ValueAndUnit
attr_reader :value, :unit
def initialize(value = nil, unit = nil)
@value, @unit = value, unit
end
class << self
# Load serialized data into the model scope with our expected transformation.
# ie. we expect successful execution could return ValueAndUnit instance from width method.
#
# @return [ValueAndUnit] The instance of ValueAndUnit from cleaned out string data.
def load(data)
# Make sure data is compliant with our expected data format
if data.present? && (matched_data = data.match(/([\d.]+)\s+(.+)/))
self.new(matched_data[1], matched_data[2])
else
self.new
end
end
# Dump the ValueAndUnit instance into the storable (serialized) format. In our case we want it to be stored as "{value} {unit}" ie. "10 Inches".
#
# @return [String] The transformed string representation of the data.
def dump(data)
data.to_s
end
end
def to_s
"#{self.value} #{self.unit}"
end
end
Here goes few sample usages -
record = SomeModel.new
record.width.unit = 'Inches'
record.width.value = 10
record.save
While we are pulling an existing record
record = SomeModel.find(1)
puts record.width.unit # => 'Inches'
puts record.width.value # => '10
Written by nhm tanveer hossain khan (hasan)
Related protips
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Ruby
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#