Advertisement
  1. Code
  2. Coding Fundamentals
  3. OOP

AntiPatterns Basics: Rails Views

Scroll to top

In this beginner-friendly series, we’re looking at AntiPatterns, which—as the name implies—represent pretty much the opposite of design patterns. They are discoveries of solutions to problems that you should definitely avoid.

In this article we’ll focus on the main View AntiPattern—PHPitis—and work through a couple of techniques to keep your views lean and mean. Having tons of Ruby code in your views is not only nasty but often plain unnecessary.

Topics

  • Rails Views
  • PHPitis
  • Extracting Helpers
  • Helpful Helpers
  • Forms
  • Partials
  • Conditional Content
  • Semantic Markup

Rails Views

Rails comes with ERb (Embedded Ruby) out of the box, and I think it’s not necessary to throw in cool view-rendering engines like Slim for our examples for now. If you think “convention over configuration” mostly applies to the model and controller layers, you are missing out on a lot of the goodies that make working with Rails so speedy and progressive. Taking good care of the view layer includes not only the way you compose your markup but also CSS/Sass, JavaScript, view helpers, and your layout templates. Viewed from that angle, it becomes a bit deeper than you might think at first. The sheer number of technologies which can be involved in creating your views suggests that care should be taken to keep things neat, clear and flexible.

Since the way we write markup and styles is a lot less constrained than domain modeling, you want to be extra cautious to keep things as simple as possible. Maintenance should be pretty much your number one priority. Since redesigns or design iterations can be more frequent than extensive changes to your model layer, preparing for change gets a whole new meaning when it comes to your user-facing layer. My advice: don’t necessarily build for the future, but also, by all means, do not underestimate the rate of change—especially if you have one of those “idea guys” who knows jack about implementations on the team. What I like about Rails’s approach towards views in MVC is that it is treated as equally important, and the lessons learned from the model domain were incorporated into the view—whenever possible and useful. Other frameworks seem to agree, since they integrated a lot of these ideas pioneered by Rails.

Since the last article was a bit more extensive, I chose this topic as a small breather. The following articles about Rails controllers and testing are again bigger in size. The AntiPatterns for views are not that many, but they are nevertheless equally important. We’ll focus on the main one, PHPitis, and work through a couple of techniques to keep your views lean and mean. Since the view is your presentation layer, maybe you should be especially careful to not create a hazardous mess. Let’s get to it!

PHPitis

Why do we have MVC in the first place? Yes, because the separation of concerns seemed like the most reasonable thing to do. Sure, the implementations of this idea vary a bit here and there, but the overall concept of having distinct responsibilities for each layer is the core motivation for building robust applications. Having tons of code in your view layer might not be alien to developers coming from the PHP side of things—although I hear their frameworks have caught up already (heavily influenced by things like Rails?)—but in Ruby-land these things have long been a loudly voiced AntiPattern.

The obvious problems like mixing responsibilities and duplications aside, it simply feels nasty and lazy—a little stupid too, to be frank. Sure, I get it, when you develop much within a framework, language or whatever ecosystem, it’s easy to become complicit or numb towards things like that. What I like about the people pushing Ruby is that these things seem to have a lot less weight—that might be a reason why innovating never seemed to be a problem within the community. Whatever works best wins the argument, and we can move forward.

So is this a whole section dedicated to bashing PHP? Not at all! In the past, PHP apps had the reputation of having weak separations between models, views and controllers (maybe this was one of the core reasons why people felt writing apps with Rails was much more appealing). Having single files with code for all three layers didn’t seem that sexy. So when we stuff tons of Ruby or domain code into our views, it starts to look like the dreaded PHP style of structuring things—PHPitis. Only a few things are as bad as this when it comes to developing web apps, I feel. When you care about happy developers and your own future sanity, I can’t see why anyone would go down that road—there’s only pain ahead, it seems.

Rails offers a lot of goodies to minimize code in the view as much as possible. You must learn the ways of helpers, layouts and preprocessors in order to achieve a cleaner view. A simple rule of thumb is to keep domain logic out of your views—no shortcuts!

The price to pay for being lazy on this is hard to overestimate. The Ruby code that must be in the presentation layer should be as little and as simple as possible, as well as intelligently organized. Your reward will be code that is a joy to extend and to maintain, and new team members will also have an easier time wrapping their heads around the new codebase. As a bonus, neat freak designers who code also won’t be angry and hide rotten food in your salad if you keep tons of Ruby code out of their markup.

Helpful Helpers

Knowing the myriad of helper methods in Rails will significantly improve the quality of your presentation layer. Not only will it clean things up and inject the occasional speed boost in productivity, but more importantly it helps you fight PHPitis.

The thing that you should appreciate about these helpers is that they represent extractions from commonly needed code. Instead of reinventing the wheel, when in doubt, check if there isn’t already a helper around that solves your issue in the view—the same goes for Models and Controllers as well, of course.

