views:

63

answers:

2

Hi,

I'm curious about the best practice in creating web services which support both XML and JSON output.

At the moment, my service is very XML oriented (see below), but I want to add JSON support.

Here's one example:

  def create
    render_authentication_error and return if !@user
    render_parameter_not_found_error("item") and return if params[:item].nil?
    render_parameter_not_found_error("name") and return if params[:item][:name].blank?
    @item = Item.new(params[:item])
    begin 
      if [email protected] 
        raise "Item not saved" 
      end 
    rescue 
      render_resource_not_saved_error("Error saving #{@item.name}")
    else 
      render_resource_created(:location => item_path(@item))
    end 
  end

There are helper methods in ApplicationController that renders XML accordingly.

I'm not sure how to go about adding respond_to block here since I need to do validations. Is there a way to retrieve format in a controller outside of respond_to block so that I can output error messages in a given format as well?

respond_to do |format|
  format.html { render :json => @item.to_json }
  format.xml { render :xml => @item }
end 

Let me know if you need any clarification.

UPDATE I suppose I'm looking something similar to respond_with in Rails 3. I'm on Rails 2.3 still.. I wonder if it can be done in 2.3?

UPDATE Inherited Resources seems like what I'm looking for.

Thanks!

+1  A: 

It's a little complicated, but it can be achieved. See here:

http://shifteleven.com/articles/2006/11/26/drying-up-respond_to

Also, maybe you can look at request.format and pass it? I am pretty sure it will have the format requested...

rmk
Looks interesting.. and experimental. Not quite convinced to try it out. I'll look into request.format. Thanks for the answer.
Grnbeagle
+1  A: 

Replace @person with @item, but there's the idea:

respond_to do |format|
  if @person.save 
    format.html { 
      flash[:notice] = 'Person was successfully created.'
      redirect_to @person 
    }
    format.js { render :json => @person, :status => :created, :location => @person} 
    format.xml  { render :xml => @person, :status => :created, :location => @person }
  else
    format.html { render :partial => "form" }
    format.js { render :json=>@person.errors, :status => :unprocessable_entity }
    format.xml  { render :xml => @person.errors, :status => :unprocessable_entity }
  end
end
Jesse Wolgamott
I'm hoping to avoid repeating chucks of code like that. Also rendering output from validation failure won't be elegant this way.. Thanks for the answer.
Grnbeagle
Well ok. However, that's pretty much the standard for rails right now. Also, rendering the .errors seems to be really elegant, I like it alot. Good luck!
Jesse Wolgamott
@Jesse Wolgamott I updated the post, but it seems Inherited Resources library is what I was looking for. I'll mark your answer since it's the proper way to go about in pre 3.0. Thanks!
Grnbeagle