Add JSON support to Rails app - ruby-on-rails

I am experimenting with Rails and was wondering what's needed to allow/add support for JSON requests?
I have a vanilla installation of Rails 2.3.5 and the default scaffolding seem to provide support for HTML & XML requests but not JSON.
class EventsController < ApplicationController
# GET /events
# GET /events.xml
def index
#events = Event.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #events }
end
end
# GET /events/1
# GET /events/1.xml
def show
#event = Event.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #event }
end
end
...
I'm new to this but it would appear as though i would need to add a format line in each method along the lines of:
format.js { render :js => #event.json }
couldn't this be done automatically? perhaps there's a template somewhere i need to update...or a flag i can set? Or perhaps, and most likely, I've missed the boat entirely?!?

You do:
format.json {render :json=>#event}
That will render the default activerecord JSON for the model
The option of ease of use is that you can write a private method which takes the format object and an object to render and then, based on the format, renders different things. Example:
class MyController<ApplicationController
def show
#event=Event.find(params[:id])
respond_to do {|format| myRenderer(format,#event)}
end
...
private
def myRenderer(fmt,obj)
fmt.json {render :json=>obj}
fmt.html
fmt.xml {render :xml=>obj}
end

Related

ActionController::UnknownFormat in CoinsController#index

In my CoinsController, I have added a respond_to method in my index controller. I'm not sure if my code is right but here is my index controller below:
def index
paginated = paginate(Coin.recent)
render_collection(paginated)
respond_to do |format|
format.json do
format.html # index.html.erb
format.json { render json: render_collection(paginated) }
end
end
end
I read the few documents I found online about respond_to do |format| method and when I tried adding it manually the way it is in the documentation, I get an Unknown Format error. What I'm trying to do is have logic that handles both html and json, so that it can act as a json api and a view renderer.
Any ideas?
Ok guys so I found out the solution to my problem:
def index
paginated = paginate(Coin.recent)
# render_collection(paginated)
respond_to do |format|
format.json do
render_collection(paginated)
end
format.html do
render :index
end
end
end
I had commented out the render_collection(paginated) and then added json and html to it's own block and it worked.

Rails: respond_to JSON and HTML

I have a controller "UserController" that should respond to normal and ajax requests to http://localhost:3000/user/3.
When it is a normal request, I want to render my view. When it is an AJAX request, I want to return JSON.
The correct approach seems to be a respond_to do |format| block. Writing the JSON is easy, but how can I get it to respond to the HTML and simply render the view as usual?
def show
#user = User.find(params[:id])
respond_to do |format|
format.html {
render :show ????this seems unnecessary. Can it be eliminated???
}
format.json {
render json: #user
}
end
end
As per my knowledge its not necessary to "render show" in format.html it will automatically look for a respective action view for ex : show.html.erb for html request and show,js,erb for JS request.
so this will work
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
also, you can check the request is ajax or not by checking request.xhr? it returns true if request is a ajax one.
Yes, you can change it to
respond_to do |format|
format.html
format.json { render json: #user }
end
The best way to do this is just like Amitkumar Jha said, but if you need a simple and quick way to render your objects, you can also use this "shortcut":
def index
#users = User.all
respond_to :html, :json, :xml
end
Or make respond_to work for all the actions in the controller using respond_with :
class UserController < ApplicationController
respond_to :html, :json, :xml
def index
#users = User.all
respond_with(#users)
end
end
Starting from Rails 4.2 version you will need to use gem responder to be able to use respond_with.
If you need more control and want to be able to have a few actions that act differently, always use a full respond_to block. You can read more here.

set a rails controller's response type to xml

i'm quite new to rails. i'm trying to set a rails controller's response type to xml, but not having much luck. i could certainly afford to better understand how respond_to and respond_with work.
here's what my controller looks like:
class ResponsesController < ApplicationController
respond_to :xml
def index
require 'rubygems'
require 'telapi'
ix = Telapi::InboundXml.new do
Say('Hello.', :loop => 3, :voice => 'man')
Say('Hello, my name is Jane.', :voice => 'woman')
Say('Now I will not stop talking.', :loop => 0)
end
respond_with do |format|
format.xml { render }
end
puts ix.response
end
end
this leads to an http retrieval failure. can someone advise me how to how i can fix the controller and set its response type to xml? also, a cogent 1-2 liner of how respond_to and respond_with work would be awesome!
thanks everyone.
replace
respond_with do |format|
format.xml { render }
end
with
respond_with(ix)
There are 2 ways of rendering a xml. Example 1 uses respond_to that means "every single method will use xml and use the object parse in from respond_with"
Example 2 uses respond_to that means "use the block below to declare what type of respond and the object to be parse"
example 1:
class ResponsesController
respond_to :xml #respond_to A
def index
respond_with(#asd) # respond_with A
end
end
example 2:
def ResponsesController
def index
respond_to do |format|
format.xml { render xml: #asd}
end
end
end
http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/

Rails code generated with ORM mangomapper throws NoMethodError (undefined method `each' for "4d2aeaea4403baa84a000005":String)

I am absolutely totally news to Rails and to MongoDB. I have been following tutorials from a good book and create my first Rails app with a light Twitter copy. Everything went fine and smooth.
But as part of my learning process I wanted to build the same app using MongoDB rather than the default SGBD.
I therefore configured mongo and installed the mongo_mapper gem. Everything has been configured properly following this tutorial: http://www.mongodb.org/display/DOCS/Rails+3+-+Getting+Started. Then I struggled a little bit to allow Rails generate to work without throwing me the --orm not specified error. In order to get past this I had to add the rails3-generators gem and add it to the Gemfile.
Once all this was done, everything worked fine. I was able to successfully launch the Rails server.
I added a User controller thanks to the generate. The page works fine and even lists the users I have previously added:
However all the other actions, showing, editing, deleting, etc. are not working (creating works, but then it goes to show and the errors comes):
It's virtually the same error for all different actions.
The one difference I can notice right off the bat is that with the non MongoDB db, the id's of the user was starting at 1, etc. but here with MongoDB it looks like a randomly generated id that is much more complex and that is not of type int: 4d2ae91d4403baa84a000002
I am thinking that this may be creating the issues, since all action are using the id as a parameter... but I have no idea how to fix this. I have looked at the ruby generated code and it looks alright to me (extremely similar to the code generate for the default db).
Any help would be greatly appreciated ! I don't know how to go forward with my project without solving a simple generate code with mongodb.
Thanks,
Alex
ps:
please that I did not write any of this code at all. everything has been generated, which is kinda why I expected to work from the get go...
as asked here is the code for users_controllers:
class UsersController < ApplicationController
# GET /users
# GET /users.xml
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
# GET /users/1
# GET /users/1.xml
def show
#user = User.first(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/new
# GET /users/new.xml
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/1/edit
def edit
#user = User.first(params[:id])
end
# POST /users
# POST /users.xml
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to(#user, :notice => 'User was successfully created.') }
format.xml { render :xml => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.xml
def update
#user = User.first(params[:id])
respond_to do |format|
if #user.update(params[:user])
format.html { redirect_to(#user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
#user = User.first(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
end
Hummm so it seems I found the pb...
I replaced:
#user = User.first(params[:id])
by
#user = User.find(params[:id])
But again, this code was generated... so where does the error come from ? Is there a "bug" in rails3-generators ? Or somehow I screwed up the generation ?
Alex

rails reusing view templates

A rails newbie here
I have 2 actions in my controller 1) index 2) refine_existing.
Both of them show the results in the same format.
How do I reuse the index.html.erb file?
When I try the following, it complains about refine_existing.erb not being present.
def refine_existing
...
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #results }
end
end
my index action looks like this
def index
#some logic to get #results
#set some session variables etc.
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #results }
end
end
Do I have to refactor my index view to contain partials that
a) make the headers
b) render #results
and reuse them?
Even though, both index.html.erb and refine_existing.html.erb will look exactly the same
Is there any way I can say in my refine_existing action to use index.erb view?
thanks in advance
By convention, if you don't specify a template name Rails looks for one matching the action. You can override this by calling render explicitly with the desired template name. The only wrinkle is that the path is relative to TEMPLATE_ROOT, which is normally app/views:
def refine_existing
...
respond_to do |format|
format.html { render :template => "<table_name>/index.html.erb" }
end
end
replacing table_name with the "tablized" form of the model. E.g. if your controller is PostsController, then posts. So your template would then live in app/views/posts/index.html.erb -- if you've customized paths somehow adjust as necessary.

Resources