多页面使用相同表单的Rails最佳实践

6
我正在开发一个基于Rails 2.3.1的网站。在整个网站中,我需要在各种页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上都有一个用于创建帖子的表单(总之这个表单需要出现在由各种控制器提供的许多页面上)。每个页面都显示从相应的控制器/操作检索到的各种其他信息。例如,主页列出最新的10篇文章,内容从数据库中获取等。
因此,我将Post创建表单移到了自己的partial中,并在所有必要的页面上包含了此partial。请注意,Partial中的表单POST到/questions(路由到PostsController :: create-这是默认的rails行为)。
我遇到的问题是,当未正确完成Post表单时,默认情况下,PostsController :: create方法会呈现questions / new.html.erb,即使该表单是从主页(/ home / index.html.erb)提交的。
我尝试更改部分中的表单,以提交“submitting_controller”和“submitting_action”,并在PostsController :: create中,当@post.save?== false时,渲染动作=>“../ submitting_controller / submitting_action”(这有点hacky,但可以让您从非PostsController呈现操作)。
这似乎在表面上工作正常。不完整的表单在提交它的视图中呈现,其中包含所有正确的@post.errors消息等。问题是所有其他页面上的数据都没有显示出来,因为实际的submitting_controller / submitting_action方法没有被调用,只呈现了相关视图。(记住,我进行了保留实例对象的呈现,而不是不保留@post实例对象的redirect_to,后者具有所有错误消息和提交的值。)
就我所看到的,我有两个选择:
1)当@post.save?在PostsController :: create中失败时,在重定向到submitting_controller / submitting_action时将@post对象存储在会话中,此时我从会话中取出@post对象并使用它重新填充表单/错误消息。(据我所知,在Rails中存储对象是不好的做法)
2)我可以将用于提取非Post创建表单数据的所有逻辑从各个submitting_controller / submitting_action中移动到ApplicationController中,在PostsController :: create中创建一个巨大的switch语句,针对submitting_controller / submitting_action,并调用ApplicationController中的方法来获取每个提交页面所需的所有额外数据。
您认为在Rails中最好的方法是什么?
2个回答

1
关于从完全页面更新到通过AJAX更新页面部分的要点。有很多事情你应该考虑,但最符合Rails风格的方法是将响应分为AJAX响应和纯HTML响应。查看这篇ONLamp文章这篇注册文章这本令人惊叹的使用Rails进行敏捷网络开发的书籍。基本上,您的控制器呈现一个新的div,替换包含部分提交结果的旧div。
在您的问题中,您提到了两种方法,所以我会尝试给您一些建议,解释为什么和为什么不采用这些方法。

选项1) 这个选项并不那么糟糕,只需要做一些微调就可以了。主要的微调是将对象以序列化的形式存储在数据库中,然后只需传递序列化对象的ID。好处是会持久化会话数据,因此恢复一个会话更加简洁,而且会话保持轻量级。缺点是如果你在数据库中有大量未使用的会话信息,就会污染你的应用程序,需要考虑如何从数据库中过期删除未使用的会话信息。我从未见过使用这种方法成功的例子...

选项2) 不要在application_controller中使用! :) 说真的,把它当成最后的手段。你可以把东西放在helpers中,并在控制器和视图中访问那些方法。但是测试这些东西并不容易,所以在选择这条路之前请小心。在面向对象的应用程序中,可以通过一些思考来替换switch语句,当然,在这种情况下,您可以使用选项哈希来获得一种Rails方式,以便在请求时获取有关应用程序状态的一些智能。


谢谢,几个想法:选项1)在数据库中跟踪对象似乎可能会变成一场噩梦,确实是一个滑坡。选项2)我认为控制器不能访问帮助程序(可能是CakePHP的影响)。 我同意ApplicationController是放置它们的恶心地方;) 哈希是一个好主意,但我仍然不喜欢将所有这些视图特定数据选择移动到帮助程序中 - 看起来很容易变成维护噩梦。我会阅读您提供的文章,但我认为AJAX将是前进的道路。 - empire29

1

你的Post模型是否与每个控制器一起使用以呈现表单的每个模型处于belongs_to关系?除了Post.create(params[:post])之外,你在Post控制器中进行了任何特殊处理吗?

如果你对第一个问题回答是肯定的,对第二个问题回答是否定的,那么你可以通过将accepts_nested_attributes_for添加到每个用户可以创建帖子的控制器中来实现最小化操作。

无论如何,Robertpostill的观点是正确的,这可能是开始考虑AJAX的时候,只需替换页面的部分内容即可。唯一的问题是如果用户禁用了JavaScript该怎么办。个人而言,我喜欢为非JavaScript情况设计并添加方便的方法。

至于你认为的两个选项的想法:

1)我使用此方法在flash哈希中存储对象的浅拷贝。跨重定向保留它。但是,由于帖子的变量性质,这可能对你不起作用。因为你只能发送大约4K的数据,其中包括你的浅拷贝以外的其他信息。

2)请参阅robertpostill的回复。


Emfi,关于嵌套属性的观点很好。这个想法我之前没有考虑过。你指出的默认非JS的观点也很重要。不过我的感觉是,提问者(暂且这么称呼)会通过重新构建所有对象来执行大量的数据库操作,从而损害应用程序的性能。 - robertpostill
我们对此达成了一致。然而,非JavaScript和AJAX之间的区别通常是一个link_to_remote调用、一个呈现模板的RJS,以及可能会有一些控制器逻辑来避免你通常会进行的数据库调用。 - EmFi
EmFi,不幸的是,Post模型和你将用于呈现表单的模型可能没有关联(HomeController甚至没有支持模型)。我在PostController :: create中对验证码机制进行了一些检查(验证码字段不是Post Model的一部分,而是它自己的模块)。我认为你和Robertpostill都是正确的,AJAX是解决这个问题的方法。我只需要弄清楚如何使用jQuery(我选择不使用Prototype,因为个人喜好),并且不会搞乱Rails中的任何东西。 - empire29

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接