基于 class 名称的 Ruby sqlite 查询中的动态 table 名称
Dynamic table name in Ruby sqlite query based on class name
我有一个 parent class 看起来像这样:
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
记录的每个 child class 都有一个匹配的数据库 table 其名称是“#{name of the class}”,因此 class “Post”连接到名为“posts”的 table。
我的目标是让 self.find(id) 处理此 class 的任何 children。我尝试的解决方案是将 class' 名称保存到末尾带有“s”的字符串变量中(例如 class Post -> “posts”),匹配数据库的名称,正如我在实例变量@selfdb 中尝试的那样,但这不起作用。
在 children classes 上调用 @selfdb 确认它确实为不同的 classes 正确创建了字符串,但是 运行 插入了它的 sqlite作为 table 名称只是 returns 零。
这可能是一种非常迂回的做法,欢迎任何建议。我还在学习,这只是训练营作业。
编辑:我意识到我犯了一个错误:因为 self.find(id) 是一个 class 方法,它不能使用实例变量。但是,当我将 class 方法更改为这样工作时:
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 字符串中。
您在初始化方法中定义了 @selfdb
,这意味着它仅在实例级别可用。但是您的 self.find
方法是 class 方法,因此 @selfdb
在 class 级别未定义。
我建议添加一个 class 方法,returns table 这样的名称
def self.table_name
"#{name.downcase}s"
end
然后您可以像这样在 find
class 方法中使用它
def self.find(id)
# ...
hasharray = DB.execute("SELECT * FROM ? WHERE id = ?", table_name, id)
# ...
end
并且在实例方法(例如保存记录)中,您需要使用 self.class.table_name
或者您可以添加委托人将 table_name
实例方法调用转发给 class方法:
extend Forwardable
def_delegators :"self.class", :table_name
我有一个 parent class 看起来像这样:
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
记录的每个 child class 都有一个匹配的数据库 table 其名称是“#{name of the class}”,因此 class “Post”连接到名为“posts”的 table。
我的目标是让 self.find(id) 处理此 class 的任何 children。我尝试的解决方案是将 class' 名称保存到末尾带有“s”的字符串变量中(例如 class Post -> “posts”),匹配数据库的名称,正如我在实例变量@selfdb 中尝试的那样,但这不起作用。
在 children classes 上调用 @selfdb 确认它确实为不同的 classes 正确创建了字符串,但是 运行 插入了它的 sqlite作为 table 名称只是 returns 零。
这可能是一种非常迂回的做法,欢迎任何建议。我还在学习,这只是训练营作业。
编辑:我意识到我犯了一个错误:因为 self.find(id) 是一个 class 方法,它不能使用实例变量。但是,当我将 class 方法更改为这样工作时:
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 字符串中。
您在初始化方法中定义了 @selfdb
,这意味着它仅在实例级别可用。但是您的 self.find
方法是 class 方法,因此 @selfdb
在 class 级别未定义。
我建议添加一个 class 方法,returns table 这样的名称
def self.table_name
"#{name.downcase}s"
end
然后您可以像这样在 find
class 方法中使用它
def self.find(id)
# ...
hasharray = DB.execute("SELECT * FROM ? WHERE id = ?", table_name, id)
# ...
end
并且在实例方法(例如保存记录)中,您需要使用 self.class.table_name
或者您可以添加委托人将 table_name
实例方法调用转发给 class方法:
extend Forwardable
def_delegators :"self.class", :table_name