Multiple JSON responses in a single Rails controller action - ruby-on-rails

I have my show method on a controller in my application and in the response block I have
respond_to do |format|
format.html { render :layout =>'placing', :next_days => #next_days}# show.html.erb
format.xml { render :xml => #artist }
format.json { render :partial => "places/show.json", :artist => #artist } }
end
This, generates a json output based in the show.json partial in /places/1.json for example, but what if I want one more json output, like /places/alternative_1.json? How can I do that if there is already a json format block inside respond_to?
Any help is appreciated!
Cheers!

Then you will have to make some logic inside your format.json block changing what you are associating to :partial (currently is "places/show.json"), or create another route...
As format.json { render ... } is normal Ruby code, you could do something like:
format.json do
json_partial = json_for_this_case #example
render :partial => json_partial, :locals => {:artist => #artist}
end

Related

Passing multiple parameter in respond_to block in rails

In my line_items_controller in create action I have following code
format.xml { render 'carts/_cart.html.erb',
:status => :created, :location => #line_item }
I need to send #cart as well here. I tried this
format.xml { render 'carts/_cart.html.erb', #cart,
:status => :created, :location => #line_item }
But this is not working. Could you please tell me how to do this?
Same way as :location
format.xml { render 'carts/_cart.html.erb', :status => :created, :location => #line_item, :cart => #cart }
Notwithstanding you're trying to create an xml response with an html file, have you considered this:
format.xml { render :partial => 'carts/cart', :status => :created, :location => #line_item }
This should handle #cart in the partial, as #cart is an instance var
Here is a more in-depth description of the respond_to block which you may be able to glean some nuggets from
I also found this resource for you: Rails format.xml render and pass multiple variables. The epic reply on there basically suggests that you define your instance variables in your function, and then use them in the action.xml.erb file, like this:
#app/controllers/home_controller.rb
def index
#users = ...
#another = "Hello world!"
# this `respond_to` block isn't necessary in this case -
# Rails will detect the index.xml.erb file and render it
# automatically for requests for XML
respond_to do |format|
format.html # index.html.erb
format.xml # index.xml.erb
end
end
#app/views/home/index.xml.erb
<?xml version="1.0" encoding="UTF-8"?>
<document>
<%= #users.to_xml # serialize the #users variable %>
<extra_string><%= #another %></extra_string>
</document>
That's all I got right now

Writing method for form posts a blank field

I am running rails 3.2
I have created a nested form (requests > tags) with coffeescript handling the addition of new tags.
Everything works with the exception of the form posting a blank tag.name
I am trying to write a method to delete the blank field before the form posts. I realize this may be the wrong approach, but I am still a beginner:
requests_controller.rb
def create
#request = current_user.requests.build(params[:request])
#tag = Tag.new
if #tag.name.blank?
destroy_blank
end
respond_to do |format|
if #request.save
format.html { redirect_to(#request,
:notice => 'Request was successfully created.') }
format.json { render :json => #request,
:status => :created, :location => #request }
else
format.html { render :action => "new" }
format.json { render :json => #request.errors,
:status => :unprocessable_entity }
end
end
end
request.rb
def destroy_blank
blank = #tag.name
blank.delete
end
I hope that's clear. If not let me know and I will include more information.
If you can't stop blank tags from coming in, you can create a before_create filter in the model to skip saving blank tags. Leave the controller clean and simple.
Good luck!

How to convert this respond_to options to use Rails 3 version?

respond_to do |format|
if #user.save
format.js { render :nothing => true, :status => :ok, :location => #user }
else
format.js { render :json => #user.errors, :status => :unprocessable_entity }
end
end
All options I've tried (like putting respond_to :js at the top of controller, etc) don't quite work the way as in this.
Rails 3 Format:
Use respond_to :json and respond_with(#user)
respond_to :json # You can also add , :html, :xml etc.
def create
#user= User.new(params[:user])
#---For html flash
#if #user.save
# flash[:notice] = "Successfully created user."
#end
respond_with(#user)
end
# Also, add :remote => :true, :format => :json to the form.
Try using format.json instead of format.js in your controller and :remote => :true, :format => :json in corresponding form.
Though, I'm not quite sure whether format.json or format.js should be used in that case. As default scaffolding from Rails 3 generates controllers with format.json and you're doing render :json in response I believe format.json is the right way to go. And format.js should be used when you return a piece of JS that should be executed.
The URL your are requesting should end with .json like this: /controller/action.json
If that is not possible:
You should set the 'accepts' parameter to 'application/json' while sending the ajax request.
Search for how to use 'accepts' here: http://api.jquery.com/jQuery.ajax/
And in the server side:
format.json { render :json => #user.errors, :status => :unprocessable_entity }

Redirect view after saving Rails model

When I:
self.save
or
save!
in a model it automatically redirects me to the show view for that given model. How can I override this? I want to save the model and then go to another action/view in the same controller.
In particular, I have a process where I save a members details, and then I want to continue the process by going to the next page, e.g. payment page, that uses the id of the saved model.
In your controller you might have a block like:
def create
#user = User.new(params[:place])
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
You can change the target of the redirect_to (after format.html) from here - at present it is directing you to the record for that user, ie. #user. Take a look at http://api.rubyonrails.org/classes/ActionController/Base.html for a bit more info.
You likely have a block like this in your create/update methods:
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
So if your instance variable is named #post, and it's redirecting to the show view for the post after it saves, all you have to do is change the "redirect_to(#post, ..." part to whatever you want. Say you wanted to redirect to the root of your site - you could instead have
redirect_to(root_path, :notice => 'Post was successfully created.')
In your particular case, you could use something like this if you have your routes set up:
redirect_to(payment_page_path(#post), :notice => 'Post was successfully created.')
Hope that helps!
if you call save from your Model you will not be directed anywhere, it just does a direct model access save to the database. Your redirections are described in your controller in your create and update actions. you can find a list of routes by running rake routes and then pick the path you want your app to render when you save your model instance. you may have a route called payment_path which might look like this in your controller
map.payment :controller => :payments_controller, :action => index
and you would say in your create action
def create
if #item.save(params[:item])
redirect_to payment_path
else
flash[:error] = "there was a problem"
render :action => buy
end
end
if you need to pass a param, like user id to your route, then you need to include that in the path parameters
redirect_to payment_path(#user) #=> automagically finds the id of active record models

In Rails 3, respond_to and format.all works differently than Rails 2?

the code
respond_to do |format|
format.html
format.json { render :json => #switches }
format.xml { render :xml => #switches.to_xml }
format.all { render :text => "only HTML, XML, and JSON format are supported at the moment." }
end
the above will work in Rails 2.2.2. But in Rails 3, getting controller/index.html or index on the browser will both fall into the last line: "only HTML and JSON format are supported at the moment."
The only Rails doc I can find on this is
http://api.rubyonrails.org/classes/ActionController/MimeResponds/ClassMethods.html#method-i-respond_to
which current only states:
respond_to :html, :xml, :json
but they need separate templates for json and xml, and can't handle the "only HTML and JSON format are supported at the moment" case.
In rails3 you would write:
respond_with(#switches) do |format|
format.html
format.json { render :json => #switches }
format.xml { render :xml => #switches }
format.all { render :text => "only HTML, XML, and JSON format are supported at the moment." }
end
But this only works in correspondence with a respond_to block at the top of the file, detailing the expected formats. E.g.
respond_to :xml, :json, :html
Even in that case, if anybody for instance asks the js format, the any block is triggered.
You could also still use the respond_to alone, as follows:
#switches = ...
respond_to do |format|
format.html {render :text => 'This is html'}
format.xml {render :xml => #switches}
format.json {render :json => #switches}
format.all {render :text => "Only HTML, JSON and XML are currently supported"}
end
Hope this helps.
You may find it useful to watch this episode of railscasts, which illustrates the changes to controllers in Rails 3 and in particular the changes to the responder class (putting respond_to in the controller class itself and only using respond_with #object in the action):
http://railscasts.com/episodes/224-controllers-in-rails-3
The following works for me. I believe you have to specify the "render" part for html explicitly or it will use the format.any.
respond_to do |format|
format.html { render :html => #switches }
format.json { render :json => #switches }
format.xml { render :xml => #switches }
format.all { render :text => "we only have html, json, and xml" }
end

Resources