How to build a Dashboard with Rails
Monday, November 16th, 2009Presenting Apotomo at the RuPy 2009 in Poznan/Poland was fun. I simply took an imaginatory dashboard, threw it in a Rails project and explained that there shouldn’t be any dashboard-less site out there.
So, my idea was to use a simple example and – of course - to make fun of my co-speaker Michał in front of the crowd. People were deeply convinced after I demonstrated a couple of useless widgets.
They instantly saw the need for small, independent components that can be reused through the whole application.
This is a brief tutorial, if you follow it you will learn how I built that simplistic dashbard with Apotomo. The sources for this part live at github. It took me no more than some hours to implement, the hardest part were all those fancy icons. I gotta love Gimp.
The dashboard controller
The slim controller’s job is to display the widget slots and to define the used widgets.
There’s no black magic here, just a plain template trying to look good.
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 | class DesktopController < ApplicationController def index use_widgets do |root| root << cell(:weather, :display, 'weather_forecast') root << cell(:michal, :sober, 'drinker') # a section is just a container widget to group things together: root << todo = section('todo') todo << cell(:todo, :list_init, 'todo_list') todo << cell(:todo, :new, 'todo_form') root << cell(:beer, :display, 'yummy') root << cell(:todo, :today, 'todo_counter') # let michal drink: root.find_by_id('drinker').respond_to_event(:beerDropped, :with => :drinking) end @slot_0 = render_widget('weather_forecast') @slot_1 = render_widget('drinker') @slot_2 = render_widget('todo') @slot_3 = render_widget('todo_counter') @slot_5 = render_widget('yummy') render end |
Again, this is kept easy and’s absolutely not the best way to handle things.
In the #use_widgets block we define what widgets to use in the dashboard. After everything is setup the widgets are rendered into controller instance variables (line 22-26).
The only interesting here is the #respond_to_event call – I add an event handler to drinker telling it to enter :drinking state as soon as a :beerDropped event is encountered (line 18).
This should usually be done in the widget, and not in the controller code, anyway, that’s for demonstration purpose so stop the whining.
Using a sandbox
Naturally these widgets have to be written.
By you.
When developing a widget, it’s helpful to plug it to some sandbox controller first to have an isolated environment for the new born. That’s what I did with the two alcoholic widgets that formed my main attraction.
The SandboxController action would look like this.
1 2 3 4 5 6 7 8 9 10 11 12 | class SandboxController < ApplicationController def drink use_widgets do |root| root << drink = section('drink') drink << cell(:michal, :sober, 'drinker') drink << cell(:beer, :display, 'yummy') drink.respond_to_event(:beerDropped, :with => :drinking, :on => 'drinker') end render :text => render_widget('drink'), :layout => 'rails' end |
That’s the end already?
This was brief. Anyway, two things became obvious:
Components are cool. You can actually use Apotomo widgets to write ..eh, web-based interactive widgets as you know them from desktop or your blog backend.
Dashboards need Components. No other application does it show better: to model dynamic user interfaces like a dashboard, you need strong encapsulation. You need widgets.
And… the widgets?
It is early morning so I will spare me any details about writing the actual widgets. Check out the source or head back to the Webhunter tutorial to learn the real shit.
In the next step we will implement the dashboard itself as a widget and make it more dynamic, so you can drop widgets in slots and thus change the layout. Nobody needs that but it looks awesome.
Ah, something I usually miss: feel free to give feedback, the comments are all yours!