Here’s a list of helpers you should look into pretty much right away:

  • Other helpers for forms.
  • And writing your very own, of course.

Forms

Let’s have a look at <pre class="brush: form_for"></pre> first. I know forms are a little bit boring and not that sexy for a topic, but I highly encourage you to read up on them to familiarize yourself with the finer details. It’s important to understand how they work. I remember often just glancing over them without giving them much attention. Sure, you can get them to work quite easily without understanding what’s going on under the hood. In the future, I might take the time to write a complete article on them. In the meantime, I highly recommend that you spend a little time checking the documentation–at least you‘ll appreciate how convenient Rails makes it to deal with form stuff.

The Ugly

The example below shows you the HTML of a little form we need for creating agents. It only accepts three parameters as input: <pre class="brush: name"></pre>, <pre class="brush: number"></pre> and <pre class="brush: licence_to_kill"></pre>. A lot of code for this little task, actually. The <pre class="brush: authenticity_token"></pre> comes from Rails–it’s a security thing that protects the app from “cross-site request forgery”.

some.html.erb
1
2

Writing a form by hand is not only lengthy but error prone as well. Also, if we approached it that way, we’d also have to solve the issue with the varying routes and CSS classes that we might need for creating a new object and updating an existing one—in effect, we would need to duplicate forms to create and edit records. As you’ll see soon, Rails meets you more than halfway on that. Verdict: however you put it, the manual approach is nasty and lacks convenience.

The Bad

We could go down the following road, which does not make perfect use of conventions in Rails. Heads up, don’t do it. It basically shows that you’re not handling the available tools to your advantage and you are duplicating the form for <pre class="brush: new"></pre> and <pre class="brush: edit"></pre> actions.

some.html.erb
1
2
3
4
5
  
6
  
7
8
  
9
  
10
11
  
12
  
13
14
  
15
16
17

What happens here is that the form builder carries the model you need for the form.

1
2
3
4

Behind the scenes, the line above gets expanded into the following:

1
2
3
4

The <pre class="brush: form_for"></pre> method takes a couple of arguments:

  • a symbol or a string for specifying the object
  • a <pre class="brush: url"></pre> hash
  • an <pre class="brush: html"></pre> hash
  • a <pre class="brush: namespace"></pre> hash

The url hash is for specifying the routing options. That means that you can manually specify to which routing path you submit the form—named routes come in handy with this. This style is called the “generic way” because you need to manually configure the <pre class="brush: form_for"></pre> call.

Why is this solution suboptimal? Because we want to keep business logic out of our Views and Controllers as much as we can. A side effect of that is that we need to change fewer parts when needed.

HTML
1
2

In case you missed it, this approach did not provide us with ids and classes for the <pre class="brush: form"></pre> tag automatically. The ones for <pre class="brush: input"></pre> tags, however, were generated for you. We’ll fix that in a minute. Just know what you can get for free and that you probably should use this to your advantage. If you need something different or an additional namespace, you can use the <pre class="brush: html"></pre> hash or the <pre class="brush: namespace"></pre> hash to specify things a bit more.

some.html.erb
1
2
3
4
HTML
1
2

Not bad! Now the <pre class="brush: form"></pre> tag has the specified class and id—whatever makes your blood flow—and the <pre class="brush: input"></pre> tags are namespaced with <pre class="brush: mi6"></pre>. Almost there.

The Good

This one is called the “resource-oriented style” and has the least amount of Ruby you need to write in your views. With that approach, we want to rely on automated resource identification. Rails figures out which routes it needs based on the object itself. Not only that, it gives you a different HTML output for creating a new object or for editing an existing one. Behind the scenes, Rails just asks the object if it already exists and acts accordingly.

Creating forms this way is a clever use of conventions and helps avoid duplication. One line and all the heavy lifting is done for you.

some.html.erb
1
2
3
4
5
  
6
  
7
8
  
9
  
10
11
  
12
  
13
14
  
15
16
17

Much better, isn’t it? Now we get exactly what we need for both existing and new objects. Also, we didn’t need to add text to our submit button. Rails took care of that and also adapts to new or existing objects.

HTML for a New Object
1
2
HTML for Editing Objects
1
... When editing objects, it is also reflected in the HTML output by adding the id to the form id and the route or action needed for updating a specific object. A word about Rails magic. When people argue in exactly these situations that Rails is too magical for their taste, I often think that this could simply mean that they haven’t spent enough time learning the tools of their trade. Once you take the time to master these tools, you’ll often understand why a simplification or extraction was made, and they also appear a lot more sober and straightforward. #### Attention! The code examples above used
as a block parameter. This is not recommended best practice but was done to remind you what this object represents and what gets yielded from
. Most people just use a plain ```|f|
1
 
|form|```, which looks much nicer and more concise. By the way, things like
,
,
and the like are just helper methods that are called on the form builder object. There are a ton of them which cover pretty much any possible need you might encounter. ###### some.html.erb
1
2
3
4
5
  
