How to make :render => nothing work - ruby-on-rails

I have an jquery AJAX call that loads a window. In the window, there is a form with a submit to allow the users to download an item. I have to make this second form use a regular submit so that I can prompt a download.
My problem is when there is no file to download, it redirects to the page in which this file is located.
I am trying many different styles of getting it to render nothing, but none of them seem to work.
unless params[:controller] == "reports"
unless #jobs.present?
flash.now[:error] = "No work orders for this selection."
render :nothing => true
end
end
Also
respond_to do |format|
format.html { render :nothing => true }
end
Nothing seems to work. Any ideas?

Don't use render: nothing. This will "fail" ajax request.
Instead, use:
render json: nil, status: :ok

Related

My rendering in Rails (possibly) causes a 422 error

I have received reports from users to my website that they get Error 422 when visiting a "result" page using POST. I cannot re-create this error at all so I am wondering if there is anything in my code below that would cause this error in formatting? I expect there could be errors here since I have upgraded a Rails 3.x project to a Rails 4.2.
I would either like to know if there is anything obvious in the code that would create 422 errors or if there is anyway to troubleshoot 422-errors.
Basically, in #show there is a POST method to result. It is creating a result text and lands on a url like /this-post-name/result?r=abc123 . I am rendering #show in /result because it is basically loading the same page again but with a "result box". Having to use /result is a choice I made as a newbie programmer and is not absolutely necessary, I think.
I am quite sure the error lies within the "respond_to" but can't figure that out, or troubleshoot it (i.e. re-create it).
Also, I am not sure if this is important, but I get tons of AuthencityToken errors on this page.
Edit: I managed to recreate this issue by accessing it through my iPhone and post a form, then I disabled cookies and send the form again. That would not be something people would do often but I guess having cookies disabled may cause this?
def show
#avaliable_posts = Post.where(:available => true)
end
def result
if request.get? && params[:r].blank? # Just visiting /result withoutout POST or ?r url
redirect_to category_path(#category)
else
set_round(session[:round_by_number])
# Either the visitor just posted the result or is revisiting through URL
if !params[:r].blank? # Visitor arrived from URL
#result = Result.find_by_scrambled_identifier(params[:r])
params_to_use = #result.params_used
#params_to_use = #result.params_used
else
params_to_use = params
#params_to_use = params_to_use
end
post_instance = #post.get_post_instance(params_to_use)
if post_instance.valid?
#post_result_array = post_instance.calculate_me(params_to_use)
#post_result_text_array = #post_result_array[0]
respond_to do |format|
format.html { render :action => "show" }
format.json { render :json => #post }
end
else # post not valid
#errors = post_instance.errors
respond_to do |format|
format.html { render :action => "show" }
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
format.json { render :json => #post }
end
end
end
end
A 422 means Unprocessable Entity. Within your sample code is only one place with this http status code:
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
Obviously this happens when format is XML and #validator contains an error.
Edit:
With the new information about the exception within the logs and the second linked stackoverflow question it seems to be releated to a known Rails issue
It seems like this issue is related to another issue that I have written another question for. I have an InvalidAuthencityToken issue with my website and the exceptions created through that cause a 422 (and not a 500) error as far as I understand from http://api.rubyonrails.org/v2.3/classes/ActionController/RequestForgeryProtection/ClassMethods.html
I am not 100% sure that this is the same issue but it seems quite likely and therefore I will close this question.

.js.erb file available to all other views?

So, in my rails app I ajaxified the error messages on one of my pages. the process was (so everyone understands) first, in my 'edit' link_to I added :remote => true at the end of it thus having it send an ajax request. I then added the line format.js in my respond_to do |format| block. Then, I made an edit.js.erb file with the following line of code $('#error').html("<%= flash[:error] %>"); which basically finds the error div in the current page and replaces the html in that div with the error flash message. This is cool right? No more annoying page refreshes in the event of an error.
Question is, I want to do this for all my edit and destroy pages, but how without making an edit.js.erb and destroy.js.erb file for each view folder? seems pretty simple, and maybe im just missing an obvious answer because I'm exhausted, but I can't figure it out... so... help?????
EDIT!
this is my edit controller
def edit
user = User.find(session[:id])
#table = Table.find(params[:id])
if user.id != #table.created_by
flash[:error] = "ERROR"
respond_to do |format|
format.js {render :template => 'shared/show_error'}
format.html
end
else
flash[:error] = ""
respond_to do |format|
format.js {render :template => 'table/edit', :formats => :html}
format.html
end
end
end
Problem now is, it works fine for showing the errors but if there are no errors it doesnt action render the edit page... In the server window it shows it did, but it doesnt actually show on the screen... Any ideas?
I would suggest you then make a general JS.erb file, something like:
# app/views/shared/show_errors.js.erb
('#error').html("<%= flash[:error] %>");
And then in your controller action, or from another JS.erb file, just type:
render :template => "shared/show_errors"
And voila!
I actually fixed my own problem by accident... I removed the line {render :template => 'table/edit', :formats => :html} from the else block.

Redirect to after successful ajax form

I've got a form with remote => true.
And right now my controller looks like:
# POST /items
# POST /items.json
def create
#item = #store.items.build(params[:item])
respond_to do |format|
if #item.save
format.html { redirect_to edit_admin_item_path(#item), :flash => {:success => "#{#item.name} was successfully created."} }
format.js { render :js => "window.location.href = ('#{edit_admin_item_path(#item)}');"}
format.json { render json: #item, status: :created, location: #item }
else
format.html { render action: "new" }
format.js { render :partial => 'fail_create.js.erb', :locals => { :ajax_errors => #item.errors.full_messages } }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
Which works but feels very clumsy. It also doesn't allow me to use a flash notice, which is sad time indeed.
Ideally I feel like I should be able to simply use "format.js { redirect_to...} or check against the request headers and redirect_to. Sheesh!
I'm not sure what the best solution is. Any advice would be super awesome, thanks in advance!
-- PS -- I know this has been asked somewhat before but to no avail: How to redirect after a successful AJAX form submission. There seems to many questions similar floating around, but no real solutions.
I think it might be impossible. The response to a Ajax request is processed by XMLHttpRequest. If a 3xx response is returned, XMLHttpRequest will follow the redirect itself, if the URL is of same origin. No matter how you set the headers, the browser cannot be aware of that. So the only way could be changing window.location with some Javascript.
I use a combination of Rails responders to generate my response messages and some content in my <action>.js file.
The content of — say update.js would look something like this:
// Checks if the article slug has changed.
// If it has the entire page should be reloaded at that new location.
<%= reload_if_slug_changed #article, params[:id] %>
// Displays the flash notices
// See ApplicationHelper#js_flash_response
<%= js_flash_response %>
Where the different methods are defined in some helper (in my case my ApplicationHelper). The content of the different methods are as follows:
def js_flash_response
if flash.now[:notice].present?
js = "$('#notice').html('#{flash.now[:notice]}').change();"
elsif flash.now[:alert].present?
js = "$('#alert').html('#{flash.now[:alert]}').change();"
end
end
def reload_if_slug_changed object, expected_value
"window.location.href = '#{url_for [:edit, object]}';" if object.slug != expected_value
end
The content of the flash messages are generated automatically by Rails responders and displayed with the now scope that deletes the from the flash hash, ensuring that if the user reloads (after the flash has been displayed) they will not reappear.
I don't believe that you should ever make a form pointing to a restful create action a remote one, because you would always expect critical redirect, so in my case I only need to redirect if the url slug has changed.
I hope that this helps. It's not a solution, but simply the way that I handled some of the same problems.
Best regards.
Under your scenario, here's how I would inject javascript into the page from a controller action. After you've completed the logic section of your action insert something like this:
render :update do |page|
page << "javascript_here"
end
This should allow you to insert you window.location or create a javascript flash method and call it when your create method executes correctly.
If you're looking to DRY up your controller actions, I would recommend looking into this Railscast about make_resourceful. Make_resourceful automagically performs each core activity for each action. It also allows you to tap into the hooks that they've created such as before :create, after :create, response_for :create, and after :create_fails. By using this gem, you can run code based on the success or failure of your methods and have finer grained control over them.
In addition to this, you should be able to initialize a create.js.erb and create_fails.js.erb in your view file, include a format.js without anything passed to it in your controller, and Rails will automagically run that file that contains javascript depending on if the controller action executed successfully.

Rails: rendering the js.erb template using the controller

I have a rails app trying to incorporate some AJAX where clicking new opens a modal window and a form. I want to be able to display the validation errors if it fails so in my create action, i thought about re-rendering the new.js.erb file. Is this the right approach?
def create
#place = Place.new(params[:place])
if #place.save
redirect_to places_path, :notice => "Successfully created place"
else
render "new.js.erb"
end
end
The result I get is escaped js text in my browser like:
$("#new_grouping").html("<div class=\"modal-header\">\n <a class=\"close\" data- dismiss=\"modal\">×<\/a>\n <h3>Create a new menu section<\/h3>\n<\/div>\n<form accept-charset=\"UTF-8\" action=\"/places/1-mama-s-pizza/groupings\" class=\"simple_form new_grouping\" id=\"new_grouping\" method=\"post\" novalidate=\"novalidate\">
I've tried putting various options into the render block but no luck. Any tips?
The best practice would be to support both, AJAX and Non-AJAX calls, in case the user has javascript turned off for any reason.
def create
#place = Place.new(params[:place])
respond_to do |format|
if #place.save
format.html { redirect_to places_path, :notice => "Successfully created place" }
format.js # renders create.js.erb, which could be used to redirect via javascript
else
format.html { render :action => 'new' }
format.js { render :action => 'new' }
end
end
end
The render :action => 'new' actually renders the template of the controller action new which results to new.html.erb respectively to new.js.erb depending if it's a non-AJAX or an AJAX call.
In new.js.erb goes your ERB/javascript code:
$("#new_grouping").html("<%= escape_javascript(...) %>">
As i know, rendering partial in controller is a bad idea, because then response can be without content-type and some browsers can't understand this. if it is some file attached to action you should write
render :action => "create"
or if you need just render a singe partial then in your action file write
<%= render :partial => "path/to/partial" %>
as i said, then you won't have problems with content-type in response

Ruby on Rails: insert javascript into a page

So.. I have this in the action called when someone clicks the archive button
respond_to do |format|
format.js do
render :update do |page|
page << "alert('You have reached your archive object limit. You have #{remaining} remaining archived objects.');"
end
end
end
But instead of alerting, it just gets rid of the entire page and shows a JavaScript try / catch with that alert message. How do I just do an alert without rendering anything?
Add
:layout => false
in render
Needed to change form_for to form_remote_for to enable ajax
If it's an AJAX call, you may do something like this in your action:
render :text => "<script type='text/javascript'>alert('bla');</script>"

Resources