You've been hired as a senior Ruby developer in the new hottest startup that is building a really big thing. Obviously, they have selected microservices architecture which will require holding and accessing tons of configuration values. This is where you step in as you've been assigned a task to show your exceptional skills in Ruby metaprogramming to develop a flexible class capable of storing absolutely any config value.
Implement the Config
class that takes a hash in a constructor:
conf = Config.new(foo: {bar: "x", "baz" => "y"}, "some" => "other")
and which then allows to read the values as follows:
conf.foo.bar
=> "x"
conf.foo.baz
=> "y"
conf.some
=> "other"
conf.foo.class
=> Config
conf.unknown
=> nil
The Config
class also allows to override the values and assign new values:
conf.foo = 13
=> 13
conf.foo
=> 13
conf.foo = {bar: 18, "baz" => [30, 31]}
=> {:bar=>18, "baz"=>[30, 31]}
conf.foo.bar
=> 18
conf.foo.other = ["42", "44"]
=> ["42", "44"]
conf.foo.other
=> ["42", "44"]
In case of invalid hash key usage, we should raise an ArgumentError:
conf.foo = {10 => 11}
ArgumentError (Invalid value name: {})
The internal implementation of the Config class is totally up to you as long as it behaves as in the code samples above. However, you may not use any external libraries (your CTO is a security nerd) and your tech lead forbids using the OpenStruct
class for the reasons only known to him.
We have provided some really basic test coverage for the Config class, so you can test some happy paths. Please feel free to add your own tests.
Good luck!