2010-05-14 41 views
0

我之前發佈了一個question,詢問如何限制表單可以從Rails應用程序提交的速率。我得到了一位非常耐心的用戶的幫助,他們的解決方案效果很好代碼是用於我的評論控制器,現在我發現自己希望將此功能添加到另一個控制器,即我的Messages控制器。我立即嘗試重新使用來自評論控制器的工作代碼,但我無法實現它的工作。而不是要求工作代碼,有人可以幫我理解我的工作評論控制器代碼嗎?無法理解一些代碼(Ruby on 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 

留言板控制器幾乎是一個標準的鐵軌產生的控制器之前,過濾器和相關的專用方法對一些乾涸的代碼和不存在的頁面重定向。

我將解釋我理解的代碼數量。創建評論時,會使用last_post_time值創建cookie。如果他們嘗試發表另一條評論,則會在最後兩分鐘內檢查最後一條cookie。如果顯示閃光警告並且未記錄評論。我真的不明白的是post_check方法是如何工作的,以及如何使它適應我簡單的帖子控制器。我想我可以重新使用消息控制器中的所有代碼,但該行除外:

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

in the post_check method。我很想理解這一點。有人可以解釋爲什麼這不起作用嗎?我非常感謝你閱讀我冗長的問題。

創建和更新消息控制器的動作:

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

'創建操作/方法'中的'record_post_time'意味着什麼? – jdl 2010-05-14 21:56:29

+0

我得到一個「未定義的局部變量或方法'record_post_time'」錯誤。對不起,不太清楚。我會編輯我的問題。 – BasicObject 2010-05-14 22:10:53

+0

糟糕,我的代碼中存在拼寫錯誤。沒有record_post_time錯誤了。我只是不知道要替換「@message = Message.find(params [:message_id]) 」,並且想要了解代碼。對於這種困惑感到抱歉。我相應地編輯了我的問題。 現在我只是在嘗試發佈帖子時出現錯誤:「無法找到沒有ID的消息」。它說這個問題出現在post_check方法中。 – BasicObject 2010-05-14 22:18:56

回答

1

Hm,post_check只能執行create方法。否則new/edit/show方法也會調用post_check並重定向。這會導致無限循環。順便說一句,我認爲你應該把代碼和過濾器這樣的模型:脂肪模型 - 瘦身控制器。所以防洪預防將適用於在其他控制器等中創建的註釋,而不僅僅是當用戶在您的CommentsController中創建註釋時。

+0

我認爲這是需要的!謝謝! – BasicObject 2010-05-15 16:56:01

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中的理解。

+0

謝謝你的幫助。您評論的解釋非常有用。我嘗試了你的代碼,並在Firefox中的錯誤是「這個問題有時可能是由禁用或拒絕接受cookies造成的。」刪除cookie後,我再次嘗試,結果相同。所以我認爲這是一個無限的重定向循環。有任何想法嗎? – BasicObject 2010-05-15 12:32:28

+0

通過結合你的答案和Ragmaanir的,我已經達成了一個解決方案。非常感謝你! – BasicObject 2010-05-15 16:57:29