Rails 3

Pragmatic Rails: Write RIAs, not websites!

Wednesday, November 24th, 2010

Dude, I was googling for RIA and Rails” recently. Latest posts were dated 2007. Oh wait, there’s one from 2008 basically stating “Rails needs components” – which is nothing new to me.

What’s a RIA?

A RIA nothing more than an acronym for Rich Internet Application. What’s that, again?

  • Usually that’s a Web 2.0 application running in your browser with rounded-corners, drop shadows, gradients, drag&drop, autocompletion and using at least one Javascript framework.
  • All of them heavily rely on AJAX to update parts of the page dynamically in the background.
  • A prominent feature is a dashboard with multiple widgets that update dynamically. Everybody wants dashboards.
  • Lots of intranet applications like administration backends or CMSes are RIAs whereas the companyies’ public websites usually suck.
  • They look and feel just like real desktop applications back in the days when we all had fat clients.

The goal of RIAs is to maximize, well, usability.

RIA and Rails?

Ok, now what’s wrong in Rails? It’s a great web framework. Where are all the RIAs written in Rails? Where are all the HOW-TOs about writing RIAs in Rails?

Honestly, please google and tell me what you found, I’m more than curious.

Let me state two thesis why we don’t see too many RIAs with a Rails backend.

  • RIAs on Rails exclusively run in company intranets. Since your NDA prevents you from telling us how you wrote it it’s needless to look for posts.
  • It is comparably hard writing a RIA with Rails and most people do 90% of their work in a JS framework directly – Rails doesn’t do much except sending back JSON to the untested code running in the client, so why write a post about RIA on Rails?

Rails’ VC layer is plain

Compared to the work put into the model tier where we got Active[Model|Record|Relation|...], the view layer is still plain. We got a bit AJAX here, a bit useless RJS there, however, there’s a lack of something called web components.

The problem here is that most people just take it for granted. They don’t question the paucity of components – and use work-arounds.

This is my plea for a better view layer. I don’t blame Rails for its thrifty widgets support – I have an offer to make.

Let’s write a RIA in Rails!

This is a schematic screenshot of an email app. Hey, I never said RIAs have to be pretty!

RIAs don't have to be pretty!

That’s three widgets.

  • Top-left lists the mail folders, bold ones contain new mail. Naturally, a folder has to update when the user read the new mails, and when all mails are read, it shouldn’t be bold anymore, right?
  • Top-right shows the mails in the currently selected folder, like the inbox.
  • When clicking a mail, it will pop up in the bottom so the user may read it.

Now it does make sense to to model these three independent parts as widgets, or web components. Apotomo is Rails’ one and only web component framework, so let’s use it.

# Gemfile
source 'http://rubygems.org'
 
gem 'rails', '3.0.3'
gem 'haml'
gem 'apotomo'

Generating widgets

In order to save time, why not let Apotomo create us widget stubs? This is just like creating controllers.

$ rails g apotomo:widget inbox_panel display --haml
$ rails g apotomo:widget mail_folders display --haml
$ rails g apotomo:widget mail_reader display --haml

Widgets classes and assets are placed in app/cells/.

Controllers use widgets

We need to tell the controller about our plans on using widgets.

class MailController < ApplicationController
  include Apotomo::Rails::ControllerMethods
 
  has_widgets do |root|
    root << widget(:mail_folders, 'folders')
    root << widget(:inbox_panel,  'inbox')
    root << widget(:mail_reader,  'mail')
  end
 
  def inbox
  end

This is really just a call to has_widgets where we configure the widget tree. Passing the widget class and unique id to #widget we actually create ‘em.

Rendering widgets usually happens in controller views.

# views/mail/inbox.haml
 
= render_widget 'folders'
= render_widget 'inbox'
= render_widget 'mail'

See how I refer to the widget ids in order to render them?

Fantastic, widgets in Rails!

Now let’s explore that inbox widget on the right that shows the list of mails.

class InboxPanel < Apotomo::Widget
  responds_to_event :msgClicked, :with => :process_click
 
  def display
    @mails = Mail.inbox
    render
  end
 
  def process_click
    Mail.find(param(:id)).read!
 
    replace :state => :display
  end
end

When calling #render_widget('inbox'), two things happen.

  • The #display state is invoked, which finds out which mails to list.
  • Subsequently, it renders its view display.html.haml. How would that view look like?

Widgets have their own views

This is the widget’s view in app/cells/inbox_panel/display.haml.

= widget_div do
  %table
    - @mails.each do |m|
      %tr
        %td
          = m.sender
        %td
          %a{'data-event-url' => 
            url_for_event(:msgClicked, :id => m.id)}
            = m.subject

Don’t tell me that tables are out, fag.

UPDATE
The fag term doesn’t refer to homosexuals at all, but to stupid “software developers” who prefer to argue about tables vs. divs instead of concentrating on designing better software.

The crucial point here is the call to #url_for_event which sets up a data attribute used in our unobstrusive Javascript. Right! We missed the Javascript of our view.

:javascript
  $("##{widget_id} a").click(function() {
    $.ajax({url: $(this).attr("data-event-url")})
  });

Now what’s going on here?

  • The widget_div do in line 1 (next-to-last snippet) simply wraps our widget view in a div with the widget id.
  • Using a small Jquery snippet we refer to exactly that div (widget_id returns the id) and command it to “If a message link is clicked, send an AJAX request to that link’s event url!”.

Responding to events

Apotomo processes that AJAX request and as the inbox widget is looking out for :msgClicked events it processes the click, marks the mail as read and redraws itself in the page.

class InboxPanel < Apotomo::Widget
  responds_to_event :msgClicked, :with => :process_click
 
  # ...
 
  def process_click
    Mail.find(param(:id)).read!
 
    replace :state => :display
  end
end

The curious reader might ask “What does that #replace do?” and I would reply “Just read! Replace yourself on the page by re-rendering the #display state.

Loosely-coupled pieces

How’s the rest of the widgets informed about the click? The folders should update, and the message should be displayed in the mail widget.

Right, we (again!) use event observers to keep the widgets up-to-date. The mail widget roughly looks like this.

class MailReader < Apotomo::Widget
  after_add do
    root.respond_to_event :mailClicked, :with => :read, :on => self.name
  end
 
  # ...
 
  def read
    @mail = Mail.find(param(:id))
 
    replace :view => :display
  end
end

Again, we use #respond_to_event, this time we attach it to the very root widget in order the catch all bubbling events. Regardless what happens here in detail, the event system already shows its strengths.

  • Two independent widgets, one triggers and catches, the other one only consumes events. Both do update at the same time without knowing anything about each other.
  • By attaching observers to root – which are a kind of “global observers”, widgets stay completely decoupled from the outer world. They just state their interest in a certain event and take action.

RIAs, not websites!

Apotomo is simple to learn, and we got plenty of tutorials on the project page.

However, its fine-grained widgets, the event system and the ability to send any Javascript back to the browser opens a new way for web application development in Rails – for RIA development in Rails.

  • Take the Javascript framework of your choice, Apotomo is completely JS-agnostic.
  • Write rock-solid tests for each component and complete widget trees.
  • Move away from the page-centric controller to a more GUI-like development process.

Tell me what you think about it and check out the github repo, the project page and a real example.

Pragmatic Rails: Let’s do AJAX-backed Sidebar Widgets right, Jim!

Saturday, November 20th, 2010

Days ago I explained how to write a sidebar widget in Rails, using the view component framework Cells. This was fun.

The sidebar widget.

Clicking a tag leads to a page reload, where the Recent posts list displays items matching the tag, only. It worked great, however, each click needs a real HTTP request and a reload – let’s use AJAX to handle that.

Rails and AJAX? Apotomo!

Widgets+Rails usually means you’re better off using Apotomo , a new kid on the block. Apotomo is a web component framework for Rails, I will officially announce it in a separate post soon.

Let’s discuss how I converted the Recent posts cell into an interactive widget. If that’s too brief, there is a detailed in-depth tutorial here, just follow the links at Learn.

Check out the repository of this example app if you wanna play around.

Getting a cell interactive

We need the Apotomo gem, so I put it in the Gemfile.

gem 'rails', '3.0.1'
gem 'cells'
gem 'apotomo', "~>1.0"
# ... and so on

I would never forget to run bundle install, Freddi!

In order to make a cell a widget, I inherit from Apotomo::Widget.

class PostsWidget < Apotomo::Widget
  def display
    @tag    = param(:tag)
    @posts  = @tag ? Post.tagged_with(@tag) : Post.recent
    render
  end
 
  def tag_cloud
    @tags = Post.tag_counts_on(:tags)
    render
  end
end

Nothing really changed here, so far.

Note that deriving things from Widget doesn’t involve statefulness or anything – it’s just a nestable cell now, being aware to Apotomo’s events. Right, Ryan?

Widgets are cells

The assets layout slightly changed. Here’s how my app/cells directory now looks.

|-- posts_widget
|   |-- display.html.haml
|   `-- tag_cloud.html.haml
`-- posts_widget.rb

Some names changed, but we still got our views in a separate directory. Widgets also reside in app/cells, there’s no need to push another folder into Rails.

Rendering a widget

After these changes, rendering the widget turns out to be fucking simple, too.

%html
  %head
    %title "The Incredible Cells Blog"
 
  %body
    #sidebar
      = render_widget 'sidebar-posts'

I just call #render_widget where I used to call #render_cell in the application.html.haml layout.

The call referes to the widget id which is defined in the controller’s widget tree. Let’s see how that works, so we can render the component.

Messing up the widget tree

Usually, widget trees are declared on the controller class layer.

class PostsController < ApplicationController
  include Apotomo::Rails::ControllerMethods
 
  has_widgets do |root|
    root << widget(:posts_widget, 'sidebar-posts')
  end

Just include the necessary module and setup the tree using the has_widgets method. Notice how I refer to the widget class first, then I assign the id.

Wow- this already renders the Recent posts box! The #render_widget helper automatically invokes the #display state of the widget.

Triggering events

Clicking a tag still does a real request. As I want an AJAX call here, I change the tag_cloud.html.haml view a bit.

#tag-cloud
  - tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class|
    = link_to tag.name, "", :class => css_class, 
 
      'data-event-url' => url_for_event(:tagClicked, 
        :tag => tag.name)
 
:javascript
  $("#tag-cloud a").click(function(e) {
    $.ajax({url: $(this).attr("data-event-url")});
    return false;
  });

The first three lines didn’t change at all. However, two new steps involved here.

  • First we set an attribute in each clickable tag link. The #url_for_event computes some url needed to trigger the :tagClicked event in Rails.
  • Second a small jQuery script catches click events and fires an AJAX request to the “event url. This is that unobstrusive Javascript everybody’s talking about.

What we need to do now is catching the :tagClicked event in the ruby world and update the item list in the browser.

Luckily, Apotomo saves us from any routing and dispatching.

Catching events

As Apotomo triggers the event in the widget tree, the widget classes are one place to define observers.

class PostsWidget < Apotomo::Widget
  responds_to_event :tagClicked, :with => :filter
 
  def filter
    replace :state => :display
  end
 
  def display
  # ... and so on

I love Apotomo’s simple event system.

Again, two new steps.

  • Calling responds_to_event sets the observer. In case of fire, it invokes the #filter state method.
  • The #filter state itself just calls the #display state which collects posts and renders. The #replace helper method simply wraps the rendered view in a jQuery replace statement. Note that you may do that yourself – it’s up to you to emit any Javascript.

