Rails子控制器?

我对Rails很新,并且有一个问题,我不能完全理解这种架构上“正确”的做法。

问题涉及我所谓的子控制器。 场景是这样的:

我有一系列页面,其中包含一些包含一些信息的表单(想想右上角的gitHub上的用户面板)。

因此,在我的应用程序中,我有控制器为页面生成数据并渲染出很好的响应,但是当涉及到这个面板时,在我看来,你会想要某种控制器动作来专门生成这个面板和它的观点。

问题是,你是怎么做的? 如何在视图中渲染“子控制器”?

我会将逻辑放在帮助器或模块中。 ( http://api.rubyonrails.org/classes/ActionController/Helpers/ClassMethods.html

然后渲染您希望显示这些内容的部分。 ( http://api.rubyonrails.org/classes/ActionView/Partials.html

就像赫尔曼所说的那样,如果你需要在控制器切换到视图后生成逻辑(即,页面控制器生成页面视图,但你想要一个自定义面板),那么就把它放在帮手中。 或者,在切换到视图之前,在Pages控制器中调用单独的方法。 或者,如果它有很多逻辑,请创建一个模块并将其粘贴到/ lib文件夹中。 因此,你可以拥有一个完整的Panel模块,其中的方法可以生成Panel的不同部分,并由控制器调用。 但是如果你想从视图中调用这些方法,那么你应该使用一个帮助器。

我不认为模块是这里所需要的,模块是跨类的一小部分共享行为所必需的。

我认为这里需要的是理解ApplicationController的inheritance以及布局

所以,例如,我的布局可能如下所示:

 Foo  <%= render :partial => (current_user ? "/shared/user_widget_bar" : "/shared/login_bar") %> <%= yield %>   

我想用它的任何代码都会放在我的ApplicationController中,因为它将在我的大多数应用程序中共享:

  before_filter :generate_user_widget def generate_user_widget if current_user @avatar = ... @unread_messages = ... end end 

我明白它属于一个单独的控制器可能更干净但老实说,除非代码很大,它没关系,甚至可以放在一个模块中,然后由ActionController包含。 但是,如果考虑它的范围,它确实需要在ApplicationController中。

如果有更多相关页面,例如,你有一个Rails应用程序管理多个站点,你想要在特定站点上共享行为,尝试创建一个没有操作的父控制器,只有私有方法,任何需要的控制器访问这些方法可以inheritance它。 这样你就可以在filter之前应用到inheritance它的所有控制器,省去了忘记在非父控制器中添加一个控制器的痛苦。

例如:

 class SiteA::SiteAParentController < ApplicationController before_filter :generate_user_widget ... end class SiteA::ProductController < SiteA::SiteAParentController def index ... end end 

好吧,如果你真的需要从视图中调用控制器动作,你可以使用组件。 它们是框架的一部分,现在它们只作为插件存在。 一个似乎维护得很好的插件就在这里: http : //github.com/cainlevy/components/tree/master

从其文档:

==用法

请注意,这些示例非常简单,使用Rails partials可以更好地实现。

===发电机

运行script/generator users details将创建具有“详细信息”视图的UsersComponent。 然后你可以像这样充实模板:

 class UsersComponent < Components::Base def details(user_or_id) @user = user_or_id.is_a?(User) ? user_or_id : User.find(user_or_id) render end end 

===来自ActionController

 class UsersController < ApplicationController def show return :text => component("users/detail", params[:id]) end end 

===来自ActionView

 <%= component "users/detail", @user %>