我正在开发一个应用程序。基本的东西,用户注册(与相关组织)。
最初我从一个简单的控制器开始 -
# Need to check if organization exists already; deny user creation if it does
if @organization.save
@user.save
redirect_to user_dashboard_path...
我很快发现自己陷入了回调汤:
验证组织后,我们保存用户。创建组织后,我创建了另外两个模型,EmailTemplate 和 PassTemplate(一个组织 has_one :email_template,has_one :pass_template)
after_create :init_company, :init_email_template, :init_pass_template, :init_form
这些回调中的每一个通常都会调用模型上的方法,例如:
def init_email_template
self.email_template.create_with_defaults
end
最初我认为这很聪明——在幕后做了这么多,但我一直在阅读 Steve McConnell 的 Code Complete,觉得这一点都不简单。如果我不知道已经发生了什么,那么没有任何迹象表明任何时候创建组织都会创建 3 个关联对象(其中一些对象反过来会初始化子对象)。
这似乎是一种糟糕的编程习惯,因为它混淆了正在发生的事情。
我考虑将所有这些初始化移动到控制器,因为一个组织只创建一次:
class OrganizationsController < AC
...
def create
if @organization.save
@organization.create_user
@organization.create_email_template
@organization.create_pass_template
end
这似乎是更简洁的代码,并且更容易遵循。
问题 1 *是否有更好的解决方案或最佳实践来处理在创建中心对象时创建我不知道的关联对象?*
旁注 - 我将不得不重写一堆假设关联是通过回调自动创建的测试 - 如果它更好,更容易理解代码,我可以接受。
问题 2 **after_save 回调的类似情况如何?**
我有一个客户模型,它在创建后检查它是否有关联的 user_account,如果没有,则创建它。一旦我们创建了 user_account,它还会为该 user_account 创建一个 Tag 模型
class Customer < AR
after_create :find_or_create_user_account
def find_or_create_user_account
if !self.user_account_exists?
#create the user
end
Tag.create(:user_id => self.user_account.id)
end
end
有点简化,但我相信这不是特别好的编程。一方面,我将逻辑放在第三个模型中创建两个不同的模型。似乎马虎又一次分离逻辑的原则。其次,方法名称并没有完全描述它在做什么。也许 find_or_create_user_account_and_tag 会是一个更好的名称,但它也违背了让方法只做一件事的原则——保持简单。
在阅读了观察者和服务之后,我的世界陷入了一个循环。
几个月前,我把所有东西都放在了控制器中。不可能很好地测试(这很好,因为我没有测试)。现在我的控制器很瘦,但我的模型很肥胖,而且我认为不健康(不清楚,不明显,几个月后另一个程序员/我自己更难阅读和破译)。
总的来说,我只是想知道是否有一些关于逻辑分离、避免回调汤以及不同类型代码的好指南、信息或最佳实践