Separating Logic and Data into Separate Applications with Rails and ActiveResource

Most Rails apps, and indeed, most web apps, combine data access and business logic into one single codebase. However, there are times when it make sense to separate business logic and data access into two separate standalone apps. Two use cases come to mind, but there are certainly others. The first is the ability to separate scalability of data access and scalability of business logic. A high data throughput app might benefit from scaling out the back end data access app independently of the front-end app. Another use case is the desire to have multiple front-end applications access the same data store — a web app and a mobile app, for example.

ActiveResource is a library that helps achieve decoupling of business logic and data access by enabling breaking up a single Rails app into two distinct and separate Rails apps. At it’s core, ActiveResource provides a way for two Rails applications to communicate with each other by abstracting out the interface between the apps and providing a map between RESTful resources and mutable Ruby objects; this is accomplished by enabling a back-end codebase (the ActiveResource) and the front-end codebase. Two applications is just the basic implementation, in reality, you can easily have 5 Rails applications all reading to and writing from a common back end ActiveResource-powered Rails application.

With the release of Rails 4.0, ActiveResource was extracted into a separate gem, so Rails 4.0+ users, you’ll need to use the gem that can be found here on github, for Rails <4.0 users, you should already have access to ActiveResource.

Depending on your use case, you may want to use ActiveResource the traditional way (RESTful resources mapped to Ruby objects), or you may opt for a more API-centric interface.

One of the greatest benefits to using ActiveResource is that it allows for scaling related properties quickly and easily without reworking or rebuilding existing functionality. For example, if you have a back-end (ActiveResource) that houses all of your data and a front-end that users use to interact with that data, but would like to offer a new product that also interacts with that data, you can create a separate front-end and wire it directly into your ActiveResource without having to worry about duplicating or syncing your dataset into a new project — simply build out your new product and your new features and wire it up to the existing ActiveResource.

Another benefit is that, by using ActiveResource, you can have all of your related properties talk to each other easily. For example, if you have a dedicated ecommerce platform, but also offer several other properties where your users can utilize their purchased products, you can wire all of your web properties into a single ActiveResource back-end that allows for easier data management and cuts down on possible mistakes in syncing or data transport between systems.

There is very little configuration that goes into enabling an ActiveResource:

Back-End (ActiveResource):

Nothing

Front-End:

You will need to modify your models so that they no longer inherit from ActiveRecord and instead inherit from ActiveResource like so:

class Object < ActiveResource::Base
end

You’ll also need to ensure that the models know where the ActiveResource resides by providing a value for the “site” class variable:

class Object < ActiveResource::Base
  self.site = ACTIVE_RESOURCE_URL
end

And, for Rails 4.0+ users, you’ll need to ensure that you’ve added the ActiveResource gem.

Many posts and forums utilize ActiveResource the traditional way:

Object.new(param1: value1)
Object.find(1)
Object.find(1).delete()

But very few focus on the ability to specify custom REST methods to accomplish other actions beyond the typical CRUD actions:

For example, this sends a custom request (GET) to the “widgets” route of the “Factory” class:

Factory.get(:widgets)

Whereas:

Factory.post(:endpoint, nil, {param1: value1, param2: value2}.to_json)

Performs a POST request to “endpoint” on the “Factory” class.

These are just some of the basic implementations; what follows is a set of tips that I have found useful when building out new web apps.

For the POST request, the hash of param / value pairs being converted to JSON allows for sending the POST params in the body of the request rather than as part of the query string. This is exemplified in the following examples:

# params sent in the request body
Factory.post(:endpoint, nil, {param1: value1, param2: value2}.to_json)
=>Started POST "/factories/endpoint.json”
=>Processing by FactoriesController#endpoint as JSON
=>Parameters: {"param1"=>"value1", "param2"=>"value2", "factory"=>{}}
# params sent in the query string
Factory.post(:endpoint, param1: value1, param2: value2)
=>Started POST "/factories/endpoint.json?param1=value1&param2=value2"
=>Processing by FactoriesController#endpoint as JSON
=>Parameters: {"param1"=>"value1", "param2"=>"value2", "factory"=>{}}

In order to use these endpoints (custom or otherwise) they must be specified in the routes file of your ActiveResource.

When developing locally it’s important to have your ActiveResource running on one port while your front-end runs on another. You can take out the guess work by forcing ActiveResource onto a non-standard port and leaving your front-end alone by adding the following to the config/boot.rb file:

module Rails
  class Server
    alias :default_options_alias :default_options
    def default_options
      default_options_alias.merge!(:Port => 3333)
    end
  end
end

There you have it, your number one resource for ActiveResource.

 

In all seriousness, read the documentation:

http://www.rubydoc.info/github/rails/activeresource/ActiveResource

http://apidock.com/rails/ActiveResource/Base

https://github.com/rails/activeresource

 

Feel free to leave comments with any questions and I’ll be happy to answer them, and feedback is welcome too!