我有一個看起來像這樣的父類:
class Record
attr_accessor :id, :url, :votes, :title, :first_name, :last_name, :selfdb
def initialize(args = {})
args.each { |name, value| instance_variable_set("@#{name}", value) }
@selfdb = "#{self.class.name.downcase}s"
end
def self.find(id)
DB.results_as_hash = true
hasharray = DB.execute("SELECT * FROM ? WHERE id = ?", @selfdb, id)
hasharray.empty? ? nil : new(hasharray[0].transform_keys(&:to_sym))
end
end
Record 的每個子類都有一個匹配的資料庫表,其名稱為“#{name of the class}s”,因此“Post”類連接到名為“posts”的表。
我的目標是讓 self.find(id) 為這個班級的任何孩子作業。我嘗試的解決方案是將類的名稱保存到末尾帶有“s”的字串變數中(例如,類 Post ->“posts”),以匹配資料庫的名稱,正如我嘗試的那樣實體變數@selfdb,但這不起作用。
在子類上呼叫 @selfdb 確認它確實為不同的類正確創建了字串,但是運行 sqlite 并將其作為表名插入只會回傳 nil。
這可能是一種非常迂回的方式,歡迎提出任何建議。我還在學習,這只是一個訓練營的任務。
編輯:我意識到我犯了一個錯誤:因為 self.find(id) 是一個類方法,它不能使用實體變數。但是,當我將類方法更改為這樣作業時:
def self.find(id)
selfdb = "#{self.name.downcase}s"
DB.results_as_hash = true
hasharray = DB.execute("SELECT * FROM ? WHERE id = ?", selfdb, id)
hasharray.empty? ? nil : new(hasharray[0].transform_keys(&:to_sym))
end
...它仍然沒有正確插入到 sqlite 字串中。
uj5u.com熱心網友回復:
您@selfdb
在初始化方法中定義,這意味著它僅在實體級別可用。但是您的self.find
方法是類方法,因此@selfdb
在類級別上未定義。
我建議添加一個回傳表名的類方法,如下所示
def self.table_name
"#{name.downcase}s"
end
然后您可以find
像這樣在類方法中使用它
def self.find(id)
# ...
hasharray = DB.execute("SELECT * FROM ? WHERE id = ?", table_name, id)
# ...
end
并且在實體方法(例如保存記錄)中,您需要使用self.class.table_name
或者您可以添加一個委托人將table_name
實體方法呼叫轉發給類方法:
extend Forwardable
def_delegators :"self.class", :table_name
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/470332.html