Pergunta

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.

Foi útil?

Solução 2

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.

Outras dicas

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

for me it seems like returning false in the callback doesn't stop returning the record, even though it is not saved onto the database, weird.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top