2013-03-06 57 views
0

我正在開發應用程序。基本的東西,用戶註冊(與相關組織)。Rails回調,觀察者,模型以及放置方法和邏輯的位置

起初,我開始了與一個簡單的控制器 -

# 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 

最初我覺得這很聰明 - 在幕後做了很多事情,但我一直在閱讀史蒂夫麥康奈爾的代碼完整版,感覺這並不簡單。如果我不知道已經發生了什麼,沒有任何暗示說組織創建時會創建3個關聯對象(並且其中一些對象又會初始化子對象)。

這似乎是一個糟糕的編程習慣,因爲它混淆了正在發生的事情。

我想過將所有這些initalizations到控制器,作爲一個組織只會被創建一次:

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

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會是一個更好的名字,但它也違背了讓方法做一件事的原則 - 保持簡單。

在閱讀了關於觀察者和服務之後,我的世界被拋向了一個循環。

幾個月前,我把所有東西放在控制器中。這是不可能的(這沒什麼問題,因爲我沒有測試)。現在我有了一個很瘦的控制器,但是我的模型很肥胖,而且我覺得不健康(不清楚,不明顯,很難在幾個月內爲其他程序員/我解讀和解讀)。

總的來說,我只是想知道如果有一些很好的指南,信息,或邏輯上分離的最佳實踐,避免回調湯,哪裏不同種類的代碼

回答

1

爲什麼不能下?

after_create :init_associated_objects 

def init_associated_objects 
    init_company 
    init_email_template 
    init_pass_template 
    init_form 
end 

我與解釋「的方法應該做的一件事」是不是嚴格,我通常有一個調用其他方法(就像上面的一個)的方法。在一天結束時,這是一個分而治之的策略。

有時我創建實用程序PORO(普通老紅寶石對象),當它沒有意義的時候有一個AR模型,但是一組功能是類的責任。例如,報告不是AR支持的模型,但當需要調用多個模型的報告僅在報告期開始和結束是實例變量的情況下僅實例化一次時,報告就更容易了。

我遵循的經驗法則是:如果我在整個MVC堆棧之外實例化模型(例如Rails控制檯),那麼我期望發生的事情應該留在模型中。

我沒有聲稱最佳做法,但迄今爲止這些方法都適用於我。我相信其他人會對此有更好的想法。

+0

感謝您的回答。我正在研究一下,查看書籍並查看railscasts,但這似乎是哲學問題和最佳實踐之間的混合。 – Squadrons 2013-03-06 15:51:09