2010-02-25 101 views
4

這發生在我身上好幾次了,我還沒有找到一個可接受的解決方案。在Ruby on Rails中運行另一個控制器操作

我在一個網站的主頁上有一個窗體,它指向另一個控制器,它實際上處理數據。當表單提交成功後,另一個控制器會發送回到主頁,並帶有一個不錯的flash [:notice]消息,這就是結束了。

當出現驗證問題時,它就成了問題。我想要做的是顯示帶有驗證錯誤的表單。通常提到的天真的解決方案是您可以渲染另一個模板,但顯示主頁不僅僅是渲染模板,它還有很多功能。渲染該模板的唯一方法是在此其他控制器操作中複製和粘貼功能,或者可能將所有功能從控制器中分離出來,這不是很好,或者

有更好的解決方案嗎?

更新:我明白有人說控制器操作應該更小,並調用另一種方法,但在實踐中,我看不到如何實現它。我要從我做的一個網站上發佈一個真實的例子。

有兩種模型和控制器:帖子和評論。一個職位有很多原因。一個後顯示是這樣的:

def index 
    set_posts # sets @posts 
end 

def show 
    @post = Post.find_by_slug(params[:id]) 
    @comment = Comment.new 
    if not @post 
    flash[:error] = "'#{params[:id]}' does't exist" 
    set_posts 
    render :action => :index, :status => :not_found 
    end 
end 

private 
def set_posts 
    @posts = Posts.get_all_public_posts 
end 

的意見控制器只有創建操作:

def create 
    @comment = Comment.new(params[:comment]) 
    @comment.post = Post.find_by_slug params['post_id'] 

    if not @comment.post 
    # Now what? 
    # We should here call PostsController.set_posts and render views/posts/index 
    end 

    if @reason.save 
    flash[:notice] = 'Thank you for your message.' 
    redirect_to(@reason.item) 
    else 
    # Now what? 
    # We should here call PostsController.show without overriding the @comment 
    end 
end 

的 「?現在是什麼」部分是我沒有很好的解決方案。

回答

0

這是從正常的香草欄形式不同嗎?

if(valid) 
flash = ... 
redirect_to :home 
else 
rerender form with error messages & submitted values 
end 
+0

不同之處在於,渲染已包含在主頁操作中的表單需要很多控制器邏輯。 – EmFi 2010-02-25 05:26:04

+0

重新渲染表格丟失了家庭控制器操作中的大約25行代碼。 – Pablo 2010-02-25 05:26:53

1

多少時形式呈現並請求重定向到默認的行動之間的更改主頁的休息嗎?

如果答案不是很多,那麼您應該考慮使用remote_form_for,並且只更新成功時的通知區域或更新失敗時驗證錯誤的表單。

如果這不符合您的要求,可以將主頁操作中的所有重複邏輯移動到ApplicationController類中定義的方法,並將其作爲主頁操作的before_filter的一部分進行調用,你的形式。 N.B:以這種方式做事需要您設置實例變量,在過濾器中設置的局部變量不會持續到動作。

+0

這可能是一個可能的解決方案。謝謝。 – Pablo 2010-02-25 05:27:33

+0

@J。巴勃羅費爾南德斯:我編輯了我的解決方案,以包含另一種方式。 – EmFi 2010-02-25 05:29:38

1

我以前遇到過這個問題。我來自CakePHP,驗證錯誤存儲在會話中,並在請求之間持續存在。 Rails在默認情況下不會採用這種方式,這就讓您決定如何處理錯誤。

正如你明顯也讀過的那樣,將錯誤放入會話並進行重定向通常不會在Rails世界中建議。正如你所說,Rails的方式似乎只是在不做重定向的情況下渲染另一個動作。當我第一次嘗試時,我注意到我被迫重複了很多代碼,以便設置第二個動作來呈現第一個動作的視圖。

與任何類型的代碼重複一樣,解決方案是將重複的代碼移動到單獨的方法中,然後從兩個操作中調用該方法。乾淨的方法是使用before_filter來運行這兩個操作的代碼。

+0

當你在控制器間進行交互時,如何將其移動到單獨的方法,就像我現在更新的示例中那樣?使用before_filter意味着要進行額外的不準確的查詢以防萬一,不是嗎? – Pablo 2010-02-27 10:43:03

+0

不知道我理解你的代碼......在你的'Comments#create'動作中,這個'@ reason'變量是從哪裏冒出來的?你突然想要保存一些甚至不存在的東西。此外,「如果不是@ post」塊不會做你想要的。您需要在提取帖子的行上解救'ActiveRecord :: RecordNotFound'。 – 2010-02-27 22:23:24

0

我同意這裏的其他海報 - 如果您有類似的代碼,那麼重構爲每個控制器操作所調用的常用方法是非常重要的。

如果控制器在多個控制器中很常見,則應用控制器是最好的選擇。

或者,您可以製作一個通用控制器類,即兩個控制器都繼承自 - 且僅包含該輔助方法。除非您可能會分享其他方法,否則我不建議您這樣做。

相關問題