6
  
7
8
  
9
  
10
11
  
12
  
13
14
  
15
16
17
Concise and reads nice, right? ### Partials Collections are another thing we don’t want to be too verbose about. Rendering partials for individual objects of collections is so concise and straightforward—if done right—that I feel you have very little excuse for not making use of Rails conventions to reduce Ruby view code. Let’s turn things around with this one and start with an example that shows you how you are encouraged to approach this. Along the way, I’ll explain what you can leave out as well. #### The Good ###### app/views/agents/index.html.erb
1
2
3
4
The
method is quite smart. The line above is all you need to write for iterating over a collection. If you need to change something in this view, it will be a very small change—and therefore a small cause of error. What happens here is that the framework is able to determine which partial it needs. Through the name of the object, it knows where to look for the partial—given that you adhere to the conventional naming of things. The way I see it, this is a good example of how Rails is not trying to impress you with wizardry. The Rails team works hard to make your life easier by cutting through repetitive red tape of sorts. ###### app/views/agents/_agent.erb
1
2
3
Agent name: 
4
Licence to kill: 
5
Number: 
6
Gambler: 
7
Womanizer: 
8
The only other thing that is necessary to make this work is to place a partial template at the appropriate path in your object’s directory and extract the attributes you need from the object. No need to write any loops on your own. It's fast and easy, handy and pragmatic, I’d say. This extraction was originally done because the name of the partial was most of the time the name of the iterated object anyway, and so it was easy to create a convention that handles this common task more effectively. #### The Bad OK, now that we know how to handle this, let’s look what you could and should avoid. The example below is just a bad usage of Rails, but I wouldn’t call it ugly this time. ###### app/views/agents/index.html.erb
1
2
3
4
  Agent name: 
5
  Licence to kill: 
6
  Number: 
7
  Gambler: 
8
  Womanizer: 
9
10
You get the same result as above, but it’s definitely more verbose. Iterating over the collection in the view is not necessary anymore. When you use
as above, the block parameter
is implied, and you can just use it without the
loop. So stay away from code like this—it does not make you look particularly good (but nobody will collect your head for it either). It’s just not elegant and adds to the PHPitis. ### Extracting Helpers The most obvious solution for cleaning up code from your views is to avoid writing any or to extract them intelligently. Let’s say we want to scramble the names of our agents in the index list. We should not put this code directly in our views. If we decide that the model is also not the appropriate layer to place this, then a custom helper in the
1
/helpers
directory might be the right choice. ##### app/helpers/agents_helper.rb
1
2
3
module AgentsHelper
4
  def scramble(agent)
5
    agent.name.split('').shuffle.join
6
  end
7
end
8
By packaging this in a module inside the helpers directory, we now have access to this method in our views. Please give specific helpers their own home, and don’t put everything on
(
1
/helpers/application_helper.rb
), which is really meant for more “global” stuff. Now I can access this little fellow in my partial template—or any view—for rendering my collection of agents. ##### app/views/agents/_agent.erb
1
2
3
Agent name: 
4
Licence to kill: 
5
Number: 
6
Gambler: 
7
Womanizer : 
8
Your own custom helpers are a great way to keep your views clean and healthy. And as you have seen, it’s so quick and easy that there’s little excuse to be too lazy and not extract them for battling PHPitis. ## Conditional Content The helper method
is a handy tool for extracting content that doesn’t really fit the bill for a partial but needs a bit of encapsulation. It’s a way to store a bit of markup that you can apply on a page-per-page basis—you yield it into the layout where needed. In size, it should be a lot smaller than partials or even layouts. This technique can also save you the step of creating your own method for it. Navigational menus or sidebars are often examples where this helper becomes useful. Let’s say you want to have a spot in your menu that is only for admins, but you don’t need to adjust the whole layout. Or you have pages where the sidebar is not needed. With
, you inject what you need where you need it on a page-per-page basis. Duplication no more! ###### app/views/agents/index.html.erb
1
2
3
4
  
  • ###### app/views/layouts/application.html.erb
    1
    2
    3
    ...
    
    4
    5
     
    
    6
      
    
    7
        
    
    8
          
    
    9
          
    
    10
          
    
    11
        </ul>
    
    12
      </header>
    
    13
      
    
    14
      
    
    15
    16
    17
    </pre>
    
    18
    </form>
    
  • Advertisement
    Did you find this post useful?
    Want a weekly email summary?
    Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
    Advertisement
    Looking for something to help kick start your next project?
    Envato Market has a range of items for sale to help get you started.