Normally when you build a web or mobile application, you will have to build seperate backend because most web framework originally means to generate data along with dynamic HTML templates. But if we think that web application is just a form of native applications and we treat it that way, generate only data and just use static HTML to handle the logic. This way, we can reuse our backend to almost every native applications we want.

If you’re asking for some BIG example out there that use this trick, Try Twitter.com

Why use Rails ?

  • Huge resources and communities that provide almost everything you want to build applications.
  • Very clean Routing and easy to use.
  • Secure enough.
  • Easiest (in my opinion) to debug using better_errors and binding_of_caller.
  • I want to use Rails, that’s all.

Beyond this point require Ruby and Rails installed already.

Getting started: Rails-API

Assuming that you’ve already installed Ruby(1.9.3+) and Rails(3.2+) already, today we use this nicely done gem to help us prepare new application

$ gem install rails-api
$ rails-api new contact-api

with Rails-API we’ll get only essential part of Rails to build API instead of getting all heavy and unnecessary features from traditional Rails. And now we have our newly created app called contact-api

Then put this on your gemfile and run “bundle install”, this will make your life a lot easier.

group :development do
  gem 'better_errors'
  gem 'binding_of_caller'
end

Rails time

Since there’s only API, so we don’t need to setup things like HTML template or homepage here. Let’s generate contact by using

$ rails g scaffold contact name:string email:string
$ rake db:migrate

If you’re running on Rails 3+, you need to put these line in your app/model/contact.rb

attr_accessible :name, :email

If Rails 4+, in app/controllers/contacts_controller

def create
  @contact = Contact.new(contact_params)

  if @contact.save
    render json: @contact, status: :created, location: @contact
  else
    render json: @contact.errors, status: :unprocessable_entity
  end
end
private

def contact_params
  params.require(:contact).permit(:name, :email)
end

and then run your rails server with

$ rails s

Try access by your browser to localhost:3000/contacts and you will see an empty JSON “[]” there. Now let’s try to make it error by access to localhost:3000/contacts/test and you’ll see error like below. contact error

Obviously, it’s a “Not found” error because we try to access object Contact that have id = “test” which doesn’t exist. On the right side, you’ll see a very handy shell that you can play with it like how you play in “rails console”. And since we have our console right before our eyes, we should try something.

Contact.create!(name:"John", email:"[email protected]")

and result is

contact create

Now we can try to access localhost:3000/contacts/1 and you will see JSON of your newly created contact. contact 1

Prepare for CORS

What we trying to do here is to actually access to Rails server(localhost:3000) from another server instance. So it’ll inevitably face with CORS problem and here we’ll cover that problem before it’s occured with rack-cors

Put this line in Gemfile

    gem 'rack-cors', :require => 'rack/cors'

then

    bundle install

Finally, put this code in config/application.rb inside class Application and it’ll look like this.

module ContactApi
  class Application < Rails::Application
    #.....
    config.middleware.use Rack::Cors do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :options]
      end
    end
  end
end

Restart Rails server and it’ll become accessible from every origin.

HTML time

It’s time to build our static site to serve as a native client for contact-api. But before that, we have to choose which server to serve our static files. It can be many things such as another Rails, Node.js, PHP, etc. Whichever is fine but I choose to go with Go, no reason, I just want it. (See details of how easy Go handle static file in previous post)

Below is my jsFiddle(obsoleted) demo using angularjs as a client to add contact object by using Rails backend as API only. Or you can play a demo at this Google App Engine Site

All the code can be found at Github