当你有一个可重用的小部件时,在 Rails 中执行 UJS 的最佳方法是什么?
在我当前的项目中,我有几个实例,其中有一个存在于 Rails 部分内的可重用表单。该表单通过ajax提交给特定的控制器(:remote => true)。控制器执行一些操作,然后返回适当的 js.erb 以通过 javascript 修改页面。
当我只有一个视图时,这很有效。但是当这个可重用的部分存在于多个视图上时,问题似乎就会发生。在视图 1 中,我可能想在视图 2 中发出一组完全不同的 javascript 命令。
作为一个具体示例,假设我有一个具有正常 CRUD 操作的注释控制器。
我现在有部分名为 _comments_box.erb。这个 _comments_box.erb 包含通过简单的行提交评论的功能:
- form_for comment, :url => post_comments_path(post), :remote => true do |f|
这提交到 comments_controller.rb 创建方法,看起来像这样:
def create
... do some stuff, like create a new comments model
respond_to do |format|
# will respond with create.js.erb
format.js
end
end
create.js.erb 反过来向视图添加评论,也许会做一堆对 DOM 的其他更新。
假设我在名为 post_summary.erb 的视图中渲染 _comments_box.erb。现在我有另一个视图 post_detail.erb 需要相同的 _comments_box.erb。然而,post_detail.erb 要求我更新 DOM 上完全不同的 div 以响应新评论。
我需要为每个实例化创建不同的 JS 响应。所以我可以:
- 创建一个备用控制器方法,例如 create_2。将一些参数从 post_detail.erb 传递到 _comments_box.erb 到 _comments_box.erb 部分,以便它知道要触发哪个控制器方法。这将允许我拥有一个单独的文件 _create_2.js.erb,它允许我独立操作 post_detail.erb 视图。
- 完全忘记使用 js.erb,只使用普通的旧 AJAX 并返回 JSON,并完全在客户端处理 javascript 操作。
看来选项1允许我继续使用Rails支持的UJS,这很好。但这也意味着我可能会在各处添加大量重复的代码,这很烦人。有没有办法让我在继续使用 UJS 的同时优雅地做到这一点?
In my current project I have a couple instances where I have a re-usable form that exists inside a rails partial. This form submits to a specific controller via ajax (:remote => true). The controller does some stuff and then returns back the appropriate js.erb to modify the page via javascript.
This works fine for when I have a single view. But the problem seems to happen when this re-usable partial exists on multiple views. In view 1 I might want to issue a completely different set of javascript commands then in view 2.
As a concrete example, say I have a comments controller that has the normal CRUD operations.
I now have partial called _comments_box.erb. This _comments_box.erb contains the ability to submit a comment via a simple line:
- form_for comment, :url => post_comments_path(post), :remote => true do |f|
This submits to a comments_controller.rb create method which looks somethings like this:
def create
... do some stuff, like create a new comments model
respond_to do |format|
# will respond with create.js.erb
format.js
end
end
The create.js.erb in turn adds a comment to the view, perhaps doing a bunch of other updates to the DOM.
Say I render the _comments_box.erb within a view called post_summary.erb. Now I have another view, post_detail.erb that requires the same _comments_box.erb. However the post_detail.erb requires me to update completely different divs on the DOM in response to a new comment.
I need to create a different JS response for each instantiation. So I can either:
- Create an alternate controller method, say create_2. Pass in some parameter to the _comments_box.erb from post_detail.erb to the _comments_box.erb partial so it knows which controller method to fire. This will allow me to have a separate file _create_2.js.erb that will allow me to manipulate the post_detail.erb view independently.
- Forget about using js.erb altogether and just use plain old AJAX and get back JSON, and handle the javascript manipulation completely on the client-side.
It seems option 1 allows me to continue to use the UJS supported by Rails which is nice. But also means I probably will be adding a lot of duplicate code everywhere which is annoying. Is there a way for me to do this elegantly while continuing to use UJS?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这正是
Apotomo
的目的:http://apotomo.de/这是它自己的描述:
尝试一下,很棒。
That's exactly the purpose of
Apotomo
: http://apotomo.de/Here is it's own description:
Have a try, it's great.
我不建议将 UJS 用于前端应用程序:服务器不应该处理客户端业务。我同意它有用且干净,但它缺乏性能,因此应该保留用于后端内容(RJS 将移至 gem,请参见此处:http://weblog.rubyonrails.org/2011/4/21/jquery-new-default)。
也就是说,回到您公开的解决方案:
1)我认为您不需要额外的控制器,您只需传递额外的参数即可知道查询来自哪里。
hidden_field
可以解决这个问题。有了这些信息,渲染好的js.erb
文件2) 我会选择它并返回 json,但您将面临同样的问题:知道请求来自哪里。< /p>
I'd not recommend using UJS for frontend apps: server shouldn't take care of client side business. I agree it's useful and clean but it lacks performance and thus should be kept for backend stuff (RJS will move into a gem, see here: http://weblog.rubyonrails.org/2011/4/21/jquery-new-default).
That said, back to the solutions you expose:
1) I think you won't need an extra controller, you'd just have to pass additional params in order to know from where to query came from. A
hidden_field
could do the trick. With this info, render the goodjs.erb
file2) I'd go for it and return json but you'll face the same problem: knowing from where the request comes from.
更好的解决方案(比使用
hidden_field
)可能是检查控制器操作中的request.referer
。通过这种方式,您可以利用每个上下文都有唯一 URL 的事实,并且在渲染小部件部分时不必显式指定另一个唯一值。A better solution (than using a
hidden_field
) might be to check therequest.referer
in your controller action. This way you leverage the fact that each context has a unique URL, and don't have to explicitly specify another unique value when rendering your widget partial.