I would like to use my form partial for html and js requests. For the second i have to put :remote => true into form_for tag.
Is it possible to read the response type (html, js, ...) and use this as condition in a view?
For instance, this example of respond_to's usage should help you. And for complement: There is a Discussion in Ruby Forum you can take advantage.
respond_to do |format|
format.js { #Magic goes here }
You can also check before the respond_to block by calling request.xhr?. But be aware with the respond_to block. AJAX can respond with html (i.e $.ajax({dataType: 'html'}))
Related
When there is
def some_action
respond_to do |format|
format.html {}
format.js {}
format.json { respond_with #objects}
end
end
It seems like html line and the js line automatically serve up/call the file matching the action's name. And the html and the js are serve up one or the other, not both. Is this correct?
The json gets called if you have an ajax call in your js that got called, and it requests data, and these need data to respond with, right? Do I need it to respond to json and to js, or just one?
If you don't to respond_to, and omit all the types, does it by default respond to html and to js?
When I do respond_to in the controller, rather than a respond_to block within each action, does using respond_with #objects apply to any argument (:thml, :js, :xml, :json, etc)?
Alternate syntax:
class TheController < ApplicationController
respond_to :html, :js, :json, only: [:some_action, :other_action]
def some_action
respond_with #objects
end
end
How does the alternate syntax work?
If you use the alternate syntax, can you not respond differently to different types of requests? Do you have to do a respond_to block isntead of the alternate syntax if you want to respond differently? How do each of these cases address graceful degradation to html?
respond_with
For a given controller action, respond_with generates an appropriate response based on the mime-type requested by the client.
This basically means your controller will send the appropriate data on a request basis - for example, if you did the following:
#app/controllers/articles_controller.rb
Class ArticlesController < ApplicationController
def show
#article = Article.find params[:id]
respond_with #article
end
end
This would basically respond with the data from #article each time you send a request. If the request is in the json mime-type, it will come back as a JSON object; if it's an HTML request, it will come back with the HTML object on the show view
--
respond_to
Basically allows you to tailor the specific responses to different mime-types. If you send a JS request, you can manage the JS response etc
respond_to blocks inside the controller actions are very cumbersome, and only really meant for specific changes / edits to the response itself.
A much simpler way to handle the respond_to is to declare it at the top of the controller file, essentially telling Rails that every action will use the options defined in that method:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
respond_to :js, :json, :html #-> the same as using respond_to block for each action
end
note that in Rails 4 respond_with feature has been extracted to the gem 'responders' (https://github.com/plataformatec/responders).
The cases of when you need/don't need each format.*whatever* line.
Normally, you don't need any of it. Rails by default looks for an html file (aka template) matching the action name under the view folder matching the controller's name.
I'm not sure when/why the json and html are sometimes paired together(like in the scaffold-generated code). Perhaps the json line is for turbolinks (please confirm/correct this). But I do know you use a respond_to block with various types of format lines when you want each type to behave differently (e.g. serve up 10 results at a time through js, but more results through html).
The js format is needed when you use remote: true in a form or link. This is because Using this remote: true disables the html template from being served up, and instead looks for a js file matching the action's name, and executes/renders that file. You don't actually need the respond to json line if you're doing things in js only.
Bonus hint: if your js files have js.erb, you can access the instance variables (how about local variables? please confirm/correct this) that you set in your action. This kind of makes sense because your *.js.erb file is technically a view. Views can access its corresponding actions' variables (hmm what about when vies get rendered from another controller?). So if you already have access to your action's variables in your js file, this can eliminate the need to make ajax calls or json calls in many situations.
I'm actually not sure when you need the json line when also using remote: true / javascript. explicit jQuery.ajax() method calls that want json data might warrant the use of the respond to json line.
I have Vacancies controller and I need to pass #vacancies to json and also render another layout. The following code does not work (json is not passed however I have "wide" layout). If I remove format.html { render layout: "wide"} } json passes correctly. How to combine these two things?
class VacanciesController < ApplicationController
respond_to :html, :json
...
def index
#vacancies = Vacancy.all
respond_with(#vacancies) do |format|
format.html { render layout: "wide"} }
format.json { render json: #vacancies }
end
end
...
You can't call render twice, that's problem #1. You also can't send two responses to a single request.
There is also no purpose in rendering HTML (which means a fresh page load) and sending JSON (which is for AJAX requests, ie requests that don't reload the page) at the same time. It isn't possible, but it also would be pointless even if it was possible.
If you want to tell a request to use a specific layout, you can pass the layout option to a render call. However, a render call does not take a data object as the first argument, it takes a view name, or only an options hash. So to call this correctly you should use:
render :index, :layout => 'example'
I expect that will make your HTML views show up correctly.
Please understand however, the layout option is only useful for HTML responses, not JSON responses. Layout is telling your render call what outer HTML to wrap around the view your action is calling, and if you don't specify it uses 'application.html'
To help you understand one more thing: your respond block is telling the computer how to respond to different kinds of requests. It's like a switchboard. If you wrote it with if/else statements it might look like this:
if request_type == 'html'
render :index, :layout => 'wide'
elsif request_type == 'json'
render :json => #vacancies
else
raise raise ActionController::UnknownFormat
end
So, with your respond_with block, if you fix your html render call, and assuming you're developing on localhost, if you enter the following URL in your browser and hit enter...
http://localhost:3000/vacancies
That would be making an HTML format GET request, which will load the page with layout: 'wide' but no other data. If you type:
http://localhost:3000/vacancies.json
That will simulate a JSON request, and you'll get just the JSON representation of the #vacancies data.
I hope that helps you solve your problem. If not, please describe what you're trying to accomplish in more detail so I can help you understand how to do it.
PS: one last tip: if you want to specify layouts at the controller level you can just call layout at the top of your controller, like so:
class ExampleController < ApplicationController
layout 'awesome', :only => [:new,:edit]
...
end
This works like any other filter, you can pass :only, or :except, or no options at all.
I need to send some html code to another site via API on my rails 2.3 application.
The html code is rendered by another action.
Is there a good way for a controller to get the rendered view html code?
One way I can think of is that action A calls action B via HTTP and get the result.
However, I think this is a waste of resources.
Is there a better way?
Thanks.
Sam
I think you want render_to_string which will send the output of the render to a string, instead of back to the client. Use it in your format.js response block.
See api doc
respond_to do |format|
format.js { render(:partial => 'some_thing.html.erb', :layout => false) }
end
I have a controller named CourseRequests which will be accepting an ajax request for the "new" method.
Since it will be responding with json, should I use /course_requests/new.json?
I don't want to make a template for such a silly json response, how would I do that?
What does respond_to do? (I have seen it block style and I understand that, but what about non-block style)
Yes, your JS would be doing something along the lines of:
$.getJSON("/course_requests/new.json",...);
You don't have to, you just need to have a respond_to block with JSON handled there.
respond_to do |format|
format.json { render :json => "test" }
end
Blockless syntax, I think you mean this: http://davidwparker.com/2010/03/09/api-in-rails-respond-to-and-respond-with/ . Basically, you specify what mime types your controller responds to and then you can use the cooler responds_with method.
I saw this code in a Rails controller:
respond_to do |format|
format.js {}
end
I've seen this for XML and HTML formats but not for Javascript.
Is this the way you specify a return format if you use for REST, like if you use replace_html or remote_form_for? I know RJS templates return compiled Javascript so I'm thinking maybe this is where this code might kick in.
If you put code inside the hash symbols(format.js {}), is that what gets send back as javascript to the browser?
It is used when an AJAX request is sent from the browser to a controller. The controller can respond with a script (which is generated by ruby statements in the view) which will be executed on the client.
Rails does a little magic on figuring out what 'template' to send out
in controller:
def foo
end
in view: (app/views/controller/) you can have
foo.html.erb (usual, html template)
foo.rjs (javascript template)
rails will send out the right template back to the browser, HTML for regular requets and RSJ for Ajax requests. You might want to put in javascript code like 'page.replace_html' ..etc in your RJS template. This way, you keep the controller clear of view code.
yuo can always just add the format to the url and see what it responds, /something.js would respond using the format.js code, if you want to use it, you can do the following to avoid rendering your entire layout:
format.js { render :layout => false, :text => #models.to_json }
that would respond with a json string
format.js { render :layout => false }
would require a template called [action].js.erb