How to Use Dot Syntax for Ruby Hash

Unable to use dot syntax for ruby hash

Hash does not have dot-syntax for it's keys. OpenStruct does:

require 'ostruct'
hash = {:name => 'John'}
os = OpenStruct.new(hash)
p os.name #=> "John"

NOTE: Does not work with nested hashes.

Access Ruby Hash Using Dotted Path Key String

Just split on a dot in the path and iterate over this to find the right hash?

path.split(".").inject(hash) { |hash, key| hash[key] }

Alternatively you can build a new hash by iterating recursively over the whole structure:

def convert_hash(hash, path = "")
hash.each_with_object({}) do |(k, v), ret|
key = path + k

if v.is_a? Hash
ret.merge! convert_hash(v, key + ".")
else
ret[key] = v
end
end
end

Ruby dot notation to nested hash keys

Try this

f = "root/sub-1/sub-2/file"   
f.split("/").reverse.inject{|a,n| {n=>a}} #=>{"root"=>{"sub-1"=>{"sub-2"=>"file"}}}

hash['key'] to hash.key in Ruby


>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>

Classic hash to dot-notation hash

Here's the cleanest solution I could come up with right now:

def dot_it(object, prefix = nil)
if object.is_a? Hash
object.map do |key, value|
if prefix
dot_it value, "#{prefix}.#{key}"
else
dot_it value, "#{key}"
end
end.reduce(&:merge)
else
{prefix => object}
end
end

Test:

input = {a: {b: {"1" => 1, "2" => 2}, d: "Something"}, b: {c: 1}}

p dot_it input

Output:

{"a.b.1"=>1, "a.b.2"=>2, "a.d"=>"Something", "b.c"=>1}

How to transform dot-notation string keys in a Hash into a nested Hash?

This code may need to be refactored but it works for the input you have given.

hash = { 
:axis => [1,2],
"coord.x" => [12,13],
"coord.y" => [14,15],
}

new_hash = {}
hash.each do |key, val|
new_key, new_sub_key = key.to_s.split('.')
new_key = new_key.to_sym
unless new_sub_key.nil?
new_sub_key = new_sub_key.to_sym
new_hash[new_key] = {} if new_hash[new_key].nil?
new_hash[new_key].merge!({new_sub_key => val})
else
new_hash.store(key, val)
end
end

new_hash # => {:axis=>[1, 2], :coord=>{:x=>[12, 13], :y=>[14, 15]}}

What does &. (ampersand dot) mean in Ruby?

It is called the Safe Navigation Operator. Introduced in Ruby 2.3.0, it lets you call methods on objects without worrying that the object may be nil(Avoiding an undefined method for nil:NilClass error), similar to the try method in Rails.

So you can write

@person&.spouse&.name

instead of

@person.spouse.name if @person && @person.spouse

From the Docs:

my_object.my_method

This sends the my_method message to my_object. Any
object can be a receiver but depending on the method's visibility
sending a message may raise a NoMethodError.

You may use &. to designate a receiver, then my_method is not invoked
and the result is nil when the receiver is nil. In that case, the
arguments of my_method are not evaluated.

How to make a chained dot notation work for nested hash keys using Ruby Metapraogramming

Your test doesn't work because conf.a2 returns a Hash (which doesn't respond to the message a3). I can't tell exactly what you're trying to accomplish, but it looks like you could make your tests pass by ensuring that whenever you return a value that would have been a Hash, that value becomes an instance of your Config class.

One thing that's odd, is you have defined attr_accessors for a flat list of names, but you're accessing the names in a structured way, not as the flat list you've defined.

If you want to access your configuration in a structured way, how about something like this? Trying not to depart too far from what you have:

class Config
def initialize(args)
if args.is_a? Hash
args.each do |k, v|
next if v.nil?

if v.is_a?(Hash)
instance_variable_set("@#{k}", Config.new(v))
else
instance_variable_set("@#{k}", v)
end
end
else
raise ArgumentError, "Invalid argument. Supply a Hash instead of #{args.class}"
end
end

def method_missing(name, *args)
if name.to_s.end_with?('=')
instance_variable_set("@#{name.to_s.sub(/=$/, '')}", *args)
else
instance_variable_get("@#{name}", *args)
end
end
end


Related Topics



Leave a reply



Submit