2012-03-15 57 views
3

[這是一個後續問題「How I can modularize Rails model?」]如何使用rails在app/modules中組織名稱空間?

反正組織在app/models目錄的Rails的課? 我是否必須爲所有類使用單個頂級命名空間?

最初的動機是,我想將不從ActiveRecord::Base繼承的業務邏輯類放入app/models目錄。在這個網站上搜索可以找到很多答案,推薦將商業邏輯類放在app/models目錄中。我發佈了a different question,並得到了建議,可以將這些類放入lib目錄。

現在我很好奇。我想將這些類放入apps/models目錄中由其他人推薦的不同名稱空間和目錄中。可能嗎?

其實,我嘗試這一點,但在我看來,這就是軌道預計不會。如果我創建了這樣的類(如some_mod_name/class_in_mod.rb中的SomeModName :: ClassInMod),它不會被加載。另外,我在模塊中定義了常量。由於他們沒有加載,我不能使用它們。其實,rspec工作沒有問題,但與rails server,類不加載。我相信它與自動加載問題有關。

除了上面提到的類之外,從ActiveRecord::Base繼承的類可以放入module中的某些名稱空間中。我很好奇這個工作是否正常。

因此,換句話說,這樣的問題:我可以讓軌道高興通過配置這些文件被加載,或不在軌道設計的方式?

回答

6

是的,你可以一個模塊中定義一個ActiveRecord類。簡單的方法是使用發生器:

./script/rails generate model logic/phase_logic 
./script/rails generate model logic/evaluation_logic 

請注意,Rails將另外創建一個帶有模塊定義的文件。在這種情況下:

# app/models/logic.rb 
module Logic 
    ... 
end 

# app/models/logic/phase_logics.rb 
class Logic::PhaseLogic < ActiveRecord::Base 
    ... 
end 

# app/models/logic/evaluation_logics.rb 
class Logic::EvaluationLogic < ActiveRecord::Base 
    ... 
end 

您與模塊中定義的常量問題是由以下事實造成的,你定義的「包裝」只圍繞一個模型定義模塊中的常量,從兩個已創建。 尤其是對誰在編譯語言強背景的人 - - 理解紅寶石(和Rails)的一個非常重要的部分是要記住,沒有編譯階段,所以有些類的定義被讀取,只有當執行使用特定的類。有時候一週後應用程序服務器啓動並服務了數千個請求。

因此,正如我在previous question的回答說,自動加載的問題是,有時常量的定義這是試圖使用它們的定義後,讀。順序是隨機的 - 如果第一個使用的對象碰巧是EvaluationLogic,那麼就會出現錯誤。它是第一個碰巧是PhaseLogic的對象,一切都很好。

現在,當你有一個模塊本身文件,並在該文件app/models/logic.rb),自動加載將能夠找到並執行定義定義的任何類開始使用之前常量。我希望一切都會好起來的。

+0

謝謝。我仍然想知道爲什麼加載順序與我預期的不同(你說這是隨機的,我認爲必須有一個觸發器會導致實際的負載),但將常數放在'app/models中顯然是個好主意/ logic.rb'現在會嘗試改變這種方式。 – shigeya 2012-03-16 00:10:31

+0

經過測試。甚至沒有必要成爲'ActiveRecord :: Base'的子類在'module Logic'中放置所有常量,將它放在'app/models/logic.rb'中解決了我的問題。非常感謝你。 – shigeya 2012-03-16 00:47:20

+1

實際負載由第一個執行的代碼行觸發,其中使用了該類。當ruby嘗試執行類似'if if; EvaluationLogic.new;否則PhaseLogic.new; end'和PhaseLogic尚未定義,然後(簡化一點)自動加載機制找到文件'phase_logic.rb',執行它,並嘗試再次執行該行代碼。還有其他方式像STI。 – Arsen7 2012-03-16 08:32:29