我的模型包含费用,包括用户和项目参考..
class Expense < ActiveRecord::Base
attr_accessible :amount, :expense_date, :description, :project_id, :user_id
belongs_to :project
belongs_to :user
end
ExpensesController处理费用的基本CRUD操作。
我现在需要构建同一页面的管理员版本,最好是一个新视图,它可以包括数据的不同视图,用户,项目等,还可以编辑用户不能的数据。
我的问题是:构建第二个控制器来处理数据的管理视角,或者我在每个方法中设置条件,检测原始视图和表单,然后条件将它们重定向回他们属于哪里?
如果我构建第二个控制器,如何正确设置form_for以便它知道要去哪个控制器?
谢谢!
PS - 如果有人有任何关于如何正确组装rails应用程序的书籍,我觉得我知道蚂蚁部分的部分,但我会陷入大局的实施。我在Michael Hartl的指南中学习了rails,之前我是一名PHP开发人员。答案 0 :(得分:3)
恕我直言,如果安全性是您的应用程序的一大问题,那么使用管理命名空间和单独的控制器是确保您不留任何空白的最佳方法。它也更简单,压力更小。
我会有这样的目录结构:
/app/controllers/application_controller.rb
/app/controllers/admin_controller.rb - inherits from application_controller
/app/controllers/expenses_controller.rb - non-admin, inherits from application_controller
/app/controllers/admin/expenses_controller.rb - inherits from admin_controller
您的观点将被类似地分开/重复:
/app/views/expenses/* - non-admin expenses views
/app/views/admin/expenses/* - admin expenses views
在application_controller中,您将Devise方法设置为authenticate_user,将CanCan方法设置为check_authorization(如果在控制器操作中的某个点未检查授权,则抛出异常)。在admin_controller中,您有更严格的过滤器以确保用户是管理员。然后,您可以在特定控制器及其操作中获得更细粒度。
当然,每个控制器只需要定义它真正需要的动作,而不必复制视图。也许非admin的expense_controller有index,show,new,create,而admin只有edit,update和destroy。然后在“显示”视图中,如果用户是管理员,您仍然可以添加指向“编辑”操作的链接。
编辑 - 路线
使用上面的示例,您的routes.rb看起来像:
resources :expenses, :only => [:index, :show, :new, :create]
namespace :admin do
resources :expenses, :only => [:edit, :update, :destroy]
end
所以你仍然使用expenses_path()
作为索引,expense_path(foo)
作为show。但是,管理页面上的表单会发布到admin_expense_path(@expense)
。
答案 1 :(得分:2)
如果您想添加另一个控制器,我建议在模块中使用公共代码并在每个控制器中导入它们。每个控制器都有足够的过滤器来检查是否有足够的权利。
但我更喜欢有一个控制器和一组视图,因为我认为它避免了代码重复和/或混淆。将用户作为本地变量传递给视图,并在需要确定form_for的URL或是否隐藏或显示某个部分时检查管理员权限。
如果视图差异很大,请检查控制器中的管理员权限,并呈现用户视图或管理视图。
您甚至可以为视图的管理部分创建一个特殊的部分,并决定是否在视图中呈现它,在params中发送相应的数据。
答案 2 :(得分:1)
您可以使用Devise gem进行身份验证。 您可以为应用程序的管理部分创建一些“命名空间”。
我的意见是,创建另一个控制器取决于管理员将访问的视图和操作数量。
关于form_for操作的疑问,它将由您在form_for params中配置的路由和路径进行管理。