Now, the tag filtering works in the browser.

That’s all we need to write in order to have an AJAXed widget! It simply works, without any magic at all.

Apotomo is stable. Use it.

The framework we used here has been around for years but evolved from a “Model-driven architecture beast” into a small, stable widget framework based on Cells.

It is meant for RIA projects, dashboards, web desktops, well, Apotomo is here for helping you writing great widget-based web frontends, in a monolithic Rails environment.

Rails Misapprehensions: What the fuck is MVP?

Thursday, November 11th, 2010

People usually make me feel slightly embarassed when they ask things like “How does Cells handle MVP?” or, even better, “Is there any MVP implementation in Cells?”.

Frankly, I don’t have a fucking clue about the real differences between MVP and MVC. In the past I usually deflected people’s attention by buying beers instead or whatever. I hope to find some answers in the comments section, soon.

After actually reading a bit about “MVP, Presenters and Rails” I came to the following conclusions:

  • There simply is no difference between MVP and MVC (imho)
  • Rails Presenters don’t implement the MVP/MVC pattern completely (imho)
  • And, if Rails would be real MVC we wouldn’t need Presenters. (imho)

As always, these theses are subject to discussion.

The confusion about MVC and Rails

So the first problem I already discussed in one of my recent posts is that Rails encourages a very monolithic controller architecture having one controller being responsible for a complete page.

As Rails is an opinionated framework, their MVC-definition is absolutely ok for me. However, this is not the MVC known from GUIs – usually you’d have multiple controller-view couples in your page UI, each pair implementing complex elements like forms, menus or pageable lists.

But we already talked about that, I just wanted to point out that this is the root of the mysterious MVP misapprehension in Rails.

MVP, where art thou?

Anybody being seriously interested in GUI design patterns read Martin Fowler’s paper describing MVC, MVP, Presentation model and friends.

To be honest, I still did not understand the difference. Luckily, Martin himself seemed to realize that it is tremendously difficult to discern between the two patterns, and split MVP into Supervising Controller and Passive View (some people alleged that I’m a fan of the latter, which I’m not!).

What I basically get from these excellent writings is that

“Presenters are a loose form of MVC controller. As a result a lot of designs will follow the MVP style but use ‘controller’ as a synonym for presenter.”

which I for myself cut down to MVP == MVC” – at least in a Rails-like web development environment.

It just simplifies things.

Presenters in Rails

In the past years a couple of Presenter implementations emerged and several clever writings about that pattern popped up. I was happy to read Dmytro Shteflyuk’s blog post about his presenter project, although I disagree in some points (I’m an asshole).

The word Presenter obviously refers to the P in MVP, and in Rails they roughly work like this.

class ShowPresenter
  def top_videos
    @top_videos ||= Video.top.all(:limit => 10)
  end

After defining the data aggregating code you can use the presenter in your rendering layer.

<% cache('home/top_videos') do %>
 <%= render 'videos', :videos => @presenter.top_videos %>
<% end %>

So, we retrieve data in the presenter and then pass it to the partial, right? This approach is of course a thousand times better than collecting data for presentation in the view itself.

Help me! What’s a Presenter?

However, in my understanding of the Supervising Controller pattern (which seems to supersede MVP), we need two crucial parts in order to be a Supervising Controller at all:

  • a view to display, well, data
  • a controller to handle input response and complex view logic

Please don’t get me wrong and correct me, I appreciate any approach different from Rails’ traditional VC-stack.

However, to me it seems that presenters in Rails only handle the “complex view logic part” (“collecting the videos to display”), whereas the monolithic ActionController still renders the view and handles input responses.

Am I wrong here? Is the ActionController itself the Supervising Controller which calls a presenter and then renders a view? I’m confused.

Cells is truly MVC, but is it different from Presenters?

After all this confusion and hyperlinking I’d like to stand up for my own solution for this dilemma. Let’s comment Dmytro’s (maybe outdated) blog post where he ponders the benefits of Presenter vs. Cells telling us to use presenters whenever you

  • have too much logic in views
  • get into trouble with already cached data within views
  • can’t test an action anymore because of its complexity

and to use Cells only when

  • you need a reuseable partial with initialization code

Well, I don’t agree here. Cells do all the stuff presenters do, and more. That doesn’t mean you should use Cells everywhere in place of partials and Presenters, but nevertheless comparing Cells and Presenters is discerningly.

Presenters are data aggregators, whereas Cells are autonomous MVC stacks as claimed by the true MVC pattern. This is a bit like comparing controllers with ActiveRecord’s finder.

Presenter gets Cell

Let’s see how the former example would look with a cell.

class ShowCell < Cell::Base
  def top_videos
    @top_videos ||= Video.top.all(:limit => 10)
 
    render
  end
  cache :top_videos
end

The cell would also contain a separate view in its namespace.

Note how simple the actual cell rendering in the controller is since we handle cell caching within the cell itself!

Here, my top porns:
<%= render_cell :show, :top_videos %>

Can you see the difference?

  • Cells can aggregate and prepare data just like presenters in their methods.
  • They keep their views separated, taking away complexity from the monolithic controller
  • Handling caching within a cell drastically reduces controller’s duties and is easier testable, too
  • Both data preparation and rendering is testable in a fine-grained cell scope
  • Cells can also inherit views from parent cells which wouldn’t work with a controller+presenter approach!

By no means do I discourage usage of presenters! Use it, as long as rendering the presented data in the controller scope is clear. If it gets too complex (or if you need any other advantages cells have), use Cells.

MVC, done right

One of my intentions was to show that you don’t need presenters if you have a true MVC framework with multiple controllers/views – you can simply wrap data retrieval, rendering and optimization code (like caching) in a separate controller.

That is how GUIs used to work for decades and how web based frameworks should evolve.

