应该由不同的控制器处理前端和后端吗?

时间:2010-05-01 13:06:36

标签: ruby-on-rails architecture

在我之前的学习项目中,我总是使用一个控制器,但现在我想知道这是好的做法还是总是可行的。

在所有RESTful Rails教程中,控制器都有showeditindex视图。如果授权用户已登录,则edit视图可用,index视图会显示其他数据操作控件,例如删除按钮或指向edit视图的链接。

现在我有一个Rails应用程序完全属于这种模式,但index视图不可重复使用:

  1. 普通用户看到一个华丽的索引页面,包含大量图片,复杂的布局,没有Javascript要求,......
  2. Admin用户索引有一个完全不同的简约设计,jQuery表和许多其他数据,...
  3. 现在我不知道如何处理这个案子。我能想到以下几点:

    1. 单一控制器,单一视图:使用if语句将视图拆分为两个大块/部分。
    2. 单个控制器,两个视图:indexindex_admin
    3. 两个不同的控制器:BookControllerBookAdminController
    4. 这些解决方案似乎都不完美,但现在我倾向于使用第三种选择。

      这样做的首选方式是什么?

4 个答案:

答案 0 :(得分:15)

几乎每次我得到一个新项目时,我都会问自己这个问题。我通常选择两种解决方案中的一种:

1)。单控制器,单视图

除非项目非常简单,并且只有一两种类型的用户,否则我现在几乎从不选择此解决方案。如果您获得多种用户类型,最好使用解决方案#2。虽然这种解决方案可能很有吸引力,因为您认为通过编写更少的代码可以节省一些时间,但最终,您的控制器和视图的复杂性会增加。更不用说你必须考虑的所有边缘情况。这通常意味着错误。

我的公司曾经不得不拯救一个失败的项目,它有3种用户类型。 (管理员,业务和成员)。他们使用了解决方案#1。代码处于可怕的状态,(这就是我们被要求拯救这个项目的原因)我们开玩笑地说它不是MVC,而是MMM。 (模型 - 模型 - 模型)这是因为业务逻辑没有被正确地提取并放入模型中,而是在控制器和视图中传播。

2)。多控制器,多视图

这些天我越来越多地使用这个解决方案。我通常使用用户类型命名控制器。例如:

在“app / controllers”中

class BookController < ApplicationController
end

并在“app / controllers / admin”

class Admin::BookController < Admin::BaseController
end

我只需要在填写BookController时考虑普通用户,只需在填写Admin::BookController时考虑管理员用户

我不确定是否有更好的方法,但这是我从目前为止所完成的十几个项目中学到的......

答案 1 :(得分:3)

我在这种情况下所做的事情最近发生了很大的变化。目前的方法如下:

我根据访问要求分离控制器。这让我很清楚 心智模型和检查访问控制(并测试它)的一种非常简单的方法。

我甚至将模型中的“您自己的访问权”分开 控制器。我通常也会保留控制器的名称 单独的命名空间。

这种方法也使得使用标准的restuful控制器变得非常容易 像InheritedResources这样的实现。

请注意,如果需要相同的功能,您可以重复使用许多视图 不同类型的访问。

所以我有这样的事情:

### lets start with routes

# this is basically guest access level. you can only list it and see details
map.resources :books, :only => [:index, :show]

namespace :my do |my|
  # this will require at least login.
  # index and show will be basically same as at the guest level. we can reuse the views
  my.resources :books
end

namespace :admin do |admin|
  # this will require admin login
  admin.resources :books
end

# now the controllers

# this might be just enough of a controller code :). the rest goes into model.
class BooksController < InheritedResources::Base
  actions :index, :show
end

module My
  class BooksController < InheritedResources::Base
    before_filter :require_user

    protected
    def begin_of_association_chain
      # this will force resources to be found on current_user.books.
      # so if you go to /my/books/123 and book 123 is not your book you will get 404
      current_user
    end
  end
end

module Admin
  class BooksController < InheritedResources::Base
    before_filter :require_admin

    # this controller is essentially unrestricted. you can get/edit/update any book
    # and you can have separate view template for index too
  end
end



## Views
# well, this is the part that I like the least in this approach, but
# I think the good outweight the bad.
# I see 2 ways to reuse the views w/o writing lots of ugly customization code for the InheritedResources
# 1) render 'parent' views inside templates. i.e. like:
# my/books/index.html.haml:
!= render :file => "/books/index"

# or just link the templates on the filesystem level with symlinks.
# (or if all of them are the same you can link the directory)

答案 2 :(得分:2)

如果有两个模块,请使用两个电流1] Admin 2] User

class BookUserController < ApplicationController
  #Here layout is used will be of layouts/application.html.erb
  #Here all the methods which user can will be present 
end


class BookAdminController < ApplicationController
  layout 'admin'  #here we set the layout is layouts/admin.html.erb 

end

如果只有一个页面要显示管理员,则可以使用单个控制器和两个方法

class BookUserController < ApplicationController
  layout 'admin', :only=>['index_admin']

  def index_admin


  end

  def index



  end


end

OR

class BookUserController < ApplicationController
  def index_admin

    render :action=>'index_admin', :layout => false
  end

  def index



  end


end

答案 3 :(得分:1)

当我需要一个明确分开的管理区域时,我倾向于为一个资源寻找一个带有两个控制器的解决方案。管理员界面的admin / booksController中的Admin :: BooksController,包含所有操作和公共BooksController,根据需要只有索引和显示方法。