Rails navigates back to error page after long running process - ruby-on-rails

This is very likely to be the wrong way of doing it but I hope someone can point me in the correct direction
The problem is that some_process takes a while to execute if there is an error and if the browser goes to another page in the meanwhile, the page comes back to the edit page when it (some_process) does complete eventually.
(greatly simplified code)
def update
respond_to do |format|
result = some_process
if result
format.html { redirect_to :action => :index }
else
# error
format.html { render :edit }
end
end
end
How do you prevent this? some_process cannot be interrupted. Should it be run in another thread? Is there some method to prevent rendering the page if the user has lost interest and already gone elsewhere?
Should I check something before render :edit to see whether it is still on the same page?
Total Rails newbie question & I've exhausted my Google-fu.

Related

Rails 5, rendering the same view in a consecutive action doesn't refresh the browser

Quick question, I've been trying for the last couple hours to discern what is causing the following behavior but it's just beyond my grasp.
I have this two actions on my 'UsersController':
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
flash[:success] = 'Wellcome, %s! You have successfully
registered.' % [#user.name]
format.html { redirect_to login_path }
format.json { render :show, status: :created, location: #user }
else
flash.now[:error] = 'Hmm... There seems to be some errors.'
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Basically, we render a clean 'new' view, try to register a new user, and if the creation of a user fails, the application should flash a message for the current action (the create action), and render the 'new' view, updating the previous one with the flash information and the errors of the #user variable.
The problem is that, although the server processes the response just fine, the browser does not update the page, never re-renders the page, it keeps the stale 'new' view. I've looked the response with chrome's web tools and it bears the updated view, but for some reason the browser just won't render it.
I think it has something to do with caching, but really I'm out of my element here. If instead of rendering I just redirect to the new action, the flash works fine (removing the .now(), that is), but this way I lose the #user, which I would like to keep with it's full functionality.
Any ideas why this behaves like this, or at least how to solve it?
If you redirect_to the new action, when the user submits, it will still post to the create action and the user_params would still take effect. Simplying rendering :new on the already new page will not perform a fresh request/response. To initiate a fresh request you will have to use redirect_to.

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.

Previous page after updating rails

I am trying to go back to the previous page after updating a link. Here is my link controller:
def update
if #link.update(link_params)
redirect_to :back
else
format.html { render :edit }
format.json { render json: #link.errors, status: :unprocessable_entity }
end
end
Although the link does update, it the page only refreshes, instead of going back to the previous page. Could someone help point out what I am doing wrong? Thanks!
Referrer
Each time you load a controller action in your application, you'll get a request object, which should have the referer attribute:
def update
if #link.update(link_params)
redirect_to request.referer
else
format.html { render :edit }
format.json { render json: #link.errors, status: :unprocessable_entity }
end
end
The problem is that you are sending a request from your browser in a way that it wants to handle the response as if you were going to a new page. redirect_to :back simply tells rails to send the referrer as the redirect URL. If the code read redirect_to 'http://google.com' you would expect the browser to go to google.com, would you not? The correct thing to is to make an asynchronous call using javascript and use javascript to go back in the event of success.
How this happens depends on which JavaScript library you are using. Simply make the call, and in your success function, call window.history.back() and the browser will go back.

Getting a "Expected response to be a <:redirect>, but was <200>" when trying to pass a test

Just to clarify: I'm new to Ruby and Rails.
I've tryed to solve my problem with the sugestions in here, here and here, but they didn't seem to have direct relation with my problem, or I'm too dumb do understand.
I'm trying to test a scenario where I don't update an object and I want my app to redirect. I'm not sure if my controller code is right, I think I'm probably not covering this scenario. Here's my test code:
test "should not update status if nothing has changed" do
sign_in users(:rodrigo)
put :update, id: #status
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:rodrigo).id
end
, and my controller update code:
def update
#status = current_user.statuses.find(params[:id])
#document = #status.document
if params[:status] && params[:status].has_key?(:user_id)
params[:status].delete(:user_id)
end
respond_to do |format|
if #status.update_attributes(params[:status]) &&
#document && #document.update_attributes(params[:status][:document_attributes])
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
I've already tried to verify if #status.changed?, and it really didn't. I'm without options here. If anyone want to help and need more information, I can provide it.
Facepalm for me...
I've mentioned in my question:
I've already tried to verify if #status.changed?, and it really didn't.
It did change when I put something different in one of the model attributes, but I've only asked .changed? after saving my #status model. I'm really sorry about it, I'm yet just figuring out how Ruby on Rais works.
That said, I've came up with a solution to my problem, that was just setting the only one attribute of my model (except the id, of course) with the value from the params[:status] hash. And BEFORE saving it, I ask if #status.changed?. If it doesn't, I redirect_to the unchanged #status, otherwise, I just save it and go through the old code.
Of course that doesn't cover all my scenario, since I also have to check if my #document model has changed, but this is not the scope of this question.

Rails Validation - Redirect not working

I feel somewhat stupid about this one, but:
if #prof.update_attributes(params[:profile])
respond_to do |format|
format.html {redirect_to(#prof, :notice => "Profile successfully created.") }
end
end
...is in the update method of my controller. I have some attributes being validated in the model.
If validation fails, I just want them back on the same form to be scolded by various red text. (ie. everything in the errors array).
I'm getting a 'template missing' error when validation fails - the template for 'update'. I feel like I'm overlooking something extremely simple. Help!
Try this:
respond_to do |format|
if #prof.update_attributes(params[:profile])
format.html { redirect_to(#prof, :notice => "Profile successfully created.") }
else
format.html { render action: 'edit' }
end
end
The cause of the error is due to the fact that Rails, unless told otherwise, will attempt to render a template with the same name as the action, in this case update, which obviously doesn't exist.
What you want to do is tell rails to render the edit action again in the event of an error. Typically, you would do this with the respond_to block, allowing the block to respond differently depending on whether validation passed or failed.
At present, you have your if statement wrapping the block, and no statements telling rails to render differently in the event of an error. To fix this, I would do the following:
respond_to do |format|
if #prof.update_attributes(params[:profile])
# all is well, redirect as you already wrote
else
format.html { render action: 'edit' }
end
end

Resources