How Blueprint and Compass help Idiots making CSS layouts

Sunday, November 7th, 2010

It takes me at least 2 hours to get CSS make what I want – normally this is having a two-column layout, pushing elements around and having decent margins between floating blocks. My CSS-skills do suck hard, and I usually give up asking friends and colleagues for help.

Luckily, I met Wynn Netherland and Adam Stacoviak at the LSRC 2010 – I didn’t attend their training Design eye for the Dev guy however, Wynn pointed me to Blueprint and Compass after telling him how hard I suck at implementing CSS.

This short write-up is meant to help non-designers to have pretty clean CSS layouts by using the mentioned frameworks.

What is Blueprint?

Blueprint is basically a CSS template that offers a grid layout and a nice basic font setup. It’s as if your CSS buddy would give you some ready-made CSS file and you could use his classes in your HTML files.

The central concept of Blueprint is the grid. You don’t arrange elements by eyeballing but snapping to (invisible) grid lines – this usually looks great.

The grid.

Can you see how the left navigation columns and the content block are perfectly aligned in columns? That’s this grid everybody refers to.

Now, Blueprint provides a bunch of CSS for snapping and moving. For instance, the following div would horizontally span the next 3 cells in your grid.

<div class="span-3">....</div>

This is how I created the very left column. I don’t worry about actual widths, padding, margins – Blueprint does it for me.

A two-column layout

Another thing I love about Blueprint: It comes with a two-column CSS setup which is used on almost every web page, separating your site into

  • header
  • sidebar
  • content
  • footer

In my page I have a super simple HTML setup.

<body class="bp two-col">
  <div id="container">
    <div id="header">
    <div id="sidebar">
    <div id="content">
    <div id="footer">

All I need to to is setting my body’s class to bp and two-col. I can then use the four column elements Blueprint provides inside the #container element.

This is not too much work and saves me from fighting with float: left and all the other tricks I love and hate.

Blueprint offers much more cool stuff, but all I wanted for now is pointing out that Blueprint is just pure CSS and nothing more.

What is Compass?

The next step t’wards good-looking pages is Compass – and here I had a hard time figuring out how it works.

Compass is a set of Ruby applications helping you to maintain your CSS. It heavily relies on SASS, which itself is a CSS-generating language.

Now, what Compass basically does is

  • automatically including Blueprint CSS files in your project
  • scanning for SASS files and compiling them to real, browser-readable CSS files
  • providing a great and lucid set of documentation, once you come behind how things work together

Rails and Compass

Let’s see how all these tools can be combined to make your Rails app look less sucky.

The first thing is requiring Compass in your Gemfile.

gem 'rails', '3.0.1'
gem 'compass'
gem 'haml'

The next step is initializing compass in my Rails app. I simply call

rails-app$ compass init rails --using blueprint

Now Compass does a few things worth mentioning.

  • it creates .scss stylesheets in app/stylesheets, which you’d usually edit to customize your look-and-feel. Note that you no longer use CSS directly but SASS.
  • it installs an initializer to automatically compile your site’s stylesheets

All I do for now is including Compass’ compiled stylesheets in my layout.

%head
  = stylesheet_link_tag 'compiled/screen.css', ...

Looking at my page source and following the screen.css url, I can see that Compass already did a lot of work for me by including the Blueprint CSS sources in my local CSS file.

body.two-col #container {
  width: 950px;
  margin: 0 auto;
  overflow: hidden;
  *zoom: 1;
}
 
/* and so on... */

When I now use the container setup I described earlier, my site already looks 10 times better.

%body.bp.two-col
    #container
      #header
        %h1 Apotomo
 
      #sidebar
      #content
        = yield

What is SASS?

In order to customize your design, you may open the app/stylesheets/screen.scss file and add things.

body.two-col {
  background-color: #dedede;
 
  #container {
    background-color: white;
    height: 100%;
  }
}

This is SASS – it’s meant to keep you away from coding CSS directly while providing some nifty object-oriented features like mixins, inheritance and variables. You can read about that at the project page or in this great post.

BTW- there are two different SASS syntaxes available which confused me.

  • The older .sass syntax doesn’t need curly brackets and instead relies on indendation as HAML does.
  • The .scss syntax is more CSS-like and seems to be the authorative syntax (?).

Presentation-free Markup?

Something I didn’t get either was the difference between presentational classes and semantical selectors in Compass and SASS, although it’s very simple.

I used to put presentational classes into my HTML.

<body>
  <div id="sidebar">
    <div class="width-300">
    <div class="width-300">

Instead, I could have done that using semantical selectors in SASS, cleanly separating content and presentation.

#sidebar {
  div { width: 300px; }
}

I don’t need to mention the div’s width anywhere except in the SASS file, as I already know that divs in the sidebar won’t have any other width than 300. Is that right?

Another example: When debugging my layout, I like the showgrid feature which displays the grid in the background of the element.

While I could do something like

  <div id="container" class="showgrid">

which uses a presentational class in my markup I can also control that in my SASS stylesheet.

#container {
    @include showgrid;

The showgrid mixin is applied to the #container selector, which basically includes the showgrid code into this selector.

Now, use it!

I hope this article helps nerds understanding how these awesome frameworks act together and how they can be used to do something we all love: Having good-looking sites.

Rails Misapprehensions: Cells don’t break MVC

Monday, November 1st, 2010

I was posting a stupid simple example how Cells can be used the other day. This controversial post got lots of great comments, thanks to all! While some just questioned Cells and its use, a few comments really bashed the project in a very aggressive way. I like that.

The rudeness in some sequential comments seems to come from one cause: Ignorance. The writings simple proof that the author did not understand anything about Cells, and MVC in Rails.

