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)
Reblogged this on sushil10018.
LikeLiked by 1 person
I just tried out and this way could be more efficient? but it’s shorter at least. 😀
class Rstruct
def self.new(hash)
hash.each do |x,v|
if v.is_a? Hash
hash[x] = self.new(v)
elsif v.is_a? Array
v.each do |vv|
hash[x] = []
hash[x] << self.new(vv)
end
end
end
OpenStruct.new(hash)
end
end
LikeLike