Persisting flash when a form is submitted multiple times - ruby-on-rails

Background: I have essentially a multiple choice quiz. When a user submits a form, update scores their answer, chooses a new question, puts a message in the flash, and redirects back to the show action. show displays the message and the new question.
The immediate problem is that if they submit the form twice, update gets called twice. The first time scores their answer for the question they were given. The second time scores their answer for the question that was just now selected, which they haven't seen yet. So then they get redirected with a message saying something like "wrong! The answer is Spain, not Italy" When they had been choosing between Hydrogen and Helium.
So my first solution to this is to include a question_id field in the submitted form. If the submitted id isn't the id of the question that was asked, just ignore this request. This works for keeping track, but the message that was stored in the flash is lost.
So I've tried adding flash.keep if the ids don't match. My thinking is that one update will set the flash, and then the next request received will be the second update. But the flash is still getting lost. It seems that the second update doesn't start with a flash at all, which confuses me.
So my questions are: is there a better way to handle this problem? And if not, why is the flash disappearing?
update looks something like this (some lines omitted):
def update
game = current_user.credence_game
question = game.current_question
if params[:question_id].to_i == question.id
given_answer = params[:answer_index].to_i
credence = params[:credence].to_i
correct, score = question.score_answer(given_answer, credence)
game.score += score
game.new_question
game.save
flash[:correct] = correct
flash[:score] = score
flash[:message] = question.answer_message(given_answer)
else
flash.keep
end
redirect_to action: 'show'
end
If I add a p flash line just before redirect_to, the server spits out this:
#<ActionDispatch::Flash::FlashHash:0x007f2a8431b4a0 #used=#<Set: {}>, #closed=false, #flashes={:correct=>false, :score=>-32, :message=>"Incorrect. The right answer is White River (Arkansas) (1102km) versus Yellowstone River (1080km)."}, #now=nil>
Started PUT "/credence" for 127.0.0.1 at 2014-08-17 15:20:16 +0100
Processing by CredenceController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EiqXDoFy77nmdKOE4YkHOeEFg4DvB5zdgFi98ynNCx0=", "question_id"=>"52", "credence"=>"60", "answer_index"=>"1", "commit"=>"60%"}
<Model stuff>
Redirected to http://localhost:3000/credence
Completed 302 Found in 667ms
#<ActionDispatch::Flash::FlashHash:0x000000059864f8 #used=#<Set: {}>, #closed=false, #flashes={}, #now=nil>
Started PUT "/credence" for 127.0.0.1 at 2014-08-17 15:20:18 +0100
Processing by CredenceController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EiqXDoFy77nmdKOE4YkHOeEFg4DvB5zdgFi98ynNCx0=", "question_id"=>"52", "credence"=>"70", "answer_index"=>"1", "commit"=>"70%"}
<Model stuff, just loading the game and the question>
Redirected to http://localhost:3000/credence
Completed 302 Found in 421ms
Started GET "/credence" for 127.0.0.1 at 2014-08-17 15:20:19 +0100
Processing by CredenceController#show as HTML
<Model stuff>
Rendered layouts/_messages.html.erb (400.4ms)
Completed 200 OK in 963ms (Views: 776.4ms | ActiveRecord: 27.7ms)
<GET requests for CSS, images, etc.>
So it does seem like the first request after the flash is set, is the one where I'm calling flash.keep, but it still doesn't have the flash.
Edit: I'm realising the problem is likely that I'm using CookieStore. The first request doesn't get a chance to set cookies before the second request is sent. Using the session instead of flash would have the same issue.
A simple solution here, that I don't much like, would be to simply disable the forms with javascript onsubmit. A more complicated one would be: when the question ids don't match, look up the answer that the user gave for the submitted question id, and set the flash appropriately without changing the score.
Any alternatives?

Related

Trigger turbo_stream and html response within show action rails 7

I have a simple messaging app. Users can set up a public profile with their description and people can send them inquiries. Those inquiries are then collected in a table in the user dashboard.
When a user is clicking on a row, a turbo frame opens up and shows the inquiry.
I would like to implement, that the inquiry is automatically set to #inquriy.seen = true whenever a row is clicked / the inquiry show action is called. Within the table is a blue dot in my ui that indicates, that the message/inquiry is not yet read.
currently i have this code within the show action:
respond_to do |format|
if #inquiry.update!(seen: true)
format.html
format.turbo_stream { flash.now[:notice] = "Anfrage angesehen." }
end
end
The problem is, that it does not work. The inquiry is successfully updated, but the table does not change. Instead I am getting a Completed 406 Not Acceptable response and an ActionController::UnknownFormat error.
I already tried to accept turbo_streams in the mime_type.rb but there are other features in my app that are using turbo streams that work just fine (btw also in the update action of the inquiries (you can manually set them to read)).
How can I trigger the turbo_stream when clicking calling the show action to update the table in the index action?
Thanks!

Rails 200 status codes change to 302 if a request takes too long?

