我已将某些功能分离到各种服务/库中,尝试将此功能与我的应用程序的其余部分完全分开。我将从这里称之为服务。
目前这个小服务将ActiveRecord对象泄漏到调用代码中,但我真的更喜欢分离更清晰。
服务的API:
module MyService
# This method should really be read-only, but we're exposing
# ActiveRecord objects, so the caller can mess around with them. :(
def self.people
Person.all
end
end
调用代码示例
MyService.people.find_each(batch_size: 500) do |person|
# Do something useful with person
end
我正在考虑将ActiveRecord对象转换为Structs,然后再将它们返回到调用代码,这可能是实现此目的的一个想法。
这只有一个问题:Person模型有数千个条目。因此,我的天真方法将实例化数千个ActiveRecord,将其内容复制到数千个Structs然后返回。这显然是一个巨大的记忆力。
我想要的是能够让调用代码批量获取Person对象,并避免让MyService.people同时实例化所有记录。
我真的无法完全理解如何实现这一点。谁能指出我在这方面的正确方向?
答案 0 :(得分:2)
您可以在需要阻止的MyService
上编写自己的方法,并将Person
转换为yield
之前的只读版本。
module MyService
ReadOnlyPerson = Struct.new(:first_name, :last_name)
def self.each_person
Person.find_each do |person|
read_only_person = ReadOnlyPerson.new(person.first_name, person.last_name)
yield read_only_person
end
end
end
MyWrapper.each_person do |person|
puts person.first_name
end
如果您希望保留完整的ActiveRecord
功能(写作除外),您还可以使用readonly!
直接标记您的实例:
def self.each_person
Person.find_each do |person|
person.readonly!
yield person
end
end
您仍然可以分配person.first_name = 'Phil'
之类的内容,但尝试save
会引发异常:
ActiveRecord::ReadOnlyRecord: Person is marked as readonly