Rails 406 for .js.erb - ruby-on-rails

I know this has been asked a lot, but I've looked at all the simple solutions and they're not working.
Firstly, .js.erb responses are working for all my other controllers...I generated a new controller and it won't respond to .js.erb
def report
#report = Report.all
respond_to do |format|
format.js do
render :content_type => 'text/javascript'
end
end
end
This route does work and will render html. I have no idea why .js.erb would work for my other controllers and not for a new one. I've done plenty of fiddling before making this new one...so debugging will be hard for me.

Remove the entire respond_to block. Rails will pick the correct view:
def report
#report = Report.all
end

If you are getting a 406
You need to explicitly disable erb's layout template checking.
render layout: false
You can keep respond_to and format if you need them for supporting other formats.
(NOTE: dynamic js for Content Security Policy purposes?)

Related

how do you get paperclip url to json in rails?

I'm aware of the other questions pertaining to this subject, but none seem to help. I want the paperclip image url passed to json so I can render it in a reactjs component. I obviously cannot use Rails' image_tag helper.
I've defined this method in my items model
def image_url
image.url(:thumb)
end
And this in my controller
def index
#items = Item.all
render :json => #items.to_json(:methods => [:image_url])
end
But literally all that does is replace the rendered page with json. How should I go about this? It doesn't make sense to create a migration and model validation specifically for the image url.
Just needed to format the html.
respond_to do |format|
format.html
format.json { render :json => #items.to_json(:methods => [:image_url]) }
end
Still doesn't solve the part where I'm trying to use that method in a reactjs component, but that's another issue.

Has controller action specific layouts changed in Rails 4.1

I've just upgraded to Rails 4.1.
I previously had the following in a controller action, which worked perfectly.
respond_to do |format|
format.html { render html: #user, layout: "fullscreen" }
end
This is not working in Rails 4.1, and the page simply renders the object #<User:0x007fb087429a70>
Edit the controller as follows fixes this error.
respond_to do |format|
format.html
end
What is the correct way to set the layout in Rails 4.1. I'm having trouble finding this in the docs.
html option was added in render method in Rails version 4.1. See the issue listed here
When you tried
def action_name
## ...
respond_to do |format|
format.html { render html: #user, layout: "fullscreen" }
end
end
in a Rails version prior to v4.1, what really happened was render ignored the html option, picked up the layout and went ahead to look for a view named action_name.html.***(where *** refers to template handler like erb, haml, etc). It found the view and rendered it. If the view didn't exist then you would have received a Missing template error
And when you use the same code in Rails 4.1, as the html option is allowed in render method it will definitely be processed. Now, first you need to understand what the html option actually does:
You can send a HTML string back to the browser by using the :html
option to render:
render html: "<strong>Not Found</strong>".html_safe
You use this when you don't want to write an html file for your action and wish to simply render a HTML string.
Which is the reason when this particular action is called you now see an html page with object #<User:0x007fb087429a70> because you passed the value to html option as #user.
Edit the controller as follows fixes this error.
respond_to do |format|
format.html
end
Firstly, it was not an error. You misinterpreted what html option does. I am pretty sure you do have a view corresponding to your action which is what you expected to be rendered. The above code does that for you.
I suppose you simply wish to specify layout for your view. All you need to do is:
respond_to do |format|
format.html { render layout: "fullscreen" }
end

Rails AJAX - don't redirect or render

Using rails and .js.erb to make an AJAX request (and append values to a div), how do you prevent rendering a new layout? In other words, stay on the same page without going anywhere and just append the fresh data from the server in a div. No reloading the same page, no redirecting.
At the moment my controller looks like this
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
respond_to do |format|
format.js
format.html
end
end
and my form like zisss:
<%= form_tag update_shipping_order_path(#order), method: :put, remote: true do %>
<%= select_tag 'shipping_options', #options_for_select, onchange: 'this.form.submit()' %>
<% end %>
and my routes look like a so:
resources :orders do
member do
put :update_shipping
end
end
But I get a 'Template is Missing' error
Please help!!
You need to add a update_shipping.js.erb file under app/views/your_controller/ directory. Note the name of the javascript file should be same as the action. Since you have a remote:true in your form so rails will try to render a javascript template in your case update_shipping.js.erb.
Now in your update_shipping.js.erb file write some basic javascript to update the page elements like
#update_shipping.js.erb
$('.some-div').html(<%=j #model.some_value' %>)
Try this:-
respond_to do |format|
format.js { render :nothing => true }
format.html
end
If you don't want to render a layout, you can use !request.xhr? like so:
respond_to do |format|
format.html { layout: !request.xhr? }
format.js
end
If you're looking to get your ajax-powered JS to fire, you just need to call your .js.erb file the same as your view:
#app/views/controller/update_shipping.js.erb
alert("This JS is returned & fired after the Ajax request");
You'll be best doing this in your routes.rb too:
resources :orders do
put :update_shipping
end
A little late, I came across this searching for the same issue. It must of slipped out of my mind at some point while working with action cable, but what is needed is a http response code of no_content. Http response codes tell the browser how to act when a request is returned. Here is a link to a list of them, and their symbols in rails. More on 204 no content
Here is how it would look:
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
head :no_content #or head 204
end
edit: what solved the solution for me was a link provided by William Denniss in this stack overflow question

What does respond_to do?

#some instance variables
respond_to do |format|
format.html
format.xml {...}
format.json {...}
end
Does respond_to simply send all instance variables to the next webpage or it does something more?
I'm wondering how much data would be sent by respond_to. For example, if I have many instance variables #one #two #three etc. Are they all sent by respond_to? Any other data would be bundled and sent as well? ?
You instance variables will not be sent anywhere without your direction.
You probably have a .html.erb template that renders the instance variables when an HTML request is received (format.html).
For the xml and json responses, you need to tell Rails what to do. For instance, you could supply a template .xml.builder.
Rails can also render certain structures (arrays etc.) for you automatically, simply by calling render json: #one
Rails goes through the registered formats and tries to find a compatible format, otherwise, it will raise an error.
Example:
def index
#stories = Story.all
end
index action does not have a respond_to block. If a client asks to get the page in TEXT format, it will lead to the following exception:
ActionView::MissingTemplate (Missing template blogs/index ... with { ... :formats=>[:text], ...})
We can easily fix this by adding a respond_to block:
def index
#stories = Story.all
respond_to do |format|
format.html
format.js
end
end
After the change, the client will get 406 error when the format is not supported. Also, your index action will respond to two new formats: js and HTML.
This article explains all the ways you can use respond_to blocks.

How to redirect after a successful AJAX form submission (Rails 3.2)

Suppose you have an edit form with :remote => true. Your controller method looks like
def update
#article = Article.find(params[:id])
respond_to do |format|
if #article.update_attributes(params[:article])
format.html { redirect_to #article}
format.js { render :js => "window.location.replace('#{article_path(#article)}');"}
else
format.html { render :action => "edit" }
# Render update.js.erb which replaces the body of the form
format.js {}
end
end
end
What's the best way to do the redirect on successful article update in Rails 3.2.1? The raw JS solution seems a little sleazy, but I do like the fact that it's obvious that it's performing the same function as the format.html version.
I would prefer a solution that does not use RJS (if that even works in Rails 3.2?)
How about adding the below line of code on the view file itself
#some_file.js.erb
`window.location = redirect_path
As you mentioned in the question you do not prefer RJS, but I think it's better to follow this pattern better than writing the js code in the controller.
Does your ajax interact with a model (.php,.asp?). My preferred method in this instance is to create a success/fail criteria within the model after submission and redirect directly from there. Not sure if that makes sense in this application though?

Resources