使用rails generate model
,我创建了两个模特/桌子,警察和女警。他们是具有许多属性(年龄,现场时间,案例解决等)的官员名单。如果我想做一个计算,确定谁应该获得下一次促销到Sargent的传统方式在rails中做什么?
我想创建一个新类来处理这种情况,并隐藏所有复杂的计算(比较两个列表之间的属性)远离调用者。所以也许在一个控制器中,比如Captain,在我会做的方法下
class Captain < ApplicationController
def show
promotion = Promotion.new
@ideal_sargent = promotion.sargent(Policeman.find(:all),Policewoman.find(:all))
end
end
我在哪里创建此促销课程?我是否使用rails generate controller
来制作它?或者也许为它做一个宝石?或者甚至把它全部放在一个模型中(我听说瘦控制器胖模型)?
编辑: 也许this?如果是这样,如何在没有自动生成迁移文件的情况下创建模型?
答案 0 :(得分:1)
您将它与模型和控制器分离的一般想法是一个好的。虽然你把它与控制器,发生器和宝石混淆了一下......
您想要做的是:
使用它的界面基本上就像你已经描述过的那样:
# 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
。如果您按照这种方法使用松散耦合的普通红宝石对象,您将获得易于测试,可维护,灵活和可重用的代码。 =)
答案 1 :(得分:0)
为此,我不会创建两个表来建模数据。我会使用一个名为polices的表,并保留一个列为性别,另一个列为不同的警察和女警,以及不同级别。然后我会将推广功能作为警察模式中的一种类方法。
class Police < ActiveRecord::Base
def self.promote(param1, param2)
....
end
end
通过这种方式,您可以在升级函数中封装业务逻辑,调用者可以在不知道任何复杂计算的情况下调用它。 Police.promote(a,b)