Ruby on rails Rails回调、观察者、模型以及方法和逻辑的放置位置

Ruby on rails Rails回调、观察者、模型以及方法和逻辑的放置位置,ruby-on-rails,callback,models,observers,Ruby On Rails,Callback,Models,Observers,我正在工作中开发一个应用程序。基本资料,用户注册(与相关组织) 最初我用一个简单的控制器开始- # Need to check if organization exists already; deny user creation if it does if @organization.save @user.save redirect_to user_dashboard_path... 我很快发现自己陷入了困境: 验证组织后,我们保存用户。 创建组织时,我创建了另外两个模型,Email

我正在工作中开发一个应用程序。基本资料,用户注册(与相关组织)

最初我用一个简单的控制器开始-

# 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(一个组织有一个:email\u template,有一个:pass\u template)

这些回调通常都会调用模型上的方法,类似于:

def init_email_template
  self.email_template.create_with_defaults
end
起初我认为这很聪明——在幕后做了这么多,但我一直在阅读史蒂夫·麦康奈尔的《代码全集》,觉得这一点都不简单。如果我不知道已经发生了什么,那么就没有任何迹象表明任何时候创建一个组织都会创建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\u帐户,它还会为该user\u帐户创建一个标记模型

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
class客户self.user\u account.id)
结束
结束
有点简化,但我认为它不是特别好的编程。首先,我用逻辑在第三个模型中创建两个不同的模型。似乎马虎又是逻辑分离的原则。第二,方法名称不能完全描述它在做什么。也许find_或create_user_account_和_tag会是一个更好的名称,但它也违背了让方法做一件事的原则——保持简单

在阅读了有关观察员和服务的内容后,我的世界陷入了一个小圈子

几个月前,我把所有东西都放在控制器里。这是不可能测试好(这是好的,因为我没有测试)。现在我有了瘦削的控制器,但我的模型太胖了,而且我认为不健康(不清楚,不明显,几个月后另一个程序员/我自己更难阅读和理解)

总的来说,我只是想知道是否有一些关于逻辑分离、避免回调汤以及不同类型代码的好指南、信息或最佳实践为什么没有以下内容

after_create :init_associated_objects

def init_associated_objects
  init_company
  init_email_template
  init_pass_template
  init_form
end
我对“一个方法应该做一件事”的解释并不严格,我通常有一个调用其他方法的方法(与上面的方法非常相似)。归根结底,这是一种分而治之的策略

有时我创建实用程序POROs(普通的老ruby对象),因为使用AR模型没有意义,但一组功能是类的责任。例如,报告不是AR支持的模型,但如果只实例化一次需要调用多个模型的报告(其中报告周期的开始和结束是实例变量),则更容易实现

我遵循的一条经验法则是:如果我在整个MVC堆栈(例如Rails控制台)之外实例化模型,我期望发生的事情应该留在模型内部


我不主张最佳实践,但到目前为止,这些都对我有效。我相信其他人对此会有更好的想法。

谢谢你的回答。我正在做一些研究,翻阅书籍,查看铁路公司,但这似乎是一个哲学问题和最佳实践问题的混合体。
after_create :init_associated_objects

def init_associated_objects
  init_company
  init_email_template
  init_pass_template
  init_form
end