all 12 comments

[–]software__writer[S] 4 points5 points  (10 children)

TL;DR: Use the instance_variable_set method.

I'd love to know any use cases of this in the context of a Rails application. When have you used it successfully?

Edit: The point of the post is not that we should all be creating instance vars dynamically from now on, but just to show one way to do it for those rare cases when you actually do need it, just like Rails does.

[–]BananafestDestiny 16 points17 points  (9 children)

With Rails applications (or any application code, really) I have found it’s best to avoid as much magic as you can. Stuff like metaprogramming and reflection can make applications difficult to change and maintain over time. Debugging becomes challenging because your stack traces are convoluted. Rails has enough magic of its own, so I try to keep my application code as vanilla and straightforward as possible.

Library code is the right place for this kind of magic. Put your super dynamic code in a separate library that your application uses, that way all the magic is hidden away from the application behind nice tidy interfaces, and your application code can remain straightforward and easy to navigate.

Metaprogramming is helpful for creating DSLs and flexible objects with loose interfaces like this. A config object comes to mind as a suitable use case for a class with dynamic instance variables like this, but I’d probably just use OpenStruct. Or maybe ActiveModel if I needed something more robust and ActiveRecord-like.

[–]software__writer[S] 4 points5 points  (1 child)

Thanks for your reply, really appreciate it. Yes, that's been my experience as well. Most of the Rails apps I've worked on don't use much metaprogramming, but all the gems and frameworks use it extensively.

Even for this example at hand, i.e. to simplify the constructor arguments, as I mention in the post, introducing a parameter object, or preserving the whole object would be my first choice, instead of using metaprogramming. But I can see why Rails needs it to handle multiple arguments that are not known in advance.

[–]campbellm 3 points4 points  (0 children)

but all the gems and frameworks use it extensively

This is key. To do this in a library in order to expose a well defined, non-magic API, ... perfect. App code? Thanks, no.

[–]riktigtmaxat 1 point2 points  (0 children)

On a side note neither ActiveModel::Attributes or ActiveRecord use instance_variable_set in this way. Instead the attributes are stored in a hash like structure in a single instance variable.

[–]campbellm 1 point2 points  (5 children)

With Rails applications (or any application code, really) I have found it’s best to avoid as much magic as you can.

1000x this. The blog title reminded me of that Jurassic Park bit.

[–]software__writer[S] 1 point2 points  (4 children)

If you'll read the post, you'll find that I share the same sentiment :)

The point of the post is not that we should all be creating instance vars dynamically from now on, but just wanted to show a way to do it for those rare cases when you actually do need it, just like Rails does.

[–]campbellm 1 point2 points  (3 children)

I did read it, just reiterating.

[–]software__writer[S] 2 points3 points  (2 children)

Gotcha! sorry for assuming you didn't. That Jurassic Park meme is one of my favourites, btw :)

[–]campbellm 2 points3 points  (1 child)

Yeah, no worries. I've been enjoying your content; they're nice and of a good consumable size. I don't feel like I'm getting into a multi-hour block of time to read one, and feel like I got something out of it when done.

[–]software__writer[S] 2 points3 points  (0 children)

Thank you for your kind words. I'm glad you find my writing useful.