簡體   English   中英

具有動態定義類的Rails單表繼承

[英]Rails Single Table Inheritance with dynamically defined classes

在使用Rails STI(單表繼承)時,我定義了一個名為Poi(興趣點)的模型。

我們應用的要求要求必須在Admin :: Categories視圖(其中具有class_name字符串輸入字段)中創建Poi的子類(例如,餐廳,俱樂部等),以便Admin應該能夠在以下位置創建新的子類:任何時候都無需程序員打開帶有空(無用)子類的新ruby文件並重新部署應用程序。

同時,如果將來我們要為Poi的子類指定不同的行為(實例/類方法),我們可以僅創建該ruby文件,但這應該是一個選擇,而不是強制性的。 對於該子類具有不同字段的不同形式也是如此:我們只需要在該子類中設置一個partial_name_for_form實例方法,該方法將返回帶有部分名稱的字符串,並且視圖將相應地呈現該方法。 如果未找到,則呈現默認Poi視圖。

由於如果您嘗試實例化一個新的具有'type'屬性的Poi對象並與Poi的子類不匹配(因此必須預先定義該子類),Rails會引發錯誤,因此我們提出了以下解決方案來動態創建Poi基於class_name的子類:

  1. 模型類別中的after_create鈎子使用此代碼立即定義新類: Object.const_set(category.class_name, Class.new(Poi))

  2. 在模型Poi文件中的require_dependency調用(因為它位於自動加載路徑中)要求為子類使用ruby文件,我們最終創建了硬編碼的子類(僅當文件存在時):

Category.all.each do |category|

require_dependency category.class_name.underscore if File.exist (File.join("app","models","pois","#{category.class_name.underscore}.rb"))

end

  1. 使用#1中的相同代碼定義所有剩余類的初始化程序(“剩余”是指其他子類,它們仍然沒有自己的ruby文件來定義它們),但檢查if Object.const_defined? category.class_name 首先是if Object.const_defined? category.class_name (因為不需要重新定義require_dependency定義的名稱)。

即使如此艱巨的復雜性,我們也幾乎一開始就對STI感到后悔,因為它可以在開發中很好地工作。

但是在生產環境中,創建提供class_name的新類別后,將無法定義Class,因為嘗試用該子類創建新的Poi時會引發錯誤uninitialized constant

我在生產環境的Rails控制台中確認after_create掛鈎可以正常工作,因為在那里已定義了類。 我的瘋狂猜測是,因為我們使用獨角獸,所以此錯誤可能與應用程序代碼的派生有關,但我不知道如何進行。

10.5 require_dependency和初始化程序

可以考慮在初始化程序中進行一些require_dependency調用,以確保預先加載了某些常量,例如,嘗試用STI解決問題。

問題是,在開發模式下,如果文件系統中有任何相關更改,則會擦除自動加載的常量。 如果發生這種情況,那么我們處於初始化程序要避免的相同情況!

來自http://guides.rubyonrails.org/autoloading_and_reloading_constants.html 從我在這里閱讀的內容來看, initializer require_dependency似乎在環境之間的工作方式有所不同。 我在這里找到了類似的問題-看看是否有幫助。

由於模型損壞,我將避免創建動態常量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM