2

我在我的代码中使用了一个可怕的模式,我知道必须有更好的方法来做到这一点。帮助我重新思考我在做什么。

我的网站是一种讨论论坛。所有对讨论的回复都在 DiscussionsController#show 页面上进行,内联。

但是,有些回复是无效的 - 例如,如果您尝试发布没有文本的回复,它会将您返回到 DiscussionsController#show 并显示错误消息。

以下是我如何实现此工作流程的简要概述:

  1. 用户转到 DiscussionsController#show。这个模板上有一个回复表格。没有明确的 RepliesController#new 操作。
  2. 用户提交回复表单,该表单被 POST 到 replies_path 并在 RepliesController#create 中处理。
  3. RepliesController#create 无法保存回复,因为它无效(回复中的 validates_length_of 使对象无效)。
  4. RepliesController#create 将回复对象放入 session[:new_reply] 并重定向到用户来自的讨论路径。
  5. DiscussionsController#show 处理会话对象...

像这样:

if session[:new_reply]
  @new_reply = session[:new_reply]
  session.delete(:new_reply)
end

现在 show.html.erb 有一个新生成的 @new_reply 对象来检查错误。

这显然有问题 - 您不应该将整个对象存储在会话中。但是由于我们试图保存在 RepliesController#create 中的回复对象从未保存,我如何在控制器操作调用之间保存它?

或者,如果有更大的设计解决方案,请随时分享。这太丑了,它伤害了我。谢谢。

4

3 回答 3

2

我会将回复存储在 flash中,而不是会话,这对于通过操作传递消息/对象很有用。

如果回复无效并重定向,控制器将简单地将回复存储在闪存中:

if @reply.save
   ...
else
   flash[:reply] = @reply
end

并且您在讨论/显示页面上的表单逻辑需要更聪明一些,并在 Flash 或新的回复中获取回复(我假设您正在讨论/显示操作中创建):

form_for(flash[:reply] || @reply) do
  ...
end
于 2009-05-09T23:13:25.927 回答
2

不如不重定向,render :action => "discussions/show"而是做。我本来想说你也必须设置@discussion变量,但应该这样做,因为回复是讨论中的嵌套资源,对吧?

于 2009-05-09T10:31:07.587 回答
0

我会说你这样做的方式是合理的。不是最干净的,但它是 RESTful 的。

Radar 的建议很棒,但在当前版本的 Rails 中,使用render :action => "discussions/show"不会产生正确的行为,至少在我的尝试中,没有嵌套资源路由。使用render :controller => "discussions", :action => "show"会产生另一种行为,这不是发布者想要的。

于 2009-09-18T17:19:59.073 回答