views:

46

answers:

2

I have a before_create filter that checks if people are posting too many comments.

If they are I want to flag their account.

class Comment < ActiveRecord::Base
  before_create :check_rate_limit

  def check_rate_limit
    comments_in_last_minute = self.user.comments.count(:conditions => ["comments.created_at > ?", 1.minute.ago])
    if comments_in_last_minute > 2
      user.update_attribute :status, "suspended"
      return false
    end
    true
  end
end

The before filter returns false to stop the comment from being created. The problem is that this triggers a ROLLBACK which also undoes the changes I made to the user model.

What's the correct pattern to accomplish this? Specifically: running a check each time an object is created and being able to edit another model if the check fails.

+2  A: 

I think the best approach to rate limiting is queueing the requests and reading them at the maximal allowable rate.

The trigger to flag overuse the simply becomes a set number of requests in the queue.

It also has the advantage of not immediately impacting on your database behind as it allows to move the bottleneck before the database in a better controllable queueing system. This allows hte site to remain responsive even under "attack".

These queues can be as simple as a hashmap with a linked list. But better use some threadsafe fifo if avilable

Peter Tillemans
Hmm...that seems doable although quite a bit of extra work to setup a queue. I assume (in the rails world) this would be delayed_job or resque possibly? delayed_job still has the database overhead of creating new jobs so not sure it would solve the attack problem, but resque does it in memory. A queue like resque may be the most robust solution, but I feel like there is probably a simpler way I'm missing. I'm not too concerned about preventing all out attacks at this point - just the occasional overzealous user. Thanks for the answer though - upvoted.
Brian Armstrong
A: 

This isn't an ideal answer but for now I ended up just returning true even when the account was suspended. This way one more went through, but future ones did not.

Brian Armstrong