November 10, 2014

Service Design Patterns in Rails: Request and Response Management

This is the second post on the Service Design Patterns in Rails. The first one was about Client-Service Interaction styles patterns. This one is about Request and Response Management patterns (from the book Service Design Patterns by Robert Daigneau).

The Request and Response Management patterns are:
  • Service Controller
  • Data Transfer Object
  • Request Mapper
  • Response Mapper

Service Controller pattern means that there is a class that decides which controller should be called. The decision is made based on the Request (for example "GET /customer/123") and a set of rules.

Does it sound familiar? Yes! This is the routes.rb file. Here is the simplest rule of all:

resources :products

which means, any request to /products will be routed to the products controller.

The Data Transfer Object is an intermediate object used in the request or the response instead of using the domain objects. That is, instead of serializing the Products object on the typical rails example, you would instead use another object populated from the values in the Product.

On the request side, this is achieved through the params object. See this code which is typically in the typical Products controller example:


    def set_product
      @product = Product.find(params[:id])
    end


this is how we find in the database a product with id "params[:id]".
"params[:id]" is the 123 from "GET products/123" request.

Another example, when we want to update, how we update it with the params object:

def update
  respond_to do |format|
    if @product.update(params)
    ....
    else
    ...
    end
  end
end


However, in the response side I have bad news. A rails typical application is not using a Data Transfer Object. See the typical example:

class ProductsController < ApplicationController
  def index  
    @products = Products.all        
    respond_to do |format|                                                      
      format.json { render json @products}   

    end
  end
end

This code means that the object used in the response, is the Products object serialized as json. Under the hoods, the "ActiveRecord::to_json" call is made for this purpose. This means that the response is highly coupled with the domain object.

What we should do instead is rendering the response in the view, by using a template.

Rails does come with builder for "xml templating". If we were using xml for the response, the following code will work as long as we had an index.xml.builder file.

class ProductsController < ApplicationController
  def index  
    @products = Products.all        
    respond_to do |format|                                                      
      format.xml  
    end
  end
end

Thus, for json to work, we would expect something like:


class ProductsController < ApplicationController
  def index  
    @products = Products.all        
    respond_to do |format|                                                      
      format.json
    end
  end
end


However, rails does not come by default with "json templating" and thus the previous code won't work unless we add some "json templating" gem.

Researching a bit on google, I've found this post that explains the case very well and much better than I could and gives some options on "json templating":



Finally, Request and Response Mapper are two patterns that can be used to interact with different web services, different on the syntax, but semantically equivalent. In that situation, you need an object that maps different request/responses to the same controller.


In the case of the Request Mapper, we get back to the routes.rb file, where you can declare matching patterns. For example if you were authenticating against github, you may have this line on your routes.rb file

  get "/auth/:provider/callback" => "sessions#create"

The Response Mapper is used to construct a response but used by different web services. This can be used when you need to create a response that matches some kind of agreement between different parties. Sadly I don't know of a typical rails example that does that. If you know one, please tell me.
 
 

2 comments:

Benny said...

This is not acceptable to me, and appears to be an rolex replica uk method of increasing the price. I therefore expect to receive credit to my bank of $8 forthwith. I am happy to accept a credit note of $20 from you against a further rolex replica sale. If you can confirm this by email, we can successfully conclude my tag heuer replica. I received my rolex datejust today, I am disappointed, the watch keeps stopping losing At least 5 minutes every hour. The cartier replica sale is rattle and sounds like tin and there is a grind mark on the front of the case of this replica rolex. I'm writing to inform you that I'm extremely rolex replica after having received my Rolex replica sale order. I got the Rolex replica watch about three weeks ago. A couple days after wearing it, I noticed that the hour hand is out of rolex replica sale. It moves faster than the minute hand, so the result is that it's always telling the wrong time, which is rolex replica because I continue to have to reset the Rolex replica. What good is a rolex replica sale that doesn't tell the right time? At this point, I've just left it on my dresser table. I'm sad to have wasted $150 on something that doesn't work.

technode said...

Great stuff , thanks for sharing , very informative and presented well , keep updating morelinux certification courses in chennai|linux class in chennai|linux admin training in chennai|linux training courses in chennai|linux training cost in chennai|chennai linux training|red hat courses in chennai