1

使用rails generate model,我创建了两个模型/表格,警察和女警察。它们是具有许多属性(年龄、在该领域的时间、已解决的案件等)的官员列表。如果我想做一个计算来确定谁应该获得下一次晋升到 Sargent 的机会,那么在 Rails 中做这件事的传统方法是什么?

我想创建一个新类来处理这种情况,并将所有复杂的计算(比较两个列表之间的属性)隐藏在调用者之外。所以也许在控制器中,队长说,在方法显示下我会做

class Captain < ApplicationController
  def show
    promotion = Promotion.new
    @ideal_sargent = promotion.sargent(Policeman.find(:all),Policewoman.find(:all))
  end
end

我在哪里创建这个促销类?我rails generate controller用来做吗?或者也许为它做一个宝石?或者甚至把它全部放在一个模型中(我听说瘦控制器胖模型)?

编辑:也许这个?如果是这样,如何在不自动生成迁移文件的情况下创建模型?

4

2 回答 2

1

您将其与模型和控制器分离的一般想法是一个很好的想法。尽管您将它与控制器、生成器和宝石有点混淆......

你想做的是:

  • 引入一个服务对象,它是普通的 ruby​​ 对象
  • 将计算促销顺序的逻辑放入其中
  • 让它与控制器完全解耦并松散耦合到警察模型

使用它的界面基本上就像您已经描述的那样:

# prepare some officers to choose from
officers = [PoliceWoman.find(1)] + PoliceMan.all
# returns the first ranking officer for promotion
to_be_promoted = SargentPromotionService.new.find_top_candidate(*officers)

这种服务模式应该放在哪里?我想它包含特定于应用程序的逻辑,在应用程序之外并没有真正有用。因此,我们将其放在 app 文件夹中。但是在应用程序的哪里?

一个好的做法是设置app/domain文件夹。您可以在那里放置所有应用程序特定的域模型(服务、策略、值对象等)。设置此文件夹所需要做的就是将其添加到以下目录中的自动加载路径中 config/application.rb

config.autoload_paths += %W(#{config.root}/app/domain)

这样,您就可以清楚地分离 Rails 模型(处理持久性)和域模型 - 您应该将大部分应用程序特定代码放置在其中。如果您的应用程序非常简单且很小,您也可以跳过该app/domain文件夹并使用app/models. 如果您遵循使用松散耦合的普通 ruby​​ 对象的方法,您将获得易于测试、可维护、灵活和可重用的代码。=)

于 2013-08-18T17:46:28.153 回答
0

为此,我不会创建两个表来对数据进行建模。我会使用一个名为polices的表,并保留一列作为性别,另一列作为等级来区分警察和女警,以及不同的等级。然后我会将提升功能作为类方法放入警察模式中。

class Police < ActiveRecord::Base
  def self.promote(param1, param2)
     ....
  end
end

通过这种方式,您可以将业务逻辑封装在promote函数中,调用者可以在不知道其中任何复杂计算的情况下调用它。Police.promote(a,b)

于 2013-08-18T16:01:32.487 回答