胖模型,瘦控制器 - 但如果混合模型怎么办?

时间:2014-05-01 10:33:46

标签: ruby-on-rails oop

我正在构建一个Ruby on Rails 4.1应用程序,它具有以下模型,当您看到模型名称时应该有意义:

域名,团队,用户,会议等

现在,团队属于一个域,一个用户属于一个团队,会议也属于一个用户。域只是使用该软件的组织或公司。

创建管理员用户后,用户必须首先创建域,然后创建第一个团队,然后其他用户就可以注册。

正如您可能预料到的那样,在创建初始域和团队(在新的/创建团队和域控制器中完成)的过程中,我必须访问和更改所有三个中的引用。因此,例如,创建第一个域必须关联管理员用户,创建一个团队将涉及将其链接到用户,然后是父域。

所以,它们有点混乱,控制器需要访问多个模型。

我的问题是,这个逻辑属于哪里?根据瘦控制器的精神,您通常会将其移植到模型中,但它涉及多个模型。这是新的Rails 4问题变得有用还是我应该把它放在控制器中?

我对铁杆比较陌生,所以如果你愿意回复,请记住这一点 - 谢谢!

2 个答案:

答案 0 :(得分:3)

嵌套资源

class Domain
  has_many :teams
end

class Team
  has_many :users
  belongs_to :domain
end

class User
  has_many :meetings
  belongs_to :team
end

class Meeting
  belongs_to :user
end

然后在你的控制器中:

class TeamsController < ApplicationController

  def new
    @team = Team.new
  end

  def create
    @domain = Domain.find(params[:domain_id])
    @team   = @domain.teams.build(params[:team])
    @team.save

    respond_with @team
  end

end

这就是我们所谓的“嵌套”控制器,位于routes.rb文件中:

resources :domain do
  resources :team
end

网址将如下所示:

/domains/:domain_id/teams
/domains/:domain_id/teams/:team_id

同样的逻辑适用于其他型号。这应该为您提供构建应用程序的起点。

以下一行

@domain.teams.build(params[:team])

自动将域链接到为您设置引用(id)的团队。

但是你不应该根据rails guide进行深度嵌套,这样建筑师设计模式可以派上用场。

构建器设计模式

然而,如果事情开始变得混乱,我建议使用专用的ruby类来“构建”你的对象及其关系。我们通常将这些类称为“构建器”:

class TeamBuilder

  attr_reader :domain, :params

  def initialize(domain, params = {})
    @domain = domain
    @params = params
  end

  def build
    domain.teams.build(params)
  end

end

这里又做了一个非常简单的任务。例如,对于用户和会议:

class UserBuilder

  attr_reader :team, :params

  def initialize(team, params = {})
    @team = team
    @params = params
  end

  def build
    team.users.build(params).tap do |user|
      user.foo = 'foo'
      user.meetings.build(...)
      user.meetings << MeetingBuilder.new(user, { ... })
    end
  end

end

class MeetingBuilder
  # ...
end

我们使用MeetingBuilder中的UserBuilder来构建会议。

用法:

user = UserBuilder.new(team, { ... }).build
user.save

答案 1 :(得分:1)

理想情况下,模型不应该关心甚至不了解其他类。因此在模型和控制器之间,这种逻辑肯定属于控制器。

我可能会选择第三课,照顾那些混乱的东西,例如DomainFactory。这只是一个普通的旧红宝石对象(poro),没有活动记录或任何东西,其唯一目的是创建域名。

提示是阅读松散耦合单一责任