2016-03-18 115 views
0

我需要從數據庫的各個表中檢索列名,以便爲這些表對應的類動態設置attr_accessor方法。這需要從父類完成。根據數據庫/表列動態設置子類的屬性

class Child < Parent 
    attr_accessor :id, :column_a, :etc. 
end 

Parent#column_names方法確實工作,我打算給它的方式。它爲任何由子類指定的表返回一個列名稱數組。然而,它從#inherited方法調用時不返回任何列名稱。當我嘗試爲子類設置attr_accessor方法時,將返回一個空數組。

我在嘗試動態設置這些attr_accessor方法,使用#class_eval將它們插入到子類中。這是對#column_names的調用發生的位置,以及返回空數組的位置。

module SomeModule 
    class Parent 

    def self.inherited(child) 
     child.class_eval do 
     self.column_names.each { |att| attr_accessor att.to_sym } 
     end 
    end 

    #... 

    def self.table_name 
     "#{self.to_s.downcase}s" 
    end 

    def self.column_names 
     sql = "#... WHERE table_name = '#{table_name}';" 

     columns = [] 
     exec(sql).each do |col-data| 
     columns << col_data["column_name"] 
     end 

     columns 
    end 

    def self.exec(sql, args=[]) 
     #... 
    end 

    #... 

    end 
end 

我的理解是,這本質上應該建立一個呼叫從ChildChild.column_names其中,我認爲它。我只是不知道爲什麼返回數組沒有填充。我已經嘗試過移動column_names方法,但行爲的唯一變化取決於它的放置位置,它是子類的NoMethodError

+0

你能舉個模塊的使用例子嗎? –

+0

@max pleaner該模塊基本上是一個ORM - 只是ActiveRecord的超輕量級版本。 –

回答

0

不幸的是,inherited上的文檔不是很詳細,但我看到了什麼問題 - 這是class_eval塊中self的值。

的NoMethodError是因爲column_names方法並不在子類中定義,和自指class_eval塊內的子類,

有一個簡單的解決,這是在class_eval之前設置self到可變塊。

希望在下面的例子中可以清楚看到,我已經測試過並且能夠正常工作。請注意,與代碼唯一的真正區別在於inherited方法。所有其他的東西都在測試它,因爲我不能真正運行你的代碼。

require 'byebug' 

class ParentClass 
    def self.inherited(child) 
    parent_class = self # Store value of self in a variable 
         # because it will change in class_eval 
         # Then call column_names on this variable 
    child.class_eval do 
     parent_class.column_names.each { |attr| attr_accessor attr.to_sym } 
    end 
    end 
    def self.column_names 
    [:foo, :bar] 
    end 
end 

class ChildClass < ParentClass 
    def initialize 
    end 
end 

child = ChildClass.new 
child.foo = "bar" 
puts child.foo 
# => "bar" 

這個問題在JavaScript中更常見,它具有更嚴格的隔離範圍級別。換句話說,self的值更改頻率更高。

+0

我給了這個鏡頭,但沒有骰子。它可以工作,這意味着它可以成功地調用正確的column_names方法,並且如果返回數組是手動填充的,那很好。但是從'inherited'方法中調用它仍然會使數組爲空。如果我移動'#column_name'方法,我只會得到'NoMethodError'。我已經改變了我的方法,並可以在數組填充並運行之後調用attr_setter方法,但對於爲什麼直接調用#column_names使其爲空,我仍然很神祕。 –

+0

也許嘗試檢查table_name返回正確的值?你應該使用一個調試器,並逐步通過你的列名方法。 –

相關問題