【问题标题】:multiple controllers in one view (ruby on rails MVC)一个视图中的多个控制器(ruby on rails MVC)
【发布时间】:2012-11-07 19:47:12
【问题描述】:

大家好,我需要您的宝贵帮助。在Ruby on Rails tutorial,第10章,作者在一个视图中有2个控制器。我构建了一个类似的应用程序,其中我在一个视图中也有 2 个控制器,但是,当我渲染一个属于第二个控制器的方法时,从第一个开始我就遇到了参数问题。 (在教程中作者没有在其他控制器的动作中使用任何参数)

更具体地说,我有 2 个控制器:UsersController 和 MicropostsController。另外,在 Users 的 show.html.haml 页面中,我使用了两个控制器:UsersController 用于显示用户的微博,而 MicropostsController 则允许用户创建新的微博。

MicropostsController 内部:

def create
  @micropost = current_user.microposts.build(params[:micropost])
  if @micropost.save
    flash[:success] = "Micropost created!"
    redirect_to user_path(current_user)
  else
    #render text: renderActionInOtherController(UsersController,:show, {:id => 1})
    @user = User.find(current_user)
    @microposts = @user.microposts.paginate(page: params[:page])
    render 'users/show'
  end
end

在用户控制器内部

def show
  @user = User.find(params[:id])
  @microposts = @user.microposts.paginate(page: params[:page])
  @micropost = current_user.microposts.build if signed_in?
end

在 app/views/users/show.html.haml

- provide(:title, @user.name)
.users_page
  .row
    %aside.span4
      - if !signed_in?
        %section
          %h1
            = gravatar_for @user
            = @user.name
      - else
        %section
          = render 'shared/user_info'
        %section
          = render 'shared/micropost_form'

    .span8
      - if @user.microposts.any?
        %h3 Microposts (#{@user.microposts.count})
        %ol.microposts
          = render @microposts
        = will_paginate @microposts

所以基本上我的问题总结如下:

1)在一个视图中有多个控制器是一种好习惯吗?我在网上找到了相互矛盾的答案。 (实际上,我什至不确定这段代码是否仍然是 RESTful)

2) 如果 1 是肯定的(或者至少这不是一个坏习惯),我可以以更有效的方式实现同​​样的事情吗?因为在我看来,每次我从另一个控制器渲染动作时,我都必须重新定义变量。

3) 我在 stackoverflow 中发现了一个 similar 主题,其中有人建议使用此方法(因为我是 RoR 的新手,所以我不知道它的确切作用)。

def renderActionInOtherController(controller,action,params)
  controller.class_eval{
    def params=(params); @params = params end
    def params; @params end
  }
  c = controller.new
  c.request = @_request
  c.response = @_response
  c.params = params
  c.send(action)
  c.response.body
end

如果我在 MicropostsController 中使用这个版本的创建操作,

def create
  @micropost = current_user.microposts.build(params[:micropost])
  if @micropost.save
    flash[:success] = "Micropost created!"
    redirect_to user_path(current_user)
  else
    render text: renderActionInOtherController(UsersController,:show, {:id => 1})
    #@user = User.find(current_user)
    #@microposts = @user.microposts.paginate(page: params[:page])
    #render 'users/show'
  end
end

当我点击发布按钮时,我在浏览器中什么都没有。此外,当我尝试查看用户/1 页面时,我收到以下错误(!!):

undefined method `[]' for nil:NilClass

任何帮助都会非常有价值!如果您需要任何其他信息,请告诉我!

【问题讨论】:

    标签: ruby-on-rails controller render params


    【解决方案1】:
    1. 从技术上讲,这个术语有些令人困惑。默认情况下,控制器中的每个方法都对应一个名称相似的视图文件,因此最好将问题表述为 “渲染不是默认视图的视图是否是一种好习惯?”当然,答案是视情况而定。这是一种常用来干掉控制器代码的技术,如果它有好处,在你的应用程序中,我肯定会使用它。事实上,Rails 中uses itcreateupdate 方法中默认资源脚手架生成的控制器代码。我认为你可以提出这样的论点:Rails 核心中的任何东西,如果不是最佳实践,至少在理智的范围内。

    2. 话虽如此,可能还有改进的机会。处理相同事情的常用方法是将您的创建和更新请求路由到相同的控制器操作并使用相同的控制器视图。如果这不可行,至少可以确保您不需要重新定义变量。来自official documentation

    将渲染与 :action 一起使用是 Rails 混淆的常见来源 新人。指定的操作用于确定要使用哪个视图 渲染,但 Rails 不会在 控制器。您在视图中需要的任何实例变量都必须 在调用render之前在当前action中设置。

    1. 您不应该这样做……在这种情况下,或我能想到的任何其他情况下都不需要。任何时候你在 Rails 中看到这样的超级 hackey 都表明某些事情可能不太正确,并且可能有更好的方法来处理同样的事情。

    奖励:如果您需要去某个已经负责设置自己的地方,并且您不需要访问任何范围内的变量,那么重定向可能是更好的选择。这样,您无需在多个地方重新描述您的控制器逻辑。这是您发布的代码中的一个示例:

        # inefficient and not DRY
        @user = User.find(current_user)
        @microposts = @user.microposts.paginate(page: params[:page])
        render 'users/show'
    
        # does the same thing as above (in this case)
        redirect_to users_path
    

    【讨论】:

      【解决方案2】:

      我想补充一点,我认为教程作者为什么对 Create Microposts 操作实施了一种不那么 DRY 的解决方案的理由是,如果使用 redirect_to 而不是 render,那么他们会丢失表单的 flash 错误。

      我不确定是否有更 DRY 的解决方案来维护表单闪存错误。

      【讨论】:

        猜你喜欢
        • 2012-01-09
        • 2017-10-27
        • 2010-10-03
        • 2013-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多