Rails路由/控制器/目录结构设计问题

时间:2011-05-27 23:05:01

标签: ruby-on-rails ruby controller routes

我有一个设计问题,我希望得到一个深思熟虑的回应。

假设你有一个简单的应用程序(例如),它有一个User,Company和Theme模型。公司has_one主题和has_many用户。

管理员(用户)可以完全管理公司,用户和主题 - 整个REST堆栈,以及其他一些操作。管理员需要对其他3个资源执行其他用户角色无法执行的操作。

我们也有公司角色。这个角色可以编辑自己的公司,也可以从admin-user添加的主题中选择一个主题作为不错的默认值,或者他们可以自己制作主题。

公司还可以添加/编辑/删除用户,但仅限于他们的公司。这些页面将有不同的视图,它们会与管理员有不同的行为 - 有些重叠,但有些事情会受到限制而有些事情会被添加。

现在,我们在这里有一些非平凡的设计选择,我想知道最佳实践是什么。

第1部分

在Rails中,为管理员提供resources :users, :companies, :themes,为公司用户设置resource :company, :theme, :users是有意义的。

但是,当然,我们在这里遇到了一些命名冲突 - 无论是单数还是复数 - 所以我们可能想尝试像resource :my_company, :my_theme, :my_users之类的东西来分开它们?或者有更好的解决方案吗?

此外,主题只是公司的一个组成部分,所以也许我们想要嵌套它们?

:resource :my_company do
  :resource :theme
  :resources :users
end

这没关系,但是我们指的是哪个UsersController可能会让人感到困惑......不是吗?这真的很粘,我很想知道如何处理这个问题。你有1个控制器,还是2个?你叫他们什么名字?

所以这就是一个例子:

http://myapp.com/my_company/theme/edit
http://myapp.com/my_company/users/1/delete

公司用户也可能希望通过ajax获取主题列表,因此调用它们是正确的:

http://myapp.com/themes.json

这是如何处理这种情况,还是有更好的方法?

第2部分

此外,您的目录结构应该是什么样的?您是否应该按用户角色分隔控制器?

/app/controllers/admin/companies_controller.rb
/app/controllers/admin/themes_controller.rb
/app/controllers/admin/users_controller.rb
/app/controllers/company/my_company_controller.rb
/app/controllers/company/theme_controller.rb
/app/controllers/company/users_controller.rb

或者有更好的方法来解决这个问题吗?

似乎很奇怪users_controller重复2次,主题和主题之间存在细微差别。

我真的很感激对此做出深思熟虑的回应。谢谢!

1 个答案:

答案 0 :(得分:1)

我感谢您组织代码库的愿望,因为我不断地说服自己不要采用我的默认冲动来嵌套资源或命名空间模型。由于这个问题没有正确的答案,我只会提供我用来说服自己不要的理由。

  • 资源生活在一个地方。 User.find(1)应该有一个定位器(URL),我喜欢称之为user_path。我喜欢称之为user_path,因为我自己称之为admin_company_user_path([@ company,@ user]),每次我写这篇文章都会让我感到不适。
  • 对于不同的情况,该资源可能以不同的方式呈现自己,例如,如果请求者是XHR或者表示他们更喜欢德语到英语。为什么表示用户是管理员的标题有何不同?
  • 如果我能让它看起来像rails / README中最简单的例子,那我不应该吗?

此时我会承认并最终:

/app/controllers/companies_controller.rb
/app/controllers/users_controller.rb
/app/controllers/themes_controller.rb

我的routes.rb会有:

resources :users
resources :companies
resources :themes

我还应该解决如何处理让你想要首先将它们分开的事情 - 每个角色的不同视图。在我理想的情况下,我的决定会导致themes/_form.haml看起来像:

= form.input :title if user_can_change_title?
= form.input :theme if user_can_change_theme?

其余的差异将在CSS中处理,可能还有每个角色的样式表。

在不太理想的情况下,我可能会使用:

= render :partial => "#{current_user.role}_form"