【问题标题】:Should frontend and backend be handled by different controllers?前端和后端应该由不同的控制器处理吗?
【发布时间】:2010-05-01 13:06:36
【问题描述】:

在我以前的学习项目中,我总是使用单个控制器,但现在我想知道这是否是一种好的做法,甚至是否总是可行的。

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

现在我有一个完全符合这种模式的 Rails 应用程序,但 index 视图不可重用:

  1. 普通用户会看到一个华丽的索引页面,其中包含大量图片、复杂的布局、没有 Javascript 要求……
  2. Admin 用户索引具有完全不同的简约设计、jQuery 表和大量附加数据,...

现在我不确定如何处理这种情况。我可以想到以下几点:

  1. 单控制器,单视图:使用if 语句将视图分成两个大块/部分。
  2. 单个控制器,两个视图:indexindex_admin
  3. 两个不同的控制器:BookControllerBookAdminController

这些解决方案似乎都不是完美的,但现在我倾向于使用第 3 个选项。

最好的方法是什么?

【问题讨论】:

    标签: ruby-on-rails architecture


    【解决方案1】:

    我几乎每次接到一个新项目时都会问自己这个问题。我通常选择以下两种解决方案之一:

    1)。单控制器,单视图

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

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

    2)。多控制器,多视图

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

    在“应用程序/控制器”中

    class BookController < ApplicationController
    end
    

    在“app/controllers/admin”中

    class Admin::BookController < Admin::BaseController
    end
    

    我填写BookController时只需要考虑普通用户,填写Admin::BookController时只需要考虑admin用户

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

    【讨论】:

      【解决方案2】:

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

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

      我什至将“您自己对模型的访问”分成单独的 控制器。我通常也会保留控制器的名称,只需将其放入 单独的命名空间。

      这种方法也使得使用标准的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)
      

      【讨论】:

        【解决方案3】:

        如果有两个模块,则使用两个当前 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
        

        class BookUserController < ApplicationController
          def index_admin
        
            render :action=>'index_admin', :layout => false
          end
        
          def index
        
        
        
          end
        
        
        end
        

        【讨论】:

          【解决方案4】:

          当我需要一个明确分隔的管理区域时,我倾向于使用两个控制器来处理一个资源的解决方案。 admin/ 子目录中的 Admin::BooksController 用于管理界面,其中包含所有操作和一个公共 BooksController,根据需要只有 index 和 show 方法。

          【讨论】:

            猜你喜欢
            • 2015-11-30
            • 2022-09-23
            • 1970-01-01
            • 1970-01-01
            • 2021-10-18
            • 1970-01-01
            • 2016-09-26
            • 2020-01-30
            • 1970-01-01
            相关资源
            最近更新 更多