我正在尝试创建一个ORM来包装DynamoDB(NoSQL)查询。此ORM由存储在DynamoDB中的模型继承。实际上ActiveRecord
的风格:
class User < ActiveRecord::Base; end
变为
class User < DynamOrm; end
require 'aws-sdk'
class DynamOrm
CLIENT = Aws::DynamoDB::Client.new
def find(key, options = {})
query = CLIENT.get_item({
table_name: 'my_table',
key: key,
consistent_read: true,
return_consumed_capacity: "INDEXES"
}.merge(options))
if query.item.nil?
raise 'NO ITEM FOUND'
else
self.new(query.item)
end
end
end
这样做了,我不用担心通过我的ORM查询我的DynamoDB数据库。
User.find({ id: 52 }) # => #<User:0x007fc5bc8a64a0>
它返回我User
的一个实例。我想链接一个名为filter
的方法。像这样:
User.find({ id: 52 }).filter({ gender: 'male' })
为此,我不是在find
方法中返回实例,而是将实例存储在变量中,然后返回Class
。在我的filter
类方法中,我返回User
实例。
class DynamOrm
# [...]
def self.find(key, options = {})
# [...]
if query.item.nil?
raise 'NO ITEM FOUND'
else
@result = self.new(query.item)
self
end
end
def self.filter(filters)
#
# APPLY MY FILTERS ON `@result`
#
return @result
end
end
我有时不得不使用filter
,但有时不会。与ActiveRecord
一样,有时我必须使用order
或limit
,但并非总是如此。所以,当我只想使用find
时,它将返回一个类而不是一个实例。一个简单的User.find({ id: 1 })
将返回班级User
。
我如何重现AR方式,即直接在我的模型上调用ORM(@user = User.find()
)并获取此模型@user.inspect # => #<User:0x007fc5bc8a64a0 @id=1, @gender="male" >
的实例?
答案 0 :(得分:0)
为了能够链接你的查询函数,比如ActiveRecord,你应该有一个模仿ActiveRecord::Relation
类的类,它存储你想要制作的请求片段,但实际上并没有查询直到您执行汇总(如计数,总和或最大值)或直到您尝试访问结果。
为了使其更简单,您可以在每个函数中存储所需的操作,并在末尾调用另一个函数来执行完整查询。
我想像这样:
class DynamOrm
#Array used to store the request items before the actual request is performed
attr_accessor :request_items
def find(key, options = {})
#Stores the "find" operation with its arguments in request_items
return self
end
def filter(filters)
#Stores the "filter" operation with its arguments in request_items
return self
end
def perform_query
#Actually performs the query by combining all the stored request_items
end
end
你可以像这样使用它:
my_results = DynamOrn.new().find(my_id).filter(my_filter).perform_query
它可能不完全是你需要的,但想法是:存储查询参数,然后在最后查询。