Rails 在多个页面上使用相同表单的最佳实践
我正在开发一个 Rails 2.3.1 网站。在整个网站中,我需要一个用于在各个页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上创建帖子的表单 - 足以说明此表单需要位于由各种控制器)。这些页面中的每一个都显示在相应的控制器/操作中检索的各种其他信息。例如,主页列出了最新的 10 篇帖子、从数据库中提取的内容等。
因此,我已将帖子创建表单移至其自己的部分中,并将该部分包含在所有必要的页面上。请注意,部分 POST 到 /questions 中的表单(路由到 PostsController::create —— 这是默认的 Rails 行为)。
我遇到的问题是,当 Posts 表单未正确完成时,默认情况下 PostsController::create 方法会渲染 questions/new.html.erb,即使表单是从主页 (/home/index.erb) 提交的。 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 时可以将@post对象存储在会话中吗?在 PostsController::create、redirect_to Submitting_controller/submitting_action 中失败,此时我将 @post 对象从会话中拉出并使用它来重新填充表单/错误消息。 (据我所知,在会话中存储对象在rails中是不好的做法)
2)我可以移动用于从各种submitting_controller/submitting_action中提取非后期创建表单数据的所有逻辑,将其放入ApplicationController中,创建一个PostsController::create 中的巨型 switch 语句用于 Submit_controller/submitting_action 并调用 ApplicationController 中的方法来获取每个提交页面渲染所需的所有额外数据。
关于在 Rails 中执行此操作的最佳方法的想法?
I am developing an Rails 2.3.1 Web site. Throughout the Web site, I need to have a form for creating Posts on various pages (Home page, Create Posts page, Post listing page, Comment listing page, etc. -- suffice to say this form needs to be on many pages served by a variety of controllers). Each of these pages displays a wide variety of other information that is retrieved in the corresponding controller/action. Ex, the home page lists latest 10 posts, content pulled from the DB, etc.
So, I've moved the Post creation form into its own partial, and included this partial on all the necessary pages. Note that the form in the Partial POSTs to /questions (which routes to PostsController::create -- this is default rails behavior).
The problem I am running into is when the the Posts form is not completed correctly, by default the PostsController::create method render's questions/new.html.erb, even if the form was submitted from the home page (/home/index.html.erb).
I tried changing the form in the partial to submit the "submitting_controller" and "submitting_action", and in PostsController::create, when @post.save? == false, I render action => "../submitting_controller/submitting_action" (Which is slightly hacky, but lets you render actions from non-PostsController's).
This seemed to work OK on the surface. The incomplete form was rendered in the view that submitted it with all the correct @post.errors message, etc. The problem was ALL the other data on the pages didnt show up, because the actual submitting_controller/submitting_action methods weren't called, just the associated view. (Remeber, I did a render which preserves instance objects, rather than a redirect_to which does not preserve the @post instance object which has all the error messages and submitted values.)
As far as I can see I have two options:
1) I can store the @post object in the session when @post.save? fails in PostsController::create, redirect_to submitting_controller/submitting_action, at which point i pull the @post object out of the session and use it to re-populate the form/error messages. (As far as I understand, storing objects in the session is BAD practice in rails)
2) I can move all the logic used to pull non-post creation form data from the various submitting_controller/submitting_action, put it in the ApplicationController, create a giant switch statement in PostsController::create for submitting_controller/submitting_action and call the methods in the ApplicationController to grab all the extra data needed for each submitting page's render.
Thoughts on the best way to do this within Rails?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的 Post 模型是否与您将用来呈现表单的控制器的每个模型存在belongs_to关系?除了
Post.create(params[:post])
之外,您是否在 Post 控制器中进行任何特殊处理?如果您对第一个问题的回答是“是”,对第二个问题的回答是“否”,则可以通过将accepts_nested_attributes_for添加到用户可以在其上创建帖子的每个控制器来以最少的修改来完成。
不管怎样,Robertpostill 是正确的,因为这可能是开始考虑 AJAX 的时候,只是为了替换页面的部分。唯一的问题是如果用户禁用了 javascript 该怎么办。就我个人而言,我喜欢为非 javascript 情况进行设计并添加便捷的方法。
至于您对两个选项的看法,
1)我使用此方法在闪存哈希中存储对象的浅表副本。跨重定向保留它。然而,考虑到帖子的可变性质,这可能对您不起作用。因为您只能发送大约 4K 的数据,其中还包括除浅拷贝之外的其他信息。
2)参见 Robertpostill 的回复
By any chance is your Post model in a belongs_to relationship with each model who's controller you'll be using to render your form? Are you doing any special processing in the Post controller beyond
Post.create(params[:post])
?If you answered yes to the first question and no to the second, you could get by with minimal mangling by adding accepts_nested_attributes_for to each of the controllers on which a user can create a post.
Regardless, Robertpostill is correct in that this is probably when to start looking at AJAX, to just replace the section of the page. The only problem is what to do if a user has javascript disabled. Personally I like to do design for the non-javascript case and add convenience methods.
As for thoughts on what you consider your two options,
1) I've used this method to store a shallow copy of an object in the flash hash. Preserving it across redirects. However this might not work for you given the variable nature of posts. As you can only send about 4K worth of data, and that includes other information in addition to your shallow copy.
2) See robertpostill's response
这是关于通过使用 AJAX 从整个页面更新转向更新页面部分的要点。您应该考虑很多事情,但最 Rails 式的方法是将响应拆分为 AJAX 响应和纯 HTML 响应。查看这篇 ONLamp 文章,此注册文章 或 使用 Rails 进行敏捷 Web 开发的精彩书籍。本质上,您的控制器呈现一个新的 div 替换包含提交部分结果的旧 div。
在你的问题中,你提到了两种方法,所以我会尝试给你一些关于为什么和为什么不在这里的建议:
选项1)这个选项通过一些调整并不是那么糟糕。主要调整是将对象以序列化形式存储在数据库中。然后只需传递序列化对象的 ID 即可。优点是会话数据会被持久化,因此恢复会话会更整洁,并且会话保持轻松状态。这样做的缺点是,数据库中存在大量会话垃圾会污染您的应用程序,并且您需要考虑如何使数据库中未使用的会话垃圾过期。我从来没有很好地看到过这个结局...
选项2)Eeek不在application_controller内部! :) 说真的,把它作为你最后的武器。不过,您可以在助手中弹出内容,并访问控制器和视图中的这些方法。然而,测试这些东西并不那么容易,所以在选择这条路线之前要小心。在 OO 应用程序中,只需稍加思考即可替换 Switch 语句,当然在这种情况下,您可以使用选项哈希来获得有关发出请求时应用程序状态的一些智能方式。
This is about the point that you move from full page updates to updating sections of a page through the use of AJAX. There are a bunch of things you should consider but the most rails-esque approach would be to split the response between an AJAX response and a plain HTML response. Check out this ONLamp article, this register article or the awesome agile web development with rails book. Essentially your controller renders a new div replacing the old div containing the result of submitting the partial.
In your question you mention two approaches and so I'll try and give you some pointers on why and why not here:
Option 1) Ths option is not so bad with a couple of tweaks. The main tweak is is to store the object in a serialized form in the DB. Then simply pass around the ID of the serialized object. Your upsides are that the session data gets persisted so recovering a a session is neater and your session stays light. The downside of this is that having a bucket of session cruft in your DB will pollute your app and you'l need to do some thinking as to how you expire unused session cruft from the DB. I've never seen this end well...
Option2) Eeek not inside the application_controller! :) Seriously, keep that as your weapon of last resort. You can pop things insde the helpers though and get access to those methods inside your controllers and views. However the testing of that stuff is not so easy so be careful before choosing that route. Switch statements can be replaced in OO apps with a little thinking, certainly in his case you can use option hashes to get a railsy way of having some smarts about the state of the app at the time the request is made.