如何重用 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。嵌套资源可以使用其indexshow 操作自行呈现。但是,也应该可以渲染嵌入在相应电影页面中的 cmets。

现在,问题是,在FilmsController.show 中重用来自CommentsController 的代码的最佳方法是什么?

1) 强制CommentsController.index 呈现为字符串,然后将其以变量的形式传递给电影视图?

或者2)直接在电影视图中调用CommentsController.index作为一种“部分”,从那里执行数据库查询?

或者 3) 在CommentsController 中创建一个单独的方法来负责数据库处理,从CommentsController.indexFilmsController.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 中嵌套控制器的渲染动作?的主要内容,如果未能解决你的问题,请参考以下文章

js.erb 不在 Rails 6 中渲染

重用rails上的视图

每个动作的 Rails 布局?

我们如何避免控制器中方法的重复/重复 - RAILS 3+

Rails 5,动作电缆和 current_user

如何渲染与 Rails 中的成员操作同名的 js.erb?