Blood pressure and conclusion

In less than an hour, I quickly added blood pressure:


It was really quick and dirty and it doesn’t have an in-line form, but it’s there and it’s working. I wasn’t able to achieve as much as I could but I think I got pretty far for one weekend. And it’s very clear that by the end, my speed was much greater than at the beginning, just compare the difference in time it took to implement each of the trackers.

I think the bigger time sinks were new stuff that I didn’t know. At the moment I was starting those I knew they were going to waste some time, but I was thinking in long term. Getting Formtastic to work as I wanted took some time, but now I’m able to create forms pretty fast. Starting to use nifty_generators took some time to actually find what they were and the syntax, but now every time I generate code I’m one step closer to finish it than before; and the look of the page is not hideous.

Another waste of time was figuring out how Rails and gems interacted. Some gems I add them and work, others don’t. Previously I included those gems manually in my code, but now I know how it works. During a couple of hours I wanted to make a much more advanced graph that would properly display 4 values or 400 values until I realized that it doesn’t have to be dynamic. When you want to see the last week, you pick last week, when you want to see last month, you pick that (well, a graph like Google’s Finance would be better, but ok, I’m humble). There’s no way to pick bigger range for the graph now, but the code is very ready for it.

I believe the experiment was a success: I can and I am very productive in Rails, same as with ASP.NET MVC or more.

First graph

It’s not perfect, but it’s a start:

My Profile page: a RESTful single resource using Formtastic

I’ve just implemented the My Profile tab for Sano:


Can I write 500 words about? Well, I can try.

I like using RESTful routes. In case you don’t know what they are let me try to explain it quick, at least the relevant part. You normally have a set of route rules that would point /movies to the movie listing, /movies/new to a form to add a new movie, /movies/123 to see the movie 123. With RESTful routes in Rails all that is done automatic in a single line:

map.resources :movies

What you are doing is defining a resource. The resource has several actions that can be performed on them:

  • index (a.k.a.: listing)
  • new
  • edit
  • create
  • update
  • destroy

In Sano I have a weights resource that is a very fine example of it:

map.resources :weights

Running the rake routes command we can see all the routes it generate:

    weights GET    /weights(.:format)          {:action=>"index", :controller=>"weights"}
            POST   /weights(.:format)          {:action=>"create", :controller=>"weights"}
 new_weight GET    /weights/new(.:format)      {:action=>"new", :controller=>"weights"}
edit_weight GET    /weights/:id/edit(.:format) {:action=>"edit", :controller=>"weights"}
     weight GET    /weights/:id(.:format)      {:action=>"show", :controller=>"weights"}
            PUT    /weights/:id(.:format)      {:action=>"update", :controller=>"weights"}
            DELETE /weights/:id(.:format)      {:action=>"destroy", :controller=>"weights"}

You see the (.:format) in there? That means that every route is also accessible in alternative formats. For example: xml. Go and try it, add some weights and access

If you are curious, the code for that is this:

def index
  @weights = user.weights.all

  respond_to do |format|
    format.xml  { render :xml => @weights }

I now want everything to be a resource. How can “my profile” be a resource? Well, it’s not hard. It’s not a collection resource, it’s a single resource. There’s no list of profiles, no creation of new profiles or destruction of profiles. There’s only editing and updating of a single profile (which is actually your user).

It turns out that in Rails, that’s very easy to define:

map.resource :profile, :only => [:edit, :update]

Notice how it says “resource” instead of “resources” and it only allows certain actions. Rails is really quite flexible here, logging in is also a resource. It’s called session and you can create them, by logging in, or destroy them, by logging out (no editing). There’s also an extra action needed by OpenID. This is the route definition:

map.resource :session, :only => [:new, :create, :destroy], :member => { :finish_creating => :get }

The “member” part specifies that action to be only for items, not for the whole collection. If it was a collection resource, you could have extra listings. The same way you have index, you could have sorted_index.

The form in the my-profile-page is an example of what Formtastic is good at. This is the whole form:

<% semantic_form_for @user, :url => profile_url do |f| %>
  <% f.inputs do -%>
    <%= f.input :name %>
    <%= f.input :email %>
    <%= f.input :height, :hint => "meters" %>
    <%= f.input :gender, :as => :radio, :collection => [["Male", false], ["Female", true]] %>
    <%= f.input :birthday, :start_year => 1900, :end_year => %>
  <% end -%>
  <% f.buttons do -%>
   <%= f.commit_button :label => "Update profile" %>
  <% end -%>
<% end %>

Special thanks to Ryan Bates who covered the gender case in Railscasts episode 184 and Eifion Bedford of ASCIIcasts for making it easy to find. It surely would have take me some time to figure it out.

Can you please update your profile on Sano?

There you go 553 words!

Migrations that change the schema

Up until today I did everything with a lot of planning and I let my OCD use migrations in a way they were not intended: I would go back and fix old migrations and destroy the database and re-run them.

With Sano, as I went through as fast as I could, two things happened: I made mistakes in the schema and those mistakes are now deployed. Time to make migrations to fix them.

The original migration for the weight model was like this:

create_table :weights do |t|
  t.integer :user_id
  t.float :weight
  t.datetime :measured_at
  t.foreign_key :users

and then I created two destructive migrations:

change_column :weights, :measured_at, :date
rename_column :weights, :measured_at, :measured_on


add_index :weights, [:user_id, :measured_on], :unique => true

The first one converted the measured_at datetime column in a measured_on date column. It destroys data, but I believe there’s no way that one could fail.

