I've written a timecard app, and I have a page where people can "punch" in and out. Each person has a b开发者_运维技巧utton which makes an Ajax call back to change their status. A couple of folks have figured out that it's fun to click on a person's button a hundred times in a row, so that the report page for clock in/out times gets really goofy.
I'd like to put a simple Javascript function in the punch page which would limit the "clickability" of the page to something like once every 5 seconds. I've found a couple of other threads here talking about something like that, but I don't know enough about JS to graft those suggestions into how Rails is making the Ajax calls.
Well, there are several possibilities; depending on how much control you'd like.
First you could limit in the JS how often the request can be made. As mentioned earlier. Also, you could make it part of the model logic, not accepting updates within a certain time (also mentioned earlier)
My suggestion would be to rate limit the request per user. There is a nice rack middleware for that: http://datagraph.rubyforge.org/rack-throttle/. If needed you could add customisations, but it's a good start I think.
Couldn't you check the updated_at
field on your record? It won't limit the "mouse" click rate, but it will keep your record from getting updated more than x many times per minute/hour.
For example, in your model, you could have something like:
class TimeRecord < ActiveRecord::Base
validate :throttled_updates, on: :update
private
def throttled_updates
errors.add(:updated_at, "must be more than 5 minutes ago") if self.updated_at < 5.minutes.ago
end
end
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to
Option: disable-with
You can disable the button after an onclick event. The user user would have to reload the page to reclick. Otherwise you'll need some JS to re-enable after a timeout.
# assumes you use jQuery
link_to 'Toggle', toggle_path, :remote => true, :onclick => '
var e = $(this);
if(e.data("busy") == "yes"){
return false;
} else {
e.data("busy", "yes");
setTimeout(function(){
e.data("busy", "no");
}, 5000);
}
'.gsub("\n", '')
Check http://jsfiddle.net/u42gQ/1/
精彩评论