The Request and Requirements

A few days ago, a friend of mine asked me to create a simple CRUDing app. He had two requirements: it had to work completely off-line and be compatible with an Android tablet. Now this posed a few problems, the main one being: I am not an Android developer.

As I think more about this request, I know I can make the app entirely using javascript and then PhoneGap to make it compatible with Android. However, there is one big problem when starting a javascript app from scratch: organization. As I continue thinking about this app, I list a few other thoughts, requirements, questions, and desires of my own:

  1. Structure benefits javascript code and Backbone.js could provide this.
  2. I have had enough of those darn curly braces - I could write this in CoffeeScript.
  3. All the data has to be stored on the client’s side - I think localStorage would work.
  4. Compiling all assets into one css and js file would be awesome.
  5. A nice touch of Bootstrap would make it look professional.
  6. Is there anyway I could use bourbon or sass to make my life easier?
  7. Testing is always important especially if the feature requests grow.

All these thoughts make me realize I have one robust solution: Rails!

Rails? Really? You may ask. Why? Isn’t that a large solution for such a small app? Especially, for a client-side application?! You may be right, but please, let’s give Rails a second look.

The Gems

Over that past few years, the rails community has embraced js frameworks such as Backbone.js, AngularJS, and Ember.js. The rails asset pipeline makes integrating these frameworks quite easy. With the backbone-on-rails gem, js code can be organized nicely into Collections, Models, Views, and Route directories. With a localStorage adapter for Backbone.js, Backbone.localStorage, Rails no longer needs a server. I can write in coffeescript with the coffee-rails gem - included by default when you build a new Rails app. I am able to write clean js code for free.

As for css, things couldn’t be any simpler. I am tired of writing in css without sass, and by including sass-rails as a default, rails programmers can say ‘goodbye’ to redundant css. While I am at it, I decide to take advantage of Bootstrap 3. I mean, this app needs to be on a tablet right? And it can look professional too. I include anjlab-bootstrap-rails in my gem file, and one rake command later - rake assets:precompile - I get two precompiled files: application.css and application.js.

Testing

I am not sure how apps can exists anymore without testing, but don’t ask the government. No matter how small, I always seem to avoid problems or find ones problems with my code when testing. Rails testing frameworks are robust but simple to set up. I decide that if I am going to test the javascript, I need to automate the browser.

In other projects I have found Selenium to be a great solution. With the rspec-rails, capybara, database_cleaner, launchy, selenium-webdriver, and shoulda-matchers gems, I get it all. I get matchers, a FireFox test driver, and even a way to inspect a page with one of my favorite gems: launchy. Below is an example test:

require 'spec_helper'
describe "CRUD ToDos", :js => true do
  describe 'Index' do
    it 'user can view a table of all todos' do
      visit '/'
      should_see_in "h1", "ToDos"
      with_scope ".btn-toolbar" do
        page.should have_link "New ToDo", :href => "#todos/new"
      end
      with_scope "table#todos" do
        should_see "Title"
      end
    end
  end
end

I also want faster test execution and to reduce the boot up time of my server, console or any other execution so I include the zeus or spork gems. It is a major time saver.

Minor Changes to Rails

Once I have my rails-backbone app up and running, I need to make a few adjustments in order to have my code work with PhoneGap.

Updating your application.html.erb file

This is what a Rails application.html file looks like upon creation:

application.html.erb file created by default

I remove the ruby code and made sure my link and script tags point to the correct place:

augmented application.html file for PhoneGap

I add a div with an id ‘main’ and use this for all the backbone pages.

Creating a Rake Task for PhoneGap

My last step is to create a rake task that creates all the files necessary for PhoneGap. Viola, I have phonegap.zip file for easy code uploading.

require 'fileutils'
require 'zip/zip'
namespace :phonegap do
  task :build => [:environment, "assets:precompile"] do
    remove_dir("phonegap", true) if File.directory?('phonegap')
    mkdir("phonegap")
    cp("./app/views/layouts/application.html.erb", 'phonegap')
    File.rename('phonegap/application.html.erb', 'phonegap/index.html' )
    mkdir("phonegap/assets")
    cp("./public/assets/application.js", "phonegap/assets")
    cp("./public/assets/application.css", "phonegap/assets")
    mkdir("phonegap/assets/twitter")
    cp("./public/assets/twitter/glyphicons-halflings-regular.eot", "phonegap/assets/twitter")
    cp("./public/assets/twitter/glyphicons-halflings-regular.svg", "phonegap/assets/twitter")
    cp("./public/assets/twitter/glyphicons-halflings-regular.ttf", "phonegap/assets/twitter")
    cp("./public/assets/twitter/glyphicons-halflings-regular.woff", "phonegap/assets/twitter")
    remove_file "phonegap.zip" if File.exist?("phonegap.zip")
    Dir["phonegap"].each do |file|
      if File.directory?(file)
        `zip -r "#{file}.zip" "#{file}"`
      end
    end
    Rake::Task["assets:clean"].execute
  end
end

Thank you so much for your time. Comments are appreciated.