Since data coming back from the client can never be fully trusted, the server must somehow know what the timestamp of the originally generated form was. This could be done by saving variables in the session or database, but this is problematic. Instead, the server can place a timestamp in the form, either encrypted, or signed, to ensure the client has not altered it. The server can then reject the submission as necessary. On the client, separate logic can handle the UI portion, giving the user feedback on the time limit, but ultimately this only loosely coupled to the server handling.
Details:
The server should generate two form fields: one with the system timestamp time = Time.now.to_i
to track when the form was generated, and another with a signature Digest::MD5.hexdigest(time.to_s.concat('Some-secret-string-1234'))
(note using the same time value here for the timestamp form field and signature form field). This validates that the form is submitted with a server-generated timestamp that has not been altered by the client.
You might also send another form field with the time limit.
On the client, read the timestamp, use setTimeout and the time limit to generate a countdown or whatever you want to do on the front end.
When the form is submitted, authenticate the timestamp submitted with the form by regenerating the MD5 signature using the same method as before. Make sure it matches the signature submitted by the form. Then, add the timestamp to the timeout, and make sure it's later than the current server time. If so, you have a valid submission, within your time constraint.
You probably will need to give a little more leeway on the timeout at the server than on the client, maybe a few seconds, to account for network delays, otherwise the user might see one second remaining, click submit, and then by the time the server request is received, it will seem like the timer has expired.
Be sure to add require 'digest/md5'
to get access to MD5.
Using MD5 signatures like this is a great way to verify that a client has not altered key parameters in a form in a stateless manner, whatever you would like them to be. A good addition to your bag of tricks.
Good luck!