Given how expressive Ruby is, I’m wondering if anyone has ever tried to create a class or module that will mimick JS object syntax. For instance, in JS I can of course do this:
[1] var obj = {a: 'b'};
[2] obj.c = 'd';
[3] obj.a = 123
[4] obj['e'] = 'f';
[5] obj.e = obj['a']
In Ruby I can, as of now, have code that will permit me to do something like this:
[1] obj = {'a' => 'b'}.to_js
[2] # obj.c = 'd' << This is what I can't solve, 'c' is first defined here.
[3] obj.a = 123;
[4] obj['e'] = 'f'
[5] obj.e = obj['a']
As long as I get a symbol through square brackets or on initialization, I can easily store the K/V pair and create instance methods for the setters and getters.
However, I haven’t been able to figure out how to create an object that will respond to ‘c’ if it’s not defined, then do some magic. For instance,
- I can iterate over the hash coming in, and set up accessors
- I can use
[]=(k, v)for the bracket notation and do the same thing.
My progress in the second style up to this point.
There’s a very specific Object#respond_to_missing? which can take a specific symbol in it; but can’t respond in the general case.
There’s three possible ways that I can think of solving the commented out, second invocation style:
- Make the object not an instance of a class but a Method at all times. For instance, the following works:
class A def b; puts 'c'; end end def always A.new end c = always c.b
Given this, there may be a possible way to do some kind of error catching and then hook the object accordingly.
-
Utilize some fantastic ruby feature that I haven’t heard of. Ruby is such a rich language, this may already be quite easy.
-
Override the error handling mechanics somehow. I don’t have any idea how someone would do this in the large general case, but basically you’d be telling ruby that if any instance of some class failed to respond to a method, you’d have some generalized handler to deal with things.
Anyway, if anyone has any idea here, it would be a pretty fun exercise I think. Thanks!
Probably better ways of doing this:
If you want to subclass, than you can do this:
I’ll keep this open for a while in case someone else has an idea of a better way here.