I have a rails app that fires off some code to assemble a large report on all a users data. This takes ages and needs to come off an external API (salesforce).
I have code that works on many records:
Grabbing the data
Formatting it correctly
Passing it to the view and rendering as a pdf before refreshing the page with ajax.
Most requests end like this:
Rendered record_requests/_get_digest.html.erb (2974.9ms)
Rendered record_requests/get_digest.js.erb (2983.4ms)
Completed 200 OK in 5957ms (Views: 2770.9ms | ActiveRecord: 222.1ms)
Which is great!
But some of the largest records can take 6+ minutes to grab and process - at which point something different occurs:
```
Redirected to https://[base_URL]/record_requests/5
Completed 302 Found in 288345ms (ActiveRecord: 2.4ms)
This is also a disaster because the redirect seems to kick off the initial request again so i get stuck in a loop...
These two requests use exactly the same code!! Why is one getting rendered and the other getting redirected? Is there a built-in rails timeouts.
Soo confused, can anyone shed any light on this?
This all works via the very excellent Restforce gem,the full gemfile is listed here.
The controller looks like this:
# GET /record_requests/1
def show
respond_to do |format|
format.html {}
# format.json { head :ok }
format.js
end
end
# GET /record_requests/1/get_record
def get_digest
#client = #record_request.client_digest
#request_digest = #record_request.build_request_digest
respond_to do |format|
format.js
end
end
If its pretty much exactly 600s it will be a timeout.
I would guess, possible sources are:
salesforce itself, althought I can't see a mention of a specific timeout for requests
the client library you use to call the api, and how you handle the reponse
the webserver you host on
Of the three, as it's rails showing the redirect - I would guess it's the second one, but without the details of the code and library you use, it's hard to say - it depends on how you handle errors in that method.

Figuring out which element triggered request

I am currently working on a large project developed by 5 people.
The problem is that every time I load a particular page, I get a stray POST request along with the GET request for the page. The page contains no forms though a fair amount a jquery has been used.
Started POST "/my_profile" for 127.0.0.1 at 2012-03-06 21:34:23 +0530
ActionController::RoutingError (No route matches "/my_profile"):
Is there a way to find out which element or script triggered this POST request other than going through the entire code which is divided into 20 partials and 2 javascripts ?
If you're using Firefox, check out the Firebug plugin. The net panel will allow you to easily track down any POST / GET requests for a given page load.
You might try [binding_of_caller][1], caller or possibly [set_trace_func][2].
Dzone Snippets offers a robust way of using caller:
def caller_method_name
parse_caller(caller(2).first).last
end
def parse_caller(at)
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
Or you could do caller.inspect and just look at the raw output.
Binding_of_caller is a bit more involved and may be overkill for what you want but check it out if caller is not what you need. Same with set_trace_func.

rails 3, am I not using redirect_to correctly?

This should be the easiest thing in the world, but a POST redirect is not working.
A remote system normally POSTs data to one of my methods "mainhandler'
In one situation, though, it POSTs data to a different handler "noaudio" which is SUPPOSED to simply erase a session variable then "pass the POST" on to the normal handler ("mainhandler")
My route:
match '/mainhandler' =>"widgets#mainhandler"
My code:
def noaudio
puts "**** NOAUDIO"
session[:audiofile] = ""
redirect_to "/mainhandler"
end
def mainhandler
puts "**** NEVER GETS HERE FROM NOAUDIO ??"
end
what I see in the log (below) it LOOKS like the redirect happens but the handler "mainhandler" is never executed... I see the "puts" in the noaudio handler and I see what looks like a good redirect... but mainhandler never gets executed.
**** NOAUDIO
Started POST "/noaudio" for 1.2.3.4 at 2011-03-07 09:39:22 -0800
Processing by WidgetsController#noaudio as HTML
Parameters: blah blah blah
Redirected to http://mydomain.com/mainhandler
Completed 302 Found in 1ms
Am I using redirect_to incorrectly? or does it not work for a POST? (Although I would presumably still see at least a GET)
Redirects do not work for POSTs indeed.
You may want to take a look at that for some more info :
redirect_to using POST in rails
If you really must have this middleman and want to POST on the data to a new URL, you could use Ruby's Net::HTTP class and pass on the data.
I think you should think twice though and ask yourself if this is really what you want to do.

Rails duplicating requests

After correcting some other bugs on the application I found out that one page is being rendered twice on every request.
Rails completes the request normally and after a few, simply starts another request.
At first thought it was a Firebug problem or YSlow doing other requests, but after more tests the duplication remained and I discarded those reasons.
I tried even debugging rails step by step in the request, it goes normally and after completing the first request, I get stopped in the same debugger start line again, this time for the second request.
Printed some lines and things to see clearly on log and it clearly makes 2 requests.
I also found a few wierd requests that I cannot explain also
This bit of log shows the end of the first request and right after that one, there is a wierd index request without layout and then the same request starts again to be processed:
Processing ArtistImagesController#index (for 192.168.0.11 at 2010-07-08 15:10:56) [GET]
Parameters: {"action"=>"index", "locale"=>"pt", "controller"=>"artist_images", "artist_id"=>"2-tom-welling"}
#^ Start of first request
#v end of first request
Completed in 812ms (View: 429, DB: 41) | 200 OK [http://192.168.0.20/artistas/2-tom-welling/imagens]
SQL (0.2ms) SET NAMES 'utf8'
SQL (0.2ms) SET SQL_AUTO_IS_NULL=0
# v wierd request
Processing ApplicationController#index (for 192.168.0.11 at 2010-07-08 15:10:59) [GET]
Rendering rescues/layout (not_found)
-----------------------------------------------------> html
SQL (0.2ms) SET NAMES 'utf8'
SQL (0.2ms) SET SQL_AUTO_IS_NULL=0
# v start of second request
Processing ArtistImagesController#index (for 192.168.0.11 at 2010-07-08 15:11:00) [GET]
Parameters: {"action"=>"index", "locale"=>"pt", "controller"=>"artist_images", "artist_id"=>"2-tom-welling"}
Remembering that all those requests were generated by entering the page only once :/
Searched the code for possible loops or any kind of errors but haven't found any.
Please help is very appretiated
Search your page source for empty image src attributes. For such images the browser requests the site root, which seems to be the case.
I think your page is submitting two times. can i view your page.

Resources