无法理解一些代码(Ruby on Rails)

时间:2010-05-14 21:38:56

标签: ruby-on-rails ruby model controller

我前一段时间发布了一个question,询问我如何限制从rails应用程序提交表单的速率。我得到了一位非常耐心的用户的帮助,他们的解决方案很有效。代码是我的评论控制器,现在我发现自己想要将此功能添加到另一个控制器,我的消息控制器。我立即尝试重用评论控制器中的工作代码,但我无法让它工作。而不是要求工作代码,有人可以帮我理解我的工作评论控制器代码吗?

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[:warning] = "You are trying to reply too fast."
    @message = Message.find(params[:message_id])
    redirect_to(@message)
    return false
  end

  #...

  def create
    @message = Message.find(params[:message_id])
    @comment = @message.comments.build(params[:comment])
    if @comment.save
      record_post_time
      flash[:notice] = "Replied to \"#{@message.title}\""
      redirect_to(@message)
    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
#...
end

My Messages控制器几乎是一个标准的rails生成控制器,带有一些前置过滤器和相关的私有方法,用于干扰代码和重定向不存在的页面。

我会解释我理解的代码有多少。创建注释时,将使用last_post_time值创建cookie。如果他们尝试发布另一条评论,则检查cookie是否在最后两分钟内完成。如果是闪光警告则显示,并且不记录任何评论。我真的不明白的是post_check方法是如何工作的,以及我如何使它适应我更简单的帖子控制器。我想我可以重用消息控制器中的所有代码,但行除外:

@message = Message.find(params[:message_id])
# (don't need the redirect code)
post_check方法中的

。我真的很想了解这一点。有人可以解释为什么这不起作用?我非常感谢你阅读我冗长的问题。

创建和更新Messages控制器的操作:

def create
  @message = Message.new(params[:message])
  respond_to do |format|
    if @message.save
      record_post_time
      flash[:notice] = "Created \"#{@message.title}\""
      format.html { redirect_to(messages_url) }
    else
      format.html { render :action => "new" }
    end
  end
end

def update
  respond_to do |format|
    if @post.update_attributes(params[:post])
      record_post_time
      flash[:notice] = 'Post was successfully updated.'
      format.html { redirect_to(@post) }
    else
      format.html { render :action => "edit" }
    end
  end
end

2 个答案:

答案 0 :(得分:1)

我将尝试使用MessageController类,请阅读post_check类中的注释。哦,我也把它作为私有方法,通常最好的做法是将非可访问的操作作为私有方法。

class MessagesController < ApplicationController
  #...

  before_filter :post_check

  MIN_POST_TIME = 2.minutes

  def create
    @message = Message.new(params[:message])
    respond_to do |format|
      if @message.save
        record_post_time
        flash[:notice] = "Created \"#{@message.title}\""
        format.html { redirect_to(messages_url) }
      else
        format.html { render :action => "new" }
      end
    end
  end

  def update
    respond_to do |format|
      if @post.update_attributes(params[:post])
        record_post_time
        flash[:notice] = 'Post was successfully updated.'
        format.html { redirect_to(@post) }
      else
        format.html { render :action => "edit" }
      end
    end
  end

  private

  def record_post_time
    # Use different cookie value than comments
    cookies[:mesg_last_post_at] = Time.now.to_i
  end

  def last_post_time
    # Use different cookie value than comments
    Time.at((cookies[:mesg_last_post_at].to_i rescue 0))       
  end

  def post_check
    return true if  (Time.now - last_post_time) > MIN_POST_TIME
    flash[:warning] = "You are trying to reply too fast."

    # What we want to do here is to redirect back to the page 
    # where you are before trying to create a new message or
    # update an existing message.
    #
    # Dont use this:
    # @message = Message.find(params[:id])
    # redirect_to(@message)
    #
    # Use redirect_to :back so that you will be redirected
    # to the previous page before you invoke the create or update
    # action.  Most likely you will be at the new action or edit
    # action.
    redirect_to :back

    return false
  end

end

希望它有助于澄清您对过滤方法之前post_check的理解。

答案 1 :(得分:1)

嗯,只应对create方法执行post_check。否则new / edit / show方法也会调用post_check并重定向。这会导致无限循环。

before_filter :post_check, :only => [:create]

顺便说一句,我认为你应该在模型中加入类似的代码和过滤器:Fat Model - Skinny Controller。因此,泛洪预防将适用于在其他控制器等中创建的注释,而不仅仅是当用户在您的CommentsController中创建它们时。