Nitrous.IO: Rails Development in the Cloud

ProvisioningBox

Well Grounded

Whenever I prepare to develop a Rails application, there is a set of essential tools I need to have available to me. These are loaded on my machine:

  • Ruby
  • Sublime Text 2
  • RVM
  • Bundler
  • PostgreSQL
  • git
  • Collaboration tools (perhaps)
  • Heroku Toolkit (on Mac)

Perhaps you have a similar setup. And, like me, you are most comfortable working on a Rails application with that one machine (for me it is my MacBook Pro) because it contains your entire development environment. Conversely, it is quite a challenge to work on a project (either new or existing) without this suite of essential tools.

Living in ‘The Cloud’

All of my deployment, however, is cloud-based. It always struck me as just a bit ironic that I was tied to a particular piece of hardware in order to develop a final product that was intended to be ethereal.

That is why I was quite excited to discover Nitrous.IO. This is not just another browser-based code editor. Nitrous.IO is a complete development environment in an EC2 instance. All the tools I mentioned (running under Linux) can be loaded. The kicker is that you have a choice between the online “browser” editor window or your favorite shell editor (VIM, Emacs). If you are a Mac user, there is a very new OSX application that connects your computer directly to your Nitrous.IO instances!

But I do not expect you to simply take my word for it. The goal of this article is to give you a quick walk-through of this service and point out a few of the features I consider especially noteworthy. I am confident you will share my enthusiasm after spending a little time exploring it on your own.

Setting Up

There is practically NO SETUP involved. Everything you need to get started is included. You can create an account and start writing code immediately. Point your browser to Nitrous.IO.
NitrousRegistration

If you use your Github account for authentication you establish a link to your code repositories and you earn some N20 right away (see sidebar).

Earning Nitro

You can earn more capabilities on the system with ‘points’ they call N20.
I think it is very clever marketing; you charge up your account. This begins with completing the registration process.
After that, there are a number of ways to earn more N20 which you can ‘spend’ for some additional services.

EarnN20

In any case you should add at least one SSH key. Also, as is true to form, there is a simple GUI way to generate a key for your Box.

Create Your First Box

Each ‘instance’ on Nitrous.IO is called a ‘Box’. NewBox

Go to Boxes and setup a Box.

Here you must choose the environment you wish to work with this Box. In our case, we will choose ‘Ruby on Rails’ but I encourage you to explore the others; paticularly if those are technologies with which you often work.

CreateBoxROR

Also, you must name your box and select the region for the EC2 instance that will be spawned. After you have created this Box, you can ‘Start’, ‘Terminate’ and enter ‘IDE’ from the Dashboard.

When you create a Box it should start for you automatically.
Once the Box is running you can click on IDE (or Terminal if you are so inclined. We will remain in the browser for this article) and will be presented the online Development Enviroment.

Notice that in addition to a standard Menu across the top of the IDE, there is support for many standard keyboard shortcuts. This is something I really like. I tend to DRIVE BY KEYBOARD. When I am deep in the throes of writing code it is distracting to displace my hand to reach for the trackpad.

There is an explorer tree on the left and, once you create or open a file, you will see buttons across the top of the Editor window for some really useful features that I had not seen in any other similar product.

The bottom of the browser window is a Terminal. The Nitrous.IO IDE provides truly The Best Of All Worlds by combining

  • GUI tools
  • a filesystem explorer
  • a terminal instance

And you are not limited to just ONE instance. Click the plus “+” to start another in a new tab.
The “X” on the far right will open the Terminal to fullscreen.


This is a Linux system and you can get details of the OS by typing cat /etc/*-release


Follow the Boxes link and click on your new box.
PublicKey
You will notice that, among the information about each box, there is “Preview URI”. This is for live, interactive preview of your project as you work on it.

Let’s Write Some Ruby Code

This is only a quick tour of the interface. I have faith you will uncover many more goodies as you explore. It’s time to load up some tools and write code!

At the time of this writing the AutoParts Package Manager was just announced. The principle behind this is to provide pre-built sets of tools and utilities that can be loaded easily on any Nitrous.IO Box.
Use the search command for a list of packages available; which continues to grow.

Initialize Tools

As a result of our Ruby On Rails choice, many tools are already provisioned:

  • git
  • Bundler
  • Heroku client
  • Ruby 1.9
  • Rails 4.0.0
  • mySQL & sqlite3

This is everything needed to build a Rails 4 application instantly!

I mentioned RVM as part of my list of standard tools. That is not included but you can easily load it if you plan to work with multiple versions of Ruby (and Rails). Timothy Boronczyk has a great article on installing RVM on Ubuntu.

Looking under the Connect menu option in the IDE you will see the Database choices available to you.
ConnectMenu

That is quite enough “Guided Tour”. LET’S WRITE SOME CODE

Building a Rails App

As a Serial Rails Developer, I start every Rails project with the User/Session Authentication logic. This is common among almost all web applications. I thought it would serve as a simple example to demonstrate Nitrous.IO if we construct the foundation of a Rails application by implementing User Registration “from scratch”.

I know that veteran Rails developers have a favorite gem for handling this. Please bear with me.

In the console window type the following:

rails new youzer

Then

cd youzer

Follow that with these three commands.

rails g model User name:string email:string password:string password_confirmation:string password_digest:string
rails g controller Users new create
rails g controller Sessions index new create logout destroy

You can take advantage of the explorer tree on the left to navigate to each of the following files and make appropriate edits (you may need to refresh the tree, there is a button at the top right). Just a single click on the filename in the tree opens it in the editor.

app/models/user.rb
class User < ActiveRecord::Base
  attr_accessible :email, :name, :password, :password_confirmation, :password_digest
  has_secure_password   #This is the Rails 3 'magic' 
  validates_presence_of :password, :on => :create
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

private

def authenticate_user!
  if current_user.nil?
    redirect_to login_url, :alert => "You must first log in to access this page"
  end
end

def current_user
 begin
     @current_user ||= session[:user_id] && User.find(session[:user_id])
 rescue
 end
end

def user_signed_in?
 begin
  User.where("id=?", session[:user_id]).exists?
 rescue
  false
 end
end

  helper_method :current_user, :user_signed_in?, :authenticate_user?

end
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def index
  end

  def new
  end

  def create
    user = User.find_by_email(params[:email].downcase)
    if user && user.authenticate(params[:password])
      session[:user_id] = user.id
      redirect_to root_url, :notice => "Welcome #{user.name}"  #you may wish to modify this redirect
    else
      flash.now.alert = "Invalid email or password"
      render "new"
    end
  end

  def logout
    self.destroy
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_url, :notice => "Goodbye"
  end

end
app/controllers/users_controller.rb
class UsersController < ApplicationController
 def new
  @user = User.new
 end

  def create
  @user = User.new(params[:user])
  @user.name = params[:user][:name]
  @user.email = (params[:user][:email]).downcase
  if @user.save
        session[:user_id] = @user.id
        current_user #call in application helper
   redirect_to :root, :notice => "Registered!"  #you may wish to modify this redirect
  else
   render "new"
  end
  rescue Exception => ex
    logger.warn('ERROR: ' + ex.message)
    flash.now[:error] = 'There was an error creating the user.'
    render :action => 'new' 
 end
end
app/views/sessions/new.html.erb
<%= form_tag sessions_path do %>
<h3>Log in</h3>
  <div class="field">
    <%= label_tag :email %>
    <%= text_field_tag :email, params[:email] %>
  </div>
  <div class="field">
    <%= label_tag :password %>
    <%= password_field_tag :password %>
  </div>
  <div class="actions"><%= submit_tag "Log in" %></div>
<% end %>
app/views/users/new.html.erb
<%= form_for @user do |f| %>
 <% if @user.errors.any? %>
   <div class="error_messages">
    <h2>Form is invalid</h2>
    <ul>
     <% for message in @user.errors.full_messages %>
       <li><%= message %></li>
     <% end %>
    </ul>
   </div>
 <% end %>
<h3>Sign Up</h3>
 <div class="field">
  <%= f.label :name %>
  <%= f.text_field :name %>
 </div>
 <div class="field">
  <%= f.label :email %>
  <%= f.text_field :email %>
 </div>
 <div class="field">
  <%= f.label :password %>
  <%= f.password_field :password %>
 </div>
 <div class="field">
  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation %>
 </div>
 <div class="actions"><%= f.submit "Register" %></div>
<% end %>
app/views/layouts/application.html.erb
<!DOCTYPE html>
<head>
  <title>Your Own User Zero Effort Reset</title>
  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>

</head>
<body>
<ul id="nav">
 <% unless user_signed_in? %>
  <li><%= link_to "Log In", sign_in_path %></li>
  <li><%= link_to "Register", sign_up_path %></li>
 <% end %>
    <% if user_signed_in? %>
  <li><%= link_to "Log Out", log_out_path %></li>
 <% end %>
</ul>

<%- flash.each do |key, msg| -%>
  <div id="<%= key %>">
    <p style="float:right;"><a href="#">X</a></p>
    <p><%= msg %></p>
    <div class="clear"></div>
  </div>
<%- end -%>

<%= yield %>

<div id="wrap"></div>
<div id="foot">Application developed by Thom Parkin / Websembly, LLC</div>

</body>
</html>
app/config/routes.rb
Youzer::Application.routes.draw do
  get "users/new"
  get "users/create"
  get "sessions/index"
  get "sessions/new"
  get "sessions/create"
  get "sessions/logout"
  get "sessions/destroy"

  match 'sign_in' => 'sessions#new', :via => :get
  match 'sign_up' => 'users#new', :via => :get

  match 'log_out' => 'sessions#destroy', :via => :get

  resources :sessions
  resources :users

  root :to => 'sessions#index'
end
Gemfile
source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.0'

# Use sqlite3 as the database for Active Record
gem 'sqlite3'

# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'

# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'

# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.2'

group :doc do
  # bundle exec rake doc:rails generates the API under doc/api.
  gem 'sdoc', require: false
end

# Use ActiveModel has_secure_password
gem 'bcrypt-ruby', '~> 3.0.0'

gem 'protected_attributes'

# Use unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
gem 'capistrano', group: :development

(You are not limited to code and resources you create in the IDE. There is a handy “Upload Files” feature.)

BE SURE YOU HAVE SAVED ALL THE CHANGES

Back at the console, run bundle update to get all the necessary gems. Run these two commands to migrate the database (in the DEVELOPMENT environment)

RAILS_ENV=development && bundle exec rake db:create
RAILS_ENV=development && bundle exec rake db:migrate
Preview

At the command line type rails server.

This will startup the Webbrick development server. The port it uses (by default) is 3000. Notice also there is a choice, under the Preview menu, for this.

If you prefer another server (such as Thin) just install it.

PreviewMenu
Click Preview Port 3000 to see the results of your efforts.

Try out the application. Register a user account then log in and try logging out.

This is only a skeleton of a Rails Application. But it cannot run from here, this is only for development. We still need to deploy it.

Deploy

You can use the console client to deploy to Heroku, use Capistrano or another favorite deployment tool. You will need to fetch the SSH key for your Box, as mentioned earlier, to use SSH authentication to your deployment target.
If you choose to deploy to Heroku, you need to first set up git and the Heroku site has documented that procedure extremely well.

Tests

Test Driven Development, right? So we should have written some tests first.
I will leave that to you before adding any more functionality to this project. The goal here was to demonstrate how simply you can construct a new Rails application.

Github

There is a simple facility to fetch the SSH Public Key and establish a connection to your Github account.
PublicKeyGithub
And, this is another way to earn some additional N20 on your account!

Collaboration

Nitrous.IO also supports a very slick Collaboration capability which allows you to interactively work on the application with other developers. The details of that are far beyond the scope of this article but there is an excellent description in the Nitrous Help center.

Guidance @ Every Step

The people behind Nitrous are developers and believe strongly in “Developer Happiness”.

The Help is very clear and quite complete. There should never be a point where you feel lost or stuck.
There is an “invite” button on the toolbar which allows you to share Nitrous.IO and earn some more N20 for yourself.

Nitrous.IO was obviously written BY developers and FOR developers. It provides the promise of working entirely “in the cloud”.

With the constantly growing availability of Wireless Internet Access, and a trend of working in a ‘mobile’ state, it simply makes sense to create/updated/maintain Rails applications in the cloud.

No longer am I tied to any particular device when developing Rails applications. And, regardless of my location or the hardware to which I have access, I can start, continue and complete ANY Rails project remotely. Migrating to a new computer no longer cripples me during the time it takes to get the environment ‘just right’. I anticipate that one day very soon my “hardware requirements” for a computer (albeit laptop, tablet, phone) will be no more than WiFi capability.

Yehuda Katz has reported “Nitrous.IO and ChromeOS are really a match made in heaven“. Since the time that article was written there is a new Chrome Packaged App for Nitrous.

{All the code for this article is available at this Gist}

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • AJ Solimine

    Thanks Thom! This article is a really great overview of Nitrous.IO and the benefits it offers developers. I wanted to point out that the Autoparts package manager is really helpful for applications that require any backing service like MongoDB, PostgreSQL, MySQL, Redis and more.

    There’s also a Meteor package that comes bundled with everything you need so getting started with Meteor is as simple as `parts install meteor`. You can read more about Autoparts here:

    http://help.nitrous.io/autoparts/

    Great article!

  • Jeremy

    It sounds like a well implemented solution. I’ve tried a couple of “cloud” development environments in the past and they were also quite good. But I’ve never got beyond the fact that I’m far more likely to encounter a flaky internet connection than I am to not have my laptop nearby.

  • Tim

    Nitrous.IO is an awesome service and this is a great overview of how it works and why it’s so important. Sometimes I’ll be working on a project on one computer and switch to another (desktop to laptop, for example) only to realize the environment is totally different and my project won’t run. With Nitrous.IO I don’t have to ever worry about that again!

  • Anonymous

    I’m a fan. The new `Parts` option is killer.