Rails 请教下一般这种情况下大家会如何组织代码

winterwhisper · 2015年09月02日 · 最后由 wuwx 回复于 2015年09月02日 · 2019 次阅读

假设系统有三种角色的用户(甚至更多),分别是 Foo、Bar、Baz,系统有 Post 模型,三种角色都要对 Post 数据进行 CRUD 处理,相同动作(例如 index)相互之间展示的样式也不同

我能想到的组织代码的方法有两种

第一种,创建一个posts_controller如下

# posts_controller.rb
# ...
def index
  if is_foo?
    get_posts_for_foo
    render foo_posts
  elsif is_bar?
    get_posts_for_bar
    render bar_posts
  elsif is_baz?
    get_posts_for_baz
    render baz_posts
  end
end
# ...

第二种,如下树形结构为每个角色创建单独的posts_controller.rb,然后再在其对应的 controller 中维护单独的逻辑

controllers
  |
  foo
    |
    posts_controller.rb
  |
  bar
    |
    posts_controller.rb
  |
  baz
    |
    posts_controller.rb

第一种方法,逻辑一旦复杂,角色一多的话,即使把该封装的语句封装成方法,action 的代码也会越来越多;第二种方法又会出现很多 DRY

所以想请教下大家,觉得这两种方法哪种更好,还是有更好的方法?

第 2 种。

#1 楼 @rei wow,回的好快。那如果是第二种的话,你是怎么解决 DRY 的呢?还是说允许一定的 DRY?

#3 楼 @kikyous 这个就是第一种方法了。

DRY 的话,可以用父类解决,或者 module。问题是你怎么定义路由?怎么根据当前用户的角色,指向相应的 conroller#action?建议用 pundit 或者 cancan 这类 authorization gem,来区分不用角色的用户对 posts 的 read 权限

#5 楼 @leomayleomay 路由好说,cancan/pundit 跟我提的问题没有太大关系,这类 gem 重在 authorization,fetch records 对于这类 gem 是可有可无的,而我的问题是如何在逻辑复杂的情况下较为优雅的 fetch records。

我现在就是用 cancan,原来是用第一种方法组织代码,随着业务逻辑越来越复杂,慢慢的在重构为第二种,但进行了一段时间以后又觉得存在一些 DRY,可能会造成后期维护的不便,所以想问问大家一般是如何做的。

#2 楼 @winterwhisper 页面不同,授权不同,逻辑不同,只有模型是相同的,我觉得这就是两个功能。MVC 模型和控制器不用一一对应。

觉得 DRY 的话,可以自己抽象出行为,统一封装。显式的 if else 肯定是不怎么优雅,可读性也比较差。

pundit 做的事情和 cancan 侧重还是有所不同的 你可以看看 pundit 的文档:)Scopes 那部分就可以改变你对他的看法

需要 登录 后方可回复, 如果你还没有账号请 注册新账号