RStruct as Hash Deserializer for ActiveRecord

RStruct Can be used as your De-Serializer for JSON type data in Postgres

class HashSerializer
  def self.dump(hash)
    hash.to_json if hash.present?
  end

  def self.load(hash)
    RStruct.new(hash) if hash.present?
  end
end
Advertisements

Recursive OpenStruct in Ruby with nested Array of Hashes

Hey do you want to have your Hashes with collection/Array of Hashes more object oriented but along with it want it to behave as it was before?. Well you can use my library to do so. I have used the Ruby’s native OStructOStruct Library. RStruct Can be used as your De-Serializer for JSON type data in Postgres.

# This only supports Hashes inside Hashes
class RStruct
  # @author Shiva Bhusal
  # @blog cbabhusal.wordpress.com
  # Recursive OpenStruct
  # #
  def self.new(object)
    if object.is_a?(Hash)
      object = object.clone
      object.each do |key, value|
        object[key] = new(value)
      end
      OpenStruct.new(object)
    else
      object
    end
  end
end

Example:

> a = {l1: {l2: {name: 'shiva', name_is_valid?: true}}}
 => {:l1=>{:l2=>{:name=>"shiva", :name_is_valid?=>true}}}
> aa = RStruct.new(a)
 => #<OpenStruct l1=#<OpenStruct l2=#<OpenStruct name="shiva">>> 
> aa.l1.l2.name
 => "shiva"
> aa.l1.l2.name_is_valid?
 => true

For Arrays of Hashes inside the Hashes

class RStruct
  # @author Shiva Bhusal
  # @blog cbabhusal.wordpress.com
  # Recursive OpenStruct
  # #
  def self.new(object)
    if object.is_a?(Hash)
      object = object.clone
      object.each do |key, value|
        object[key] = new(value)
      end
      OpenStruct.new(object)
    elsif object.is_a?(Array)
      object.map do |item|
        new(item)
      end
    else
      object
    end
  end
end

For usage with Rails’s AController::Parameter

class RStruct
  # @author Shiva Bhusal
  # @blog cbabhusal.wordpress.com
  # Recursive OpenStruct
  # #
  def self.new(object)
    if object.is_a?(Hash)
      object = object.clone
      object.each do |key, value|
        new_value = value.to_hash.with_indifferent_access rescue value
        object[key] = new(new_value)
      end
      OpenStruct.new(object)
    elsif object.is_a?(Array)
      object.map do |item|
        new(item)
      end
    else
      object
    end
  end
end

Usages

> data = {key1: [{sub_key1: 'value1'}]}
 => {:key1=>[{:sub_key1=>"value1"}]}
 > structured_data = RStruct.new(data)
 => #<OpenStruct key1=[#<OpenStruct sub_key1="value1">]>
 > structured_data.key1.first.sub_key1
 => "value1"

 

And if you are trying to re-struct the data from Stripe Objects then you may want to modify the code like

if object.is_a?(Hash)
  object = object.clone
  object.each do |key, value|
    new_value = value.to_h rescue value
    object[key] = new(new_value)
  end
  OpenStruct.new(object)