我正在用ruby制作一个模拟orm,存储“论坛”数据。
我有以下表格: users (id, fname, lname)
,和 questions (id, title, body, author_id)
. a_user.create
以及 a_question.create
大致相同:
# aUser#create
def create
# adds a user to the database
raise "user already in db" if self.id
begin
QuestionsDB.instance.execute(<<-SQL, self.fname, self.lname)
insert into users (fname, lname)
values (?, ?);
SQL
self.id = QuestionsDB.instance.last_insert_row_id
return self.id
rescue => exception
raise "failed to create user: #{exception}"
end
end
# aQuestion#create
def create
# add question to db
raise "already asked" if self.id
raise "title already exists" unless Question.find_by_title(self.title).empty?
begin
QuestionsDB.instance.execute(<<-SQL, self.title, self.body, self.author_id)
insert into questions (title, body, author_id)
values (?, ?, ?);
SQL
self.id = QuestionsDB.instance.last_insert_row_id
return self.id
rescue => exception
raise "failed to create question: #{exception}"
end
end
我正在写另一个类modelbase,我想说
ModelBase.create(aUser)
或
aMB = ModelBase.new(~characteristics_from_user_or_question_object~)
aMB.create
. 用户和问题只有在添加到数据库后才具有id。
两个creates的sql基本上都接受所有预创建的属性,并将它们放到相应表中的所有列中,不包括第一个id列。有没有一种方法可以概括“将此对象的所有属性插入指定的值表('all but the first')”的指令?
1条答案
按热度按时间rfbsl7qr1#
我们可以用一些ruby元编程来实现一个非常基本的orm,但是请记住,出于安全原因,在生产中不应该使用这个。实现一个完全工作的orm是一项艰巨的工作。
我们可以用
instance_variables
.请注意
@
一开始我们可以用一个简单的gsub
. 我们还需要拒绝@id
属性。最后与instance_variable_get
我们可以得到实际值。有了这些信息,我们现在可以实现
columns
以及values
方法。现在我们需要计算表名,我们可以从具有
self.class.name
. 如果我们把所有的东西都放在一起,会像这样:如开头所述,请仅将此作为练习的一部分使用,因为它不安全(sql注入)、存在错误(例如表名的多元化和值的转义)等。
另一种实现方法是,首先查询数据库表具有哪些列名,然后从中派生类属性。比如activerecord就是这样做的。