How to generate custom response for REST API with Ruby on Rails? -
i'm implementing rest api in rails 3. allow json , xml response formats.
the default respond_with works fine long 1 wants requested resource returned, e.g.:
def show respond_with user.find(params[:id]) end /users/30.xml <?xml version="1.0" encoding="utf-8"?> <user> <birthday type="date">2010-01-01</birthday> <company-name>company</company-name> <email>email@test.com</email> <id type="integer">30</id> </user> however, following standardized response:
<?xml version="1.0" encoding="utf-8"?> <response> <status> <success type="boolean">true</success> </status> <result> <user> <birthday type="date">2010-01-01</birthday> <company-name>company</company-name> <email>email@test.com</email> <id type="integer">30</id> </user> </result> </response> how can achieve result?
i tried following, using custom response class
class response status_codes = { :success => 0, } extend activemodel::naming include activemodel::serializers::xml include activemodel::serializers::json attr_accessor :status attr_accessor :result def initialize(result = nil, status_code = :success) @status = { :success => (status_code == :success), } @result = result end def attributes @attributes ||= { 'status' => nil, 'result' => nil } end end and redefining respond_with method in applicationcontroller:
def respond_with_with_api_responder(*resources, &block) respond_with_without_api_responder(response.new(resources), &block) end alias_method_chain :respond_with, :api_responder however, not yield intended result:
<?xml version="1.0" encoding="utf-8"?> <response> <status> <success type="boolean">true</success> </status> <result type="array"> <result> <birthday type="date">2010-01-01</birthday> <company-name>company</company-name> <email>email@test.com</email> <id type="integer">30</id> </result> </result> </response> what should <user> again <result>. gets worse when return array result, <result> layer. , if @ json response, looks fine – notice there array [] wrapping user resource.
get /users/30.json {"response":{"result":[{"user":{"birthday":"2010-01-01","company_name":"company","email":"email@test.com"}}],"status":{"success":true}}} any clue going on here? how can desired response format? tried looking writing custom responder class, boiled down rewriting display method within actioncontroller:responder, giving me exact same problems:
def display(resource, given_options={}) controller.render given_options.merge!(options).merge!(format => response.new(resource)) end i believe problem somehow hidden in serialization code of activemodel, can't seem figure out how can wrap resource within container tag , still achieve wrapped resource being serialized correctly.
any thoughts or ideas?
here's did in end:
i got rid of response class.
i added to_json , to_xml methods models:
[:to_json, :to_xml].each |method_name| define_method(method_name) |options = {}| options ||= {} options[:only] ||= # filtering super(options) end endi redefined respond_with method in applicationcontroller:
def api_respond_with(resources, &block) default_respond_with |format| format.json { render :json => resources, :skip_types => true, :status => :ok } format.xml { render :xml => resources, :skip_types => true, :status => :ok } end end alias_method :default_respond_with, :respond_with alias_method :respond_with, :api_respond_withi wrote custom middleware appropriate methods add desired wrapping:
class standardizedresponsefilter def _call(env) status, headers, response = @app.call(env) if headers['content-type'].include? 'application/json' response.body = standardized_json_wrapping(response.body, env) elsif headers['content-type'].include? 'application/xml' response.body = standardized_xml_wrapping(response.body, env) end [status, headers, response] end end
if knows better approach, feel free leave comment.
Comments
Post a Comment