fbpx logo-new mail facebook Dribble Social Icon Linkedin Social Icon Twitter Social Icon Github Social Icon Instagram Social Icon Arrow_element diagonal-decor rectangle-decor search arrow circle-flat
Development

Avoiding Instance Variable Pain in Rails Controllers and Views

Michael Crismali Tandem Alum

last updated March 22, 2018

Some Rails patterns are so ingrained in us that we don’t think about them anymore. That’s sort of the point of the whole “convention over configuration” thing and it’s great. I don’t want to think about unnecessary things if I don’t have to so I can focus building the best application I can.

All that said, it’s important to step back every so often and reevaluate all of these second nature tendencies and see where we can improve. To that end, I think it’s time we reconsider our use of raw instance variables in Rails controllers and templates.

Ever since I started writing Rails, the pattern has always been the same: Assign an instance variable in the controller, use that instance variable in the view. It’s all over the Rails guides. Here’s a quick example.

https://gist.github.com/crismali/7708f2d2f7fe464c23f205eda68598b1

Did you see the problem(s)? They’re subtle, even in this small example.

…Okay, spoiler alert: The instance variables are misspelled. 😭

Each of the templates will end up raising NoMethodError for calling each/description on nil. Not the worst problem given that our templates are so small, but what if we just didn’t have that problem? Let’s rewrite this to use attr_accessor to avoid instance variables in our controller and helper_method so we can avoid them in our templates:

https://gist.github.com/crismali/6baf8997ff8b743444954800767c9a3e

Now our typos still raise NoMethodError, but now the error tells use that prodcut and prdoucts aren’t methods on our view and gives us the line number of our typo. It even gives us the handy did-you-mean-style error! 🎊

Now let’s fix our typos…

https://gist.github.com/crismali/6baf8997ff8b743444954800767c9a3e

Now we have a few pros here:

  • Better errors when we make mistakes
  • We can also see what the templates use at the top of our controller (assuming we don’t also sprinkle in instance variables in the other controller actions)
  • We can also limit what our views can get at by just omitting a getter from the helper_method list. This is handy when you just want to avoid instance variables for information that’s only used by actions and/or their hooks (before_action, after_action)

A couple cons:

  • Less conventional
  • Between self. and the declarations at the top we have to type more
  • We could make a mistake and mix up our product and products methods, but instance variables have this same problem 🙃

At the end of the day, it’s a small change to help avoid a small problem. If you don’t mind being a little less conventional, give it a shot. If not, that’s a fair tradeoff. As always, the important thing is that you follow your ❤.

Let’s do something great together

We do our best work in close collaboration with our clients. Let’s find some time for you to chat with a member of our team.

Say Hi