Tiago Scolari

bits for fun

How to Build a Mobile Rails 3.1 App

2011-09-15

This is a simple guide to show how to use the Mobylette gem to make your Rails application respond to mobile and standard devices, and the jquery_mobile_rails gem to make it look awesome while doing that.

The final application’s source is available on Github. It is also running on heroku, if you want to check.

1. Have a running application

The application will be very simple. The specs are:

  • We have a note model with title and body
  • Users may CRUD note

Create a new app:

rails new mobile_sample

Add to the Gemfile:

# Gemfile

gem 'mobylette'
gem 'jquery_mobile_rails'

I’m using the scaffold generator, it will create everything that I need:

rails g scaffold note title:string body:text
rake db:migrate
rm public/index.html
rails s

This should be all to make the base application run.

Running Application

2. Filtering mobile requests

The mobylette gem knows when a request comes from a mobile device or not. It is very simple to use, add respond_to_mobile_requests to the application_controller.rb:

# application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  respond_to_mobile_requests :skip_xhr_requests => false
end

This allows our controllers to respond with :mobile format, when a mobile request is received. We must pass :skip_xhr_requests => false because we are using JQuery Mobile, by default the gem do not process any XHR request, even from mobile.

Create a different layout for mobile devices, application.mobile.erb:

# application.mobile.erb

<!DOCTYPE html>
<html>
<head>
  <title>Mobile Version!</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <%= javascript_include_tag "application" %>
  <%= javascript_include_tag "jquery.mobile.min" %>
  <%= stylesheet_link_tag    "jquery.mobile.min.css" %>
  <%= csrf_meta_tags %>
</head>
<body>
<div data-role="page">
  <%= yield %>
</div>
</body>
</html>

The data-role="page" is a JQuery mobile property. And the meta viewport`` is telling your phone to use it’s real resolution on this page.

#3. Creating the mobile views

The application can distinguish mobile from standard requests already. Now let’s create some different mobile views using JQuery Mobile’s marks.

# index.mobile.erb

<div data-role="header">
  <h1>Notes</h1>
</div>
<div data-role="content">
  <ul data-role="listview">
  <% @notes.each do |note| %>
    <li>
    <%= link_to note do %>
      <h2><%= note.title %></h2>
      <%= truncate(note.body, :length => 25) %>
    <% end %>
    </li>
  <% end %>
  </ul>
</div>
<div data-role="footer">
  <%= link_to 'New Note', new_note_path %>
</div>
# new.mobile.erb

<div data-role="header">
  <h1>New note</h1>
</div>
<%= render 'form' %>
<div data-role="footer">
  <%= link_to 'Back', notes_path %>
</div>
# edit.mobile.erb

<div data-role="header">
  <h1>Editing note</h1>
</div>
<%= render 'form' %>
<div data-role="footer">
  <%= link_to 'Show', @note %>
  <%= link_to 'Back', notes_path %>
</div>
# _form.mobile.erb

<div data-role="content">
  <%= form_for(@note) do |f| %>
    <% if @note.errors.any? %>
      <div id="error_explanation">
        <h2><%= pluralize(@note.errors.count, "error") %> prohibited this note from being saved:</h2>
        <ul>
        <% @note.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
        </ul>
      </div>
    <% end %>
    <div class="field">
      <%= f.label :title %><br />
      <%= f.text_field :title %>
    </div>
    <div class="field">
      <%= f.label :body %><br />
      <%= f.text_area :body %>
    </div>
    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>
</div>
# show.mobile.erb

<div data-role="header">
  <h1><%= @note.title %></h1>
</div>
<div data-role="content">
  <p id="notice"><%= notice %></p>
  <p>
    <%= @note.body %>
  </p>
</div>
<div data-role="footer">
  <%= link_to 'Edit', edit_note_path(@note) %>
  <%= link_to 'Destroy', @note, confirm: 'Are you sure?', method: :delete %>
  <%= link_to 'Back', notes_path %>
</div>

The views are almost the same, I know. The application, from a mobile device, should be looking like this:

Mobile Look

4. Getting Better

You should read the JQuery Mobile Docs to learn how to improve the look of your application. I’ll write a guide about how to turn this application into a real mobile app later, and because of that, I made some changes in the layout to make it look cooler. It’s the first time I’m playing with JQuery mobile, so dont expect too much =p. These changes are in the github repo.

You can check the final app running online here.

![]({{ site.url }}http://qrcode.kaywa.com/img.php?s=5&d=http%3A%2F%2Fmobile-sample-app.heroku.com%2F %}

5. Links

UPDATE: