我前一段时间发布了一个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
答案 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中创建它们时。