Rails : Consider the view as stupid

It’s not a secret, putting business logic inside a view is a bad idea. Views should only contain HTML and presentation logic.

This is bad :

This is better :

This is VERY bad :

this is better :

Consider the view as your most stupid MVC component (I’m sorry, view. I didn’t want to make you cry). Aside from “if” and “each”, the “V” component just doesn’t understand ruby code that much. That’s why you should set convenient instance variables in the controller that the view will find easy to use. When the view is rendered, every business rules must already have been resolved in the controller. The view don’t want to think by itself, it wants to be instructed what to do.

Moreover, a view should never interract with a model. The view is completely clueless about database related stuff. When it wants to know what to display, it queries the variables that have been set by the controller (with it’s very limited ruby knowledge) and expects a simple yes/no answer.

When the view needs to iterate through a collection, that collection must have been created and tested by the controller. The view just knows how to loop and how to display stuff, not how to fetch data.

I know that all of this may be pretty basic stuff to you, but sometimes it can be tempting to make a view looks more intelligent than it should. Views shine when they are clueless and stupid about everything that isn’t related to presentation in the same way that models shine when they are clueless and stupid about the application flow. When you think about it, the remaining component is the only smart guy out there. The controller knows how to query the model and how to prepare instance variables that will be consumed by the not so smart view. In fact, the controller is the only component able to see “the big picture”.

So let’s keep our views simple and stupid!

#UPDATE 04/28/2007
Dan and Alan made me realize that I didn’t talk about helpers. Helpers are indeed very handy when you want to keep your view clueless about all the nitty gritty details of your application. Instead of letting the view works by itself, it can remain lazy and instead call services (helpers) that will do all the complicated stuff and return a nice and ready to display result.

Are you concerned about ruby being slow?

This is a real question, I’d like to hear your opinion on this matter.

Ruby is known to be slow, even compared to other interpreted languages like python. It’s sad, but it’s true. Does it bother you? Well, don’t be shy, i’ll answer first : it bothers me. You probably heard of the recent twitter performance issues. Well, it appears that ruby is partly blamed for this. Of course, there are probably some implementation details that could be improved in this application (just speculating here) and Rails itself should also take a good part of the blame (e.g. some ActiveRecord features are known to be costly on the performance side of things). But for now let’s forget about Rails costly features and let’s focus on the programming language behind it.

We cannot hide behind hardware-is-becoming-so-performant-and-cheap-that-it-doesnt-matter kind of excuses anymore. While it’s true that buying better and faster hardware will mask the fact that ruby is inefficient, it seems like we’re just trying to put a plaster on the real problem. Ruby performance shortcomings must be addressed at it’s heart, that is, in the source code of it’s official interpreter.

Could YARV be the saving grace?

What is YARV? YARV is another virtual machine for Ruby like are JRuby, Rubinus and the official interpreter written in C (ruby 1.8). In other words, it’s simply another implementation of the programming language we love. YARV humorously stands for Yet Another Ruby VM. The smart guy behind this project is SASADA Koichi and his goal with YARV is crystal clear. Like he said : The goal of this project is only one, to develop the fastest Virtual Machine for Ruby in the world.

Is it faster than, say, JRuby? I don’t know, but I know what I like the most about it : YARV is expected to get merged into the official implementation of the language. What does it means? It means we would still be able to call ourselves rubyists and not yarvers (phew). Big deal huh? This detail aside, I think it is quite important that the official interpreter stops being qualified as the worst of all. For a lot of people (myself included), the official ruby interpreter IS ruby (we can hardly blame us for wanting to use “the real thing”, can we?). To me, the importance of having an official virtual machine that is efficient is crucial.

Now, I have two questions for you :

  1. Are you concerned about ruby being slow?
  2. Do you have faith in YARV?

Enumerations and Ruby

Enumerations are an elegant way to make your code more readable. Unfortunately, Ruby doesn’t have a built-in enum type. However, if you only want to use an enumeration like a set of constants logically grouped, it’s super easy to do. You only have to create a class and define constants in it :

If you need a more elaborate enum, that is, if you want to iterate through every items like if it was a collection, you’ll have some more work to do (but not that much) :

Basically, we just used a hash in our class to make our enum behave like a collection.

  1. The add_item method is used to fill the hash and is called inside the class because we don’t want to give that responsability to the user of our enum. You’ll note that the calls to add_item are directly in the body of the class instead of being in the initialized method. That is because initialized is only called when you create an instance of a class (x = MyClass.new) and we don’t need instances of class Color.
  2. the const_missing method is used for convenience. We want to use Color::BLUE, not Color.the_internal_hash[:BLUE]. const_missing is called automatically when you try to access a constant that doesn’t exists. We then use that hook to return the hash element corresponding to the name supplied. We take for grant that this “missing constant” is in fact the desired key for our hash.
  3. We defined an iterator “each” to iterate through the collection. We could also have created an attribute reader that returns the hash and let the user of our class iterate from there. (like that : Color.items.each do …)
  4. We don’t create instances of class Color because we don’t need to. Everything happens at the class level, or if you prefer, in the object called Color. I could have enforced that behavior by preventing (if such a thing exists in ruby) users to create instances of that class, but I don’t think it was essential.
  5. In a recent article, I said that it wasn’t useful to use an instance variable (@) inside a class method. Well, this example demonstrates that it isn’t strictly true. If your class is also the only instance you need, variables that only live in this instance are useful.