The second one adds an index for uniqueness between measured_on and user_id. That means that users can have only one weight per day. That one doesn’t destruct any data but it has the potential to fail when run on the production server.

I was about to just give it a try and pray. It’s not like thousands of people are using Sano anyway. Well, I’ve just realized I didn’t have to pray. I could test the migration first. It was trivial:

  1. Open local phpMyAdmin and go to sano_devel
  2. Delete all tables in local sano_devel
  3. Open remote phpMyAdmin and go to sano (the production database)
  4. Export everything
  5. Run SQL in sano_devel with the exported text
  6. Try migrations

Well, they worked:

$ rake db:migrate
(in /Users/pupeno/Projects/sano)
==  ChangeMeasuredAtTypeAndName: migrating ====================================
-- change_column(:weights, :measured_at, :date)
   -> 0.3609s
-- rename_column(:weights, :measured_at, :measured_on)
   -> 0.1440s
==  ChangeMeasuredAtTypeAndName: migrated (0.5056s) ===========================

==  AddUniquennessIndexToWeightUserIdMeasuredOn: migrating ====================
-- add_index(:weights, [:user_id, :measured_on], {:unique=>true})
   -> 0.1171s
==  AddUniquennessIndexToWeightUserIdMeasuredOn: migrated (0.1173s) ===========

and while I’m at it, let’s test the down-migrations, so I can be sure that if something goes wrong on production, I can rollback:

$ rake db:migrate VERSION=20091121135320
(in /Users/pupeno/Projects/sano)
==  AddUniquennessIndexToWeightUserIdMeasuredOn: reverting ====================
-- remove_index(:weights, {:column=>[:user_id, :measured_on]})
   -> 0.2745s
==  AddUniquennessIndexToWeightUserIdMeasuredOn: reverted (0.2748s) ===========

==  ChangeMeasuredAtTypeAndName: reverting ====================================
-- rename_column(:weights, :measured_on, :measured_at)
   -> 0.1381s
-- change_column(:weights, :measured_at, :datetime)
   -> 0.1335s
==  ChangeMeasuredAtTypeAndName: reverted (0.2719s) ===========================

Note: actually, there was a typo in the down-migrations; I’ve fixed it and everything was all right.

The new version with the improved forms is now deployed (the one I showed in the previous post), you can now play with it:

I love to code

I said I was done for the day more than 6 hours ago, but I love to code, I couldn’t stop. I wanted to implement a small feature: make the creation of new weights simpler for the common case and I did it:


Note: That change is not yet deployed. I don’t play with servers while I’m half-asleep.

This took awfully long. The problem was that in the process I’ve found a bug in Formtastic, which made me realize I was running version 0.2.4 when the latest version was 0.9.2. That is because I was using justinfrench-formtastic:

config.gem 'formtastic', :lib => 'justinfrench-formtastic'

when I should have been using formtastic from gemcutter:

config.gem 'formtastic'

When I moved to 0.9.2 I’ve found two bugs on it, one was temporary solved and then reverted (and I fixed it by reverting the revertion) and the other is still there but I’m not 100% confident my solution is the appropriate one. At any rate I forked Formtastic in GitHub, fixed the bugs and made a merge request.

Conclusion: Git is great, GitHub is great, Formtastic is great, open source is great, Rails is great and yes, I am great ;)

Sano is open for business

I really wish I was able to get farther in one day, but I think it’s good enough that I went from idea to deployed app. On retrospective I wasted too much time figuring out formtastic. I don’t regret doing it because it was in my TODO list and in the long run it should make me more productive, but in the short run maybe I should have used the good old forms.

The other two big waste of times was CSS and tables and an issue with the Ruby OpenID gem. Both problems I encountered before and both times I gave up trying to solve them and moved on. I should have moved on again this time; but instead I figured them out.

The application is at Please don’t break it ;) Remember to log in and if you add data I’ll be grateful as it’ll make my migrations more realistic:


I’m done for today.

Super Exception Notifier

I like knowing when something goes wrong with my web apps, so I’m using Super Exception Notifier to get by email a report should any exception be raised in the app. If you go to Super Exception Notifier’s site you’ll see some instructions on how to add it to your project. This is how I do it.

Add the gem requirement in environment.rb:

config.gem 'super_exception_notifier', :version => '~> 2.0.0', :lib => 'exception_notifier'

Then be sure to have gemcutter in your gem sources:

gem sources

If you don’t have it, you can add it this way:

gem install gemcutter
gem tumble

To install the gem, in your Rails project run:

sudo rake gems:install

Create a file in config/initializers, I’ve called it exception_notifier.rb and inside I’ve set up the only really needed value for the notifications, the email address:

# Notification configuration
ExceptionNotifier.configure_exception_notifier do |config|
  config[:exception_recipients] = %w(

The last task is to make your application controller noisy by adding one line to it (the second one of course):

class ApplicationController < ActionController::Base
  include ExceptionNotifiable

You also need to be sure that you have ActionMailer properly configured, otherwise no mail is going to get through.

Merging users

Remember that I said that when you log in, your ghost user has to be merged with the real user? Well, this is the code for doing it:

class User < ActiveRecord::Base

  def merge(user_id)
    if user_id != nil
      user = User.find(user_id)

      user.weights.each do |weight|
        weight.user = self


The problem with this is that it’s very error prone. You have to make sure that every model that is related to the user model gets properly handled.

Logging in now works

If a picture is worth a thousand words, this post has three thousand fifteen words:




Simplifying the weight CRUD

After a rather long fight with formtastic I have a better CRUD for weight:


But now that I think about it, there shouldn’t be a measured at in this view. That should be in an advanced new-form.