views:

135

answers:

2

I have made a simple Rails application that allows people to comment on posts. How do I prevent that user from submitting that form over and over again? On reddit.com they only allow newer users to make new posts every ten minutes. How can I do this with my simple blog/commenting system? Any help would be greatly appreciated. Thanks for reading my question. EDIT: I'm trying to accomplish this without a user model.

Here's my current Comments controller:

class CommentsController < ApplicationController
  # before_filter :require_user, :only => [:index, :show, :new, :edit]

  before_filter :post_check

  def record_post_time
    cookies[:last_post_at] = Time.now.to_i
  end

  def last_post_time
    Time.at((cookies[:last_post_at].to_i rescue 0))       
  end

  MIN_POST_TIME = 2.minutes

  def post_check
    return true if  (Time.now - last_post_time) > MIN_POST_TIME

    # handle error
    # flash("Too many posts")
  end

  def index
    @message = Message.find(params[:message_id])
    @comments = @message.comments
  end

  def show
    @message = Message.find(params[:message_id])
    @comment = @message.comments.find(params[:id])
  end

  def new
    @message = Message.find(params[:message_id])
    @comment = @message.comments.build
  end

  def edit
    @message = Message.find(params[:message_id])
    @comment = @message.comments.find(params[:id])
  end

  def create
    @message = Message.find(params[:message_id])
    @comment = @message.comments.build(params[:comment])
    #@comment = Comment.new(params[:comment])
    if @comment.save
      record_post_time#
      flash[:notice] = "Replied to \"#{@message.title}\""
      redirect_to(@message)
      # redirect_to post_comment_url(@post, @comment) # old
    else
      render :action => "new"
    end
  end

  def update
    @message = Message.find(params[:message_id])
    @comment = Comment.find(params[:id])
    if @comment.update_attributes(params[:comment])
      record_post_time
      redirect_to post_comment_url(@message, @comment)
    else
      render :action => "edit"
    end  
  end

  def destroy

  end
end
+1  A: 

In your comment class you could do:

validate :posting_too_often

def posting_too_often
  c = self.post.comments.find_by_user_id(self.user_id, :limit => 1, :order => 'created_at desc')
  if c && c.created_at > 10.minutes.ago
    self.errors.add_to_base("stop posting so many crappy comments!")
  end
end

This might not work, because I didn't test it, but it should send you in the right direction. What you're doing is:

Before a comment is created, load the last comment by that user. If it exists and was posted within the last 10 minutes add an error to the base with an explanation of why it couldn't be saved.

I hope this helps!

jonnii
Thank you for your suggestion. I'm trying to do this without users though. People can anonymously post comments. Could this accomplished with a cookie?
Do it through their IP address, so change it to: self.post.comments.find_by_ip(...).
jonnii
+1  A: 

Try this:

class CommentsController < ApplicationController
before_filter :post_check        
def record_post_time
  cookies[:last_post_at] = Time.now.to_i
end
def last_post_time
  Time.at((cookies[:last_post_at].to_i rescue 0))       
end    
MIN_POST_TIME = 2.minutes    
def post_check
  return true if  (Time.now - last_post_time) > MIN_POST_TIME
  flash[:notice] = "Too many comments makes you a busy cat!"
  @message = Message.find(params[:message_id])
  redirect_to(@message)
  return false
end
def create
  @comment = Comment.new(params[:comment])
  if @comment.save
    record_post_time
  else
  end
end

def update
  @comment = Comment.find(parms[:id])
  if @comment.update_attributes(params[:comment]))
    record_post_time
  else
  end
end    
end
KandadaBoggu
Thank you very very much! I hope you have a wonderful day.
Hi I've tried to get this and I can't seem to get it to work. Obviously the create and update methods are in the controller, but does the rest of the code go in the comment model? Sorry I'm new to ruby and rails. Thanks for your help.
Code goes to CommentsController.
KandadaBoggu
Thanks for your help. I'm getting an error: "no implicit conversion to float from nil" when I try to create a comment. Something to do with the "return true if (Time.now - session[:last_post_at]) > MIN_POST_TIME" line and the minus operator.
Okay, I changed "return true if (Time.now - session[:last_post_at]) > MIN_POST_TIME" to: "return true if (Time.now.to_f - session[:last_post_at].to_f).to_f > MIN_POST_TIME" And now I can comment with your code in my comments controller, but I can comment more often that every two minutes still.
I have updated my code. Take a look
KandadaBoggu
Still lets me post comments as quickly as I want... :( Thank for your help.
I have updated the code to use cookies. See if it works for you.
KandadaBoggu
Okay I'm stumped. I updated my post to include my entire controller code. Thanks KandadaBoggu.
You are supposed to handle error where I have a comment for you to handle "error"
KandadaBoggu
Updated my answer, take a look.
KandadaBoggu
That did it! Thank you for helping me. I'm going to study this code over and over until understand every bit of it. Thank you so much!