Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby access propteries with dot-notation

Tags:

ruby

I'm trying to build a class that will basically be used as a data structure for storing values/nested values. I want there to be two methods, get and set, that accept a dot-notated path to recursively set or get variables.

For example:

bag = ParamBag.new
bag.get('foo.bar') # => nil
bag.set('foo.bar', 'baz')
bag.get('foo.bar') # => 'baz'

The get method could also take a default return value if the value doesn't exist:

bag.get('foo.baz', false) # => false

I could also initialize a new ParamBag with a Hash.

How would I manage this in Ruby? I've done this in other languages, but in order to set a recursive path, I would take the value by reference, but I'm not sure how I'd do it in Ruby.

like image 487
alex-phillips Avatar asked Oct 23 '25 15:10

alex-phillips


1 Answers

This was a fun exercise but still falls under the "you probably should not do this" category.

To accomplish what you want, OpenStruct can be used with some slight modifications.

class ParamBag < OpenStruct
  def method_missing(name, *args, &block)
    if super.nil?
      modifiable[new_ostruct_member(name)] = ParamBag.new
    end    
  end
end

This class will let you chain however many method calls together you would like and set any number of parameters.

Tested with Ruby 2.2.1

2.2.1 :023 > p = ParamBag.new
 => #<ParamBag> 
2.2.1 :024 > p.foo
 => #<ParamBag> 
2.2.1 :025 > p.foo.bar
 => #<ParamBag> 
2.2.1 :026 > p.foo.bar = {}
 => {} 
2.2.1 :027 > p.foo.bar
 => {} 
2.2.1 :028 > p.foo.bar = 'abc'
 => "abc" 

Basically, take your get and set methods away and call methods like you would normally.

I do not advise you actually do this, I would instead suggest you use OpenStruct by itself to acheive some flexibility without going too crazy. If you find yourself needing to chain a ton of methods and have them never fail, maybe take a step backwards and ask "is this really the right way to approach this problem?". If the answer to that question is a resounding yes, then ParamBag might just be perfect.

like image 81
yez Avatar answered Oct 25 '25 14:10

yez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!