I’ll pick some points from different authors and try to explain.

  • “It messes MVC up.”
  • “a place that also breaks the MVC framework.”
  • “Not only are you abstracting view code out to a place where it simply doesn’t belong, …”
  • “I’m not convinced that the benefits of Cells outweigh the complexity they add.”
  • “I think you are a nut.”

MVC and Rails

Ok, I won’t explain MVC here again. We already got great writings about that – however, there are two points in Rails’ MVC design that might cause confusion.

  • The ActionController mixes MVC and the FrontController , and this creates the impression that web apps have to be one monolithic controller, one view, and maybe a couple of partials rendered in the controller context.
  • Rails hides rendering, so in most cases the programmer doesn’t realize templates rendering happens “in” the controller.

Cells are small controllers, derived from AbstractController. You can imagine them as small, separate MVC-stacks between the traditional Rails VC-layer. There is nothing wrong with that, right, Martin?

At this point I should stress that there’s not just one view and controller, you have a view-controller pair for each element of the screen

(Martin Fowler about MVC, quoted)

How to break MVC?

If calling #render_cell in the controller is “breaking MVC”, why is there a #render, or even a #render_to_string method in the controller? That would mean Rails itself is doing something wrong, as it does rendering in the controller.

It is absolutely ok in the controller to instruct a separate MVC-component to render – as long as the controller doesn’t interfere in the rendering process or even shares knowledge about the cells internals.

What is view code?

First, I’d like to emphasize I never said views should be “dumb, non-runtime-interpreted view code – WTF? I use helpers, logic, everything in cell views.

Complex forms with dozens of fields, computations and conditions are surely not “view code” only, so in my opinion that should be “abstracted out to a place where it simply doesn’t belong”: to a separate component.

However, there is no need to put every little partial to a cell. Don’t do that! It is a matter of feeling to perceive when things are getting too complex for a partial mess and should be refactored to a cell instead.

Cells are more complex

This is absolutely true. Cells bring more classes and assets to your project. It is a new paradigm that wants to be understood. New programmers might be confused of cells suddenly popping up everywhere in your app.

Cells is a new concept in Rails – of course it is more complex than odd partials and helpers accessing global controller variables. It’s a bit like back in the times when OOP became popular and people asked “Why should I use objects when my simple procedures do all I need?“. Cells are object-oriented components (with all the stuff we love about OOP, like inheritance) whereas partials are… whatever.

And, don’t forget Cells can be tested in a very simple and clean way, too. This indirectly reduces complexity.

You are a nut!

True.

I hope this writing clarifies several misapprehensions I created by posting a stupid simple example. Now, fire at will!

Why Rails Controllers need a Double Render

Saturday, October 30th, 2010

In one of my last posts I already discussed the improvements Cells brings to your Rails app by providing view components.

The last day I had an lively discussion about the concept of partials or page fragments in Rails.

Partials make me feel sick. People ordinarily use ‘em in order to have “DRY code”. However, usually the extensive usage of partials makes the architecture even worse.

  • Partials blow up your controllers which should be slim – partials always blindly access variables sitting in the controller, which increases controller complexity and makes your code break often. Just use a non-existent local and you’re knocked out.
  • Partials can’t be rendered in the controller. Unavoidably this shifts code and knowledge to views – isn’t that a so called “NO-GO”?
  • Partials itself can’t be tested separately.

Today I’d like to show one concrete use-case how to really DRY up your view code with Cells.

What’s nice about partials

In our discussion we were refering to a form that was rendered in every action. A Rails developer will put the form in a partial. This is a good thing.

UPDATE: The real form was way more complex! For educational purposes I cut down this example – I wouldn’t implement such an easy task with Cells, Lonny! ;-)

Now we found out we need a customized button title in the form. We have two possibilities at this time.

  • Save the title in an instance variable read by the partial.
  • Pass the title as a local when rendering the partial.

The first is terrible. The second looked like this.

render :partial => "form", 
  :locals => {:title => "Create item."}

And in another view.

render :partial => "form", 
  :locals => {:title => "Update this item."}

The coached colleagues learning Rails asked: “But… isn’t that the opposite of DRY?“ and I said “Yes.”.

Can Helpers help?

We had several identical calls in our views. They started working out different approaches with helpers.

def my_form(title)
  render :partial => "form", #...

Using helpers they were forced to use instance variables, again, for transporting information from controller to view to helper to partial. It was a mess.

Suddenly, someone came up with a new idea: “What if we call the helper in the controller?” – they tried, and failed. Every Rails developer has to meet the DoubleRenderError once in his life.

I interrupted the experiment and introduced Cells getting wet.

DRY up your views!

We simply put the view and associated code in a cell.

class FormCell < Cell::Base
  def display
    @title = opts[:title] or raise "No title passed!"
    render
  end
end

The state view reads the instance variable.

  = form_tag do # ...
 
    = submit_tag @title, :id => :btn

Using instance variables here is ok. Remember, we’re in a small cell instance. You don’t pollute a complete request controller with some rich title.

Even better, we got some options validation, too.

Rendering twice in the controller

As we needed the form in every action, we rendered it in a before_filter. Yeah, Cells can be rendered just anywhere.

  class ItemController < ApplicationController
    before_filter do
      titles = {:create => "Create item", 
                :edit   => "Update this item"}
 
      @form_html = render_cell(:form, :display, 
        :title => titles[action_name])
    end

This is pretty DRY.

  • We define titles and render the corresponding form in one place, as they do go together. We don’t spread a bit code to every action.
  • The controller instance variable contains the rendered form markup.

Naturally, you’re not bound to filters – this is just a simple example.

Testing the form

Being an agile TDD team we instantly travelled back in time and wrote a test before implementing the cell.

class FormCellTest < Cell::TestCase
  test "the button title should be in place" do
    invoke :display, :title => "Test your partials!"
    assert_select "form #btn", "Test your partials!"
  end

Having an object-oriented partial with backing functional test we decided to knock off work for today.

You can find the Cells repo here.

Testing your Rails 3 Engine sitting in a Gem

Monday, October 11th, 2010

or Making your Rails gem suck less

When people refer to gems they usually think of new methods and classes popping up in your Ruby application as soon as you require the gem.

However, with Rails 3, gems (and plugins) can also add behaviour, controllers, views, routes and all the other well-known pieces of Rails to your host application. These kind of gems are called engines.

Luckily, in Rails 3 we got baked-in engines support. When adding the gem to your host application, Rails will detect the engine and automatically extend things for you.

What can Engines do for me?

I, being a components-facist who refuses to write monolithic apps, am very happy about engines: They help you encapsulating parts of your application and encourage reusability in and between other projects.

Man, WordPress keeps telling me to update.

Having read great posts about writing engines, I will focus on testing engines in this post.

Testing engines right

So, if you use my Apotomo gem (and you should do that if you want real web components in your Rails app) it will add

  • new classes and stuff
  • new methods to controllers
  • add a new route

Now how do I test all that in the gem?

The Rakefile

First, I setup a Rakefile containing a Rake::TestTask. It sits in the gem’s top directory.

Rake::TestTask.new(:test) do |t|
  t.libs << 'test'
  t.test_files = FileList['test/**/*_test.rb']
  t.verbose = true
end

I can now run rake test in my gem directory which will launch my gem test suite.

The test helper

Every test suite needs a file to require all needed stuff. Usually you put that into test/test_helper.rb and require it in every test.

require 'rubygems'
require 'bundler'
Bundler.setup
 
require 'shoulda'
require 'apotomo'

I use bundler when running my tests, which makes loading local gems for development simple.

Unit tests

Testing classes and methods in gems is simple – the same setup as in your app. A unit test could look like this.

require 'test_helper'
 
class ApotomoTest < Test::Unit::TestCase
  context "The main module" do    
    should "respond to js_framework" do
      Apotomo.js_framework = :jquery
      assert_equal :jquery,  Apotomo.js_generator
    end
  end
end

The test helper is required, then we run an ordinary unit test against the gem classes, modules and methods.

Testing controllers

Things get complicated when it comes to testing controllers that use new Apotomo behaviour. I don’t want to setup things, so I use a small Rails test application in my tests. I initially stole that from José Valim’s devise, that everybody loves.

Enginex is a generator

The enginex command creates a rails app for me.

apotomo/test$ enginex dummy

Unfortunately, enginex assumes I want a new gem with a setup test directory, so what it does is:

dummy
|-- Gemfile
|-- lib
|   `-- dummy.rb
|-- Rakefile
`-- test
    |-- dummy
    |   |-- app
    |   |   |-- controllers
    |   |   |   `-- application_controller.rb
    |   |   `-- views
    |   |-- config
    |   |   |-- application.rb
    |   |   |-- environment.rb
    |   |   `-- routes.rb
  ...

What I need resides in dummy/test/dummy, so I move things a bit.

apotomo/test$ mv dummy dummy_gem
apotomo/test$ mv dummy_gem/test/dummy dummy
apotomo/test$ rm -r dummy_gem

Now I got a rails app in my test/ directory.

dummy/
|-- app
|   |-- controllers
|-- config
|   |-- application.rb
|   |-- environment.rb
...

I also remove the line

require "dummy"

in test/dummy/config/application.rb.

You’re now free to setup testing scenarios in dummy by adding controllers, actions and everything else.

Requiring the test app

My apotomo/test/test_helper.rb gets a bit longer.

ENV['RAILS_ENV'] = 'test'
require "dummy/config/environment"
require "rails/test_help"

This is all I need for now, I can now run a ActionController::TestCase against a controller in my dummy app.

Note that you should first require your engine, then the rails app so your tested gem is available in the dummy app.

Functional tests

Let’s go actually testing controllers.

Remember: we’re testing a gem that extends controllers, so first, we write a small imaginary controller and put it in test/dummy/app/controllers/dummy_controller.rb.

class DummyController < ApplicationController
  include Apotomo
 
  def apotomo
    render_widget "root" # Just some bullshit to test Apotomo.
  end
end

In the controller, I really use Apotomo as if I would be a user using it. No monkey-patching and stuff – it is a test validating that my gem works in shitty real-world controllers.

require 'test_helper'
 
class ApotomoIntegrationTest < ActionController::TestCase
  tests DummyController
 
  context "The controller" do
    should "render widgets" do
      get :apotomo
      assert_select "div#root", "I'm root"
    end
  end
end

ActionController::TestCase provides a relatively easy way to write functional tests.

Naturally, you can also test “native” controllers and routes from your engine the same way.

Unit testing controllers

Sometimes pure functional tests are too less and a unit test for your controller methods would be handy – I do that often.

require 'test_helper'
 
class ApotomoControllerMethodTest < ActionController::TestCase
  tests DummyController
 
  context "The controller" do
    should "respond to #render_widget" do
      assert_responds_to @controller, :render_widget
    end
  end
end

The test case automatically provides a controller instance in @controller. You’re free to invoke methods and test ‘em.

These were the basic steps, if you wanna know more, ask!

Comments appreciated

Dudes, why are you guys so shy? Tell me how you do it, what you like and what sucks. I really appreciate comments.

10 Points How Cells Improves your Rails Architecture

Monday, October 4th, 2010

The Cells gem has been around in the Rails community for more than four years now. It has hundreds of pleased users who reported all kinds of use cases and how cells improved their apps. Here’s a compilation of the best practices.

The challenge

A shopping cart in a Rails app.

Usually you’d take a shared partial to display the cart in every controller.

%h1 Your cart
 
- if items.blank?
  = render :partial => "shared/cart/blank"
 
- else
  %ul
    - for i in items
      %li #{i}

Some view would render the cart somewhere.

<%= render :partial => 'shared/cart/cart',
  :locals => {:items => current_items} %>

1. Keep your views dumb

The render :partial looks harmless, and many Railers will argue “Well, you can put that in a helper.” – anyway, this little piece of code alreay contains a lot of knowledge. Too much.

That’s knowing

  • which items to display (current_items)
  • the exact location of the cart partial

A dumb view should not know anything about file locations at all.

<%= render_cell :cart, :display, 
  :items => current_items %>

The CartCell we’re rendering hides any physical file location from us.

2. Don’t put logic into views

Yeah, a snippet like

- if items.blank?
  = render :partial => "shared/cart/blank"
 
- else
  ..

already contains decider logic – didn’t we learn something different from MVC?

class CartCell < Cell::Base
  def display
    return render if @opts[:items].present?
 
    render :view => :blank
end

The cell is supposed to render its display view. If no items were passed, it renders the blank view.

Any decider logic happens in a class, and not in some object-unoriented helper or partial.

3. Interfaces can save lives

So I used :locals in my example above. However, I often see controllers where people just set instance variables and use them throughout all partials.

  def index
    @items = current_items
  ..

The partial blindly accesses instance variables.

  %ul
    - for i in @items

Every controller using that partial has to know which instance variables it has to set before rendering. It’s only a matter of time until some controller renders a partial without providing the queried ivar – and your code crashes.

Cells by contrast force you to define which variables you wanna pass – making you writing interfaces without noticing it.

<%= render_cell :cart, :display, 
  :items => current_items %>

4. Controllers should be slim

So instead of globally cluttering your controller with instance variables, put that into well-encapsulated cells.

class CartCell < Cell::Base
  def display
    @user = session[:user]
 
    render
end

Each cell has a limited scope not polluting anything except itself.

5. Avoid helpers

Helpers are plain modules. And can be pain.

What if the item list in the cart would be sortable? People implement that with helpers.

module CartHelper
  def render_cart_sorted
    order = params[:order] || :asc
    items = @items.sort(order)
 
    render :partial => 'shared/cart/cart', 
      :locals => {:items => items}
  end

This leads me to questioning myself “What is a helper? It’s not a view, but renders. It’s not a controller, but it aggregates data. What are helpers?”.

The answer: Helpers are shit. They completely break anything we learned from MVC and they are untestable.

class CartCell < Cell::Base
  def display
    setup!
 
    render
  end
 
  def setup!
    order = decide_order(params[:order])
    @items = @opts[:items].sort(order)
  end
 
  def decide_order(order)
    order || :asc
  end 
end

Here, sorting (or delegating sorting to the model) is the controller’s job. It’s duty is to process user gestures (user clicks on sorting icon) and to aggregate data (actually sorts data for presentation).

This is called V/C glue code as it lives between view and controller.

Under no circumstances should this be done in a helper.

6. Unit-test your glue code

Brrr, a shiver runs up and down my spine. I just imagined how you’d test this helper code.

With cells, you’d first assure that your sorting is doin’ right.

class CartCellTest < Cell::TestCase
  test "sorting should be doin' right" do
    assert_equal :asc,  cell(:cart).decide_order(nil)
    assert_equal :desc, cell(:cart).decide_order(:desc)
  end
end

Easy. What’s next?

7. Functional-test your rendering

We usually write functional tests when it comes to rendering markup. With helpers and partials this can be really painful.

Cells are made for heavy-duty testing.

class CartCellTest < Cell::TestCase
  test "the cart should look good" do
    @params = {:order => "some bullshit"}
 
    invoke :display
    assert_select "ul li", 3
    ..
  end
end

Cells let you simply test what you just did – in a separate, well-encapsulated environment.

8. Get OOP back in your views

Unfortunately, the current Rails view layer discourages using modern concepts, like inheritance, encapsulation and OOP at all. Why?

Why should we have great models and sucky views?

Now imagine it’s getting christmas, and your cart should look christmessy. Like some snowflakes in the background and a smiling reindeer on the order button.

class XmasCartCell < CartCell
  def display
    setup!
 
    render :layout => 'xmas'
  end
end

We simply inherit

  • the setup methods
  • the behaviour
  • the views

It’s just OOP, back in your views. No magic, no implicit syntax, just OOP from the book.

9. Teams love components

Mando works on the shopping cart, whereas Charles plays around with the bestseller cell. Both are working on features shown in the same controller.

However, Charles and Mando will never get into trouble with each other – both have a separate component which does not know anything about the outer world.

Mando is strictly bound to

app/cells/
         cart_cell.rb
         cart/
             display.haml
             order_button.haml

Charles codes somewhere else in

app/cells/
         bestseller_cell.rb
         bestseller/
                   list_latest.haml

They have separate tests, too. And when they think they’re stable they just plug the cells in the controllers and it will work.

Mando and Charles love components!

10. Hide your caching

The BestsellerCell needs a lot of computation. Who bought what, when and how often? Why not cache the view?

According to the Rails docs, partials do that with the following pattern.

<% cache do %>
  Our bestsellers:
  <%= render :partial => "bestseller",
    :collection => Bestseller.find(:all) %>
<% end %>

Caching is exposed to the action. The action has to know about the partial’s caching requirements. This is wrong.

The partial computing and rendering the list knows best about its needs. So put the caching where it belongs – to the partial!

class BestsellerCell < Cell::Base
  cache :list, :expires_in => 10.minutes
 
  def list
    @bestseller = Bestseller.find(:all)
    render
  end
end

When calling

render_cell :bestseller, :list

nobody except the cell itself knows about the caching for that special page fragment. Even the expiry strategy is in the cell. This is called knowledge hiding.

More to come

The component-oriented approach with cells yields more improvements for your code. And there is more, yet. Interactive cells with AJAX often needed for rich client applications or dashboards – we got a cells-backed framework for that: Apotomo.

Go, try and love it.

Cells for Rails 3 considered stable!

Wednesday, September 29th, 2010

We finally pushed out the 3.4 gem of Cells, that’s view components for Rails.

Check out the github repo.

What’s Cells?

If you’re sick of partial+helper botching, if your views are getting too complex or you ever dreamed of rendering actions within actions, Cells is for you!

How can I get it?

Just run

$ gem install cells

to get the power of components and encapsulation into your Rails 3 app.

What’s new?

  • We lost about 50% of code compared to the 2.3 version.
  • Thanks to help of Yehuda Katz, who introduced the Rails 3 API to me in a hacking session, Cells are now real controllers!
  • Finally, view inheritance and nesting is documented ;-)

Go and check it out, you’ll love it! If you run into any trouble, don’t hesitate to bother us on #cells in irc.freenode.org! Keep it real!

Getting a bloody Rails 3 generator running. And testing it.

Wednesday, September 15th, 2010

Suck me sideways! It is said the generator layer in Rails 3 got really ohsom, flexible and whatever. I can now confirm “That’s true, somehow.” – nevertheless it took me years to figure out all the internals, conventions and places where to find documentation.

What I wanted

So here’s my requirement. I have a gem cells. It’s ready for Rails 3. It’s even mentioned in the Rails’ weblog! Anyway, it needs a generator to create assets for the users. In Rails 2.3 running something like

rails2 $ script/generate cell blog latest --haml

would generate several files in app/cells/ inside the rails application.

So, basically, I need a generator inside a gem to create… files. Nothing more.

Where I put it

Here’s how I ended up with my generator. It resides at
cells/lib/generators/cells/cell_generator.rb.

Two things noteworthy here.

  • Put your generators in your gem’s lib/generators directory, nowhere else.
  • The last directory containing the generator class had to be named cells (like the gem). Any other filename worked fine when running rails g, which would list my generator.
    However, when trying to generate with rails g cells:cell it failed with “Could not find generator cells:cell.“.

I was able to find some informations on naming in the generators guide. I don’t really like the example there, and I had to dive into the code to figure out things, anyway.

How I did it

Here’s how the generator looks like (I stole a bit from devise).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
require 'rails/generators'
require 'rails/generators/named_base'
 
module Cells
  module Generators
    class CellGenerator < ::Rails::Generators::NamedBase
      argument :actions, :type => :array, :default => [], :banner => "action action"
      check_class_collision :suffix => "Cell"
 
      source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
 
      class_option :view_engine, :type => :string, :aliases => "-t", :desc => "Template engine for the views. Available options are 'erb' and 'haml'.", :default => "erb"
      class_option :haml, :type => :boolean, :default => false
 
 
      def create_cell_file
        template 'cell.rb', File.join('app/cells', class_path, "#{file_name}_cell.rb")
      end
 
      def create_views
        if options[:view_engine].to_s == "haml" or options[:haml]
          create_views_for(:haml)
        else
          create_views_for(:erb)
        end
      end
 
      def create_test
        @states = actions
        template 'cell_test.rb', File.join('test/cells/', "#{file_name}_cell_test.rb")
      end
 
    protected
 
      def create_views_for(engine)
        for state in actions do
          @state  = state
          @path   = File.join('app/cells', file_name, "#{state}.html.#{engine}")
 
          template "view.#{engine}", @path
        end
      end
    end    
  end
end

Let’s discuss some basics.

  • Derive your generator from Rails::Generators::NamedBase if it expects at least one argument (line 6)
  • Use Generator.source_root to define where your templates are located (line 10)
  • Every public method is invoked automatically during the generation process. That’s something you should know. I didn’t know that.
  • Be sure to read the Thor manual, as this is the base for Rails’ generators. E.g. Generator.template will parse the specified ERB view and drop it in the passed new location (line 17).
  • Options from the command line can be retrieved from the Generator.options method (line 21).

The complete generator files with its views and shit can be found at my repository.

Testing it

I hate manual testing. Instead of calling

rails g cells:cell blog latest --haml

a thousand times I wrote generator tests. No docs on that could be found, so far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require File.join(File.dirname(__FILE__), 'test_helper')
 
require 'generators/cells/cell_generator'
 
class CellGeneratorTest < Rails::Generators::TestCase
  destination File.join(Rails.root, "tmp")
  setup :prepare_destination
  tests ::Cells::Generators::CellGenerator
 
  test "create the standard assets" do
    run_generator %w(Blog post latest)
 
    assert_file "app/cells/blog_cell.rb", /class BlogCell < Cell::Rails/
    assert_file "app/cells/blog_cell.rb", /def post/
    assert_file "app/cells/blog_cell.rb", /def latest/
    assert_file "app/cells/blog/post.html.erb", %r(app/cells/blog/post.html.erb)
    assert_file "app/cells/blog/latest.html.erb", %r(app/cells/blog/latest.html.erb)
    assert_file "test/cells/blog_cell_test.rb"
  end

Generator tests are super smooth, just watch out for the following.

  • Be sure to require your generator (line 3).
  • Derive your test from the nice Rails::Generators::TestCase (line 5).
  • With TestCase.run_generator you can simulate a command line invocation of your generator and pass arbitrary arguments (line 11).
  • The handy TestCase.assert_file method checks if the file was generated. Additionally, you can pass a regex as second argument which is matched against the file content.

Props to the very intuitive and easy Generators::TestCase API, I do appreciate that.

Reflecting the past decades

At first, I was overwhelmed by all the features like hooks and namespaces. Now that I understand the principles of Rails 3 generators it almost seems ridiculously easy. And, if you don’t understand things, always remember to peek at the Thor docs. Maybe the generator guide should mention that somewhere.

Peace.