Ok, this will be a little longer:
If you are already familiar with Rails, you can check out the Rails API gem . The project aims to remove additional crack from Rails, which is not needed for the JSON-based RESTful API.
It may sound smooth, but it has flaws. First of all, you have everything you need for the basic functions of the rails, which you can get used to, for example, respond_to . It may be a little tricky, but pretty simple when you find out which rails module originally provided the functionality typically associated with Rails in ActionController::Base .
Having said that, let me give an example of what I did for a small API project that I did last week out of curiosity:
initial situation
We have the main Rails application. Everything works fine, but mostly monolithic. Everything is served by the Rails Framework. Fortunately for us, all of the model logic comes in a gem called core . the application essentially allows registered customers to create products that are searchable through the end-user view.
The goal was to provide a RESTful API for this, which can handle concurrency and larger data files (e.g. CSV, XLS) somewhat more efficiently.
Introducing the Rails API
The purpose of the design allows me to use the Rails API gem. The main installation works like in Rails, with the exception of a script called rails-api , that is:
rails-api new jsonapi
The advantage for me here was that I could use core from another application, but nothing would stop me from simply injecting my own models into the jsonapi application.
This way you can use all the standard Rails attributes such as routing, etc. He follows the same convention. again, standard routes initially only respond to JSON, which can sometimes get a little confusing.
Let me give an example of an API controller that processes products:
class ProductsController < ApplicationController include ActionController::HttpAuthentication::Token before_filter :find_product, :except => [:create, :index] def index render :json => @products end def create @product = product.new params[:product] if @product.save render :json => @product, :status => :created else render :json => @product.errors, :status => :unprocessable_entity end end def show render :json => @product end def update if @product.update_attributes params[:product] render :json => @product, :status => :ok else render :json => @product.errors end end def destroy if @product.destroy render :json => @product, :status => :ok else render :json => {:note => I18n.t("messages.deletion_impossible")}, :status => :unprocessable_entity end end protected def find_product @product = Product.find params[:id] end end
This is nothing special. The only thing to note is the second line, in which ActionController::HttpAuthentication::Token is explicitly enabled. This means that your aPI can be protected with an HTTP token. If you want to learn more about providing APIs, I offer Ryan Bates a "Railscasts Guide . "
Basically, you provide a filter before the ApplicationController as follows:
class ApplicationController < ActionController::API include ActionController::HttpAuthentication::Token::ControllerMethods [...] before_filter :restrict_access [...] def restrict_access authenticate_or_request_with_http_token do |token, options|
Again, pay attention to the second line, you must enable ControllerMethods manually, otherwise the controller will not know about authenticate_or_request_with_http_token .
Extension
You can know how to extend the API based on Rails conventions. It works exactly the same, except that some things are intentionally missing by default. I suggest adding JBuilder ( Railscast ) if you need more flexibility in your JSON templates.
Great, but what about customers?
Personally, there are many choices when it comes to customers. Ultimately, I find that it comes down to what you like best. I personally recommend a small node.js layer on top of the Rails API, which then gets a one-page application based on backbone.js in front of it. You can also try AngularJS if you want. You can also create another Rails application around it and call the API from your controller actions.
It also depends on which platform you want to target - the native iOS / Android application comes to mind.
The choice I made was node.js + basebone. This currently makes sense to me at that time and for the project. The node level essentially contains the token needed to communicate with the API, and the base application has a small library for communicating with the node layer. However, it can be a double-edged sword, depending on how complex your API will be. For a small example, this seems fine, but there can be a lot of code duplication to simply transfer calls from the underlying application to the Rails API.
Authentication
For authentication, you can create client API keys (tokens), and then restrict the controller logic to only accepting operations with data that are allowed with this key. You can manage the session through the node layer. Edit: This is authorization, not authentication. Nothing actually stops you from using Authlogic with the Rails API - I have not tested it, but it should work.
I admit that I have not finished this part yet - I hope that others can answer this architectural question :-)
Hope I could give some ideas.
PS: If you want to test your API, I highly recommend httpie (this is awesome!)