如何重用 Rails 中嵌套控制器的渲染动作?
Posted
技术标签:
【中文标题】如何重用 Rails 中嵌套控制器的渲染动作?【英文标题】:How to reuse the rendering actions from nested controllers in Rails? 【发布时间】:2013-01-23 17:56:18 【问题描述】:我有一个关于控制器操作之间代码重用的问题。我认为这是一个相当标准的情况,所以我对 Rails 的最佳实践很感兴趣。
假设我有一个films
资源和一个对应的FilmsController
,它有一个由CommentsController
服务的嵌套资源comments
。嵌套资源可以使用其index
和show
操作自行呈现。但是,也应该可以渲染嵌入在相应电影页面中的 cmets。
现在,问题是,在FilmsController.show
中重用来自CommentsController
的代码的最佳方法是什么?
1) 强制CommentsController.index
呈现为字符串,然后将其以变量的形式传递给电影视图?
或者2)直接在电影视图中调用CommentsController.index
作为一种“部分”,从那里执行数据库查询?
或者 3) 在CommentsController
中创建一个单独的方法来负责数据库处理,从CommentsController.index
和FilmsController.show
中调用它,并在这两个地方也使用相应的视图?
对我来说,选项 1) 和 2) 看起来有点混乱,而 3) 不是模块化的并且涉及一些代码重复。有没有更好的方法来做到这一点?
非常感谢!
【问题讨论】:
在 ruby on rails 中查找演示者模式 @TonyHopkinson - 感谢您的想法,当传递的数据更复杂时,Presenter 模式在某些情况下确实可能会有所帮助。总而言之,看起来我会选择我的选项 3),同时尽可能封装。 简单数据有一个不好的习惯,就是变得不简单,速度很快,但是欢迎您。create a separate method in CommentsController responsible for the database handling
数据库操作应该在模型而不是控制器中。数据库重用的另一件事是服务对象。
【参考方案1】:
现在问题来了,在 FilmsController.show 中重用 CommentsController 中的代码的最佳方法是什么?
您可以将共享控制器逻辑移动到应用程序控制器内部(或 lib 并适当地要求它),一个 la:
class ApplicationController < ActionController::Base
def foo
@foo = "foo"
end
end
评论控制器:
class CommentsController < ApplicationController
before_filter :foo, :only => [:index]
def index
end
end
电影总监:
class FilmsController < ApplicationController
before_filter :foo, :only => [:show]
def show
end
end
对于重复的视图逻辑,您可以将其移动到一个公共文件夹,例如 your_app/app/views/shared/_foo.html.erb
并适当地呈现它。
另一种选择是将相关代码放入外部模块中:
lib/mymodule.rb
module MyModule
def foo
end
end
然后您可以将模块包含在您的控制器中或任何您想访问foo
方法的地方。
class CommentsController < ApplicationController
include MyModule
def index
foo()
end
end
【讨论】:
为聚合控制器及其组件使用一个共同的祖先是一个有趣的想法,我实际上可能会将它用于其他一些方面。但是对于这个简单的问题,它似乎使代码更加晦涩和分散。将foo
代码放入CommentsController
并显式调用它对我来说似乎更清晰。
是的,当我说调试时从 ApplicationController 调用方法有点棘手时,我可以根据经验说话。我认为更简洁的方法是将重复的代码划分为一个 lib 模块,然后将其包含在相关的控制器操作中。至少这样你就可以清楚地表明你的方法是从外部源调用的,并且你正在将继承代码继承到从不使用它的控制器中。以上是关于如何重用 Rails 中嵌套控制器的渲染动作?的主要内容,如果未能解决你的问题,请参考以下文章