Ruby on rails 包装#找到每一个并亲自展示类似的功能 背景
我已经将一些功能划分为一个服务/类库,试图将此功能与我的应用程序的其余部分清晰地分开。从现在起我称之为服务 目前,这个小服务将ActiveRecord对象泄漏到调用代码中,但我更希望分离更干净 代码示例 服务的API:Ruby on rails 包装#找到每一个并亲自展示类似的功能 背景,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我已经将一些功能划分为一个服务/类库,试图将此功能与我的应用程序的其余部分清晰地分开。从现在起我称之为服务 目前,这个小服务将ActiveRecord对象泄漏到调用代码中,但我更希望分离更干净 代码示例 服务的API: module MyService # This method should really be read-only, but we're exposing # ActiveRecord objects, so the caller can mess around wit
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对象返回到调用代码之前将其转换为结构可能是实现这一点的一个想法
问题
这里只有一个问题:Person模型有数千个条目。因此,我的天真方法将实例化数千个ActiveRecord,将其内容复制到数千个结构中,然后返回。这显然是一个巨大的内存消耗
我希望调用代码能够批量获取Person对象,并避免MyService.people一次实例化所有记录
我真的无法完全理解这是如何实现的。有人能给我指出正确的方向吗?您可以在
MyService
上编写自己的方法,该方法需要一个块,并在生成之前将人
转换为只读版本
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
如果您想保留完整的ActiveRecord
功能(除了编写),还可以直接用readonly标记实例代码>:
def self.each_person
Person.find_each do |person|
person.readonly!
yield person
end
end
您仍然可以分配诸如person.first\u name='Phil'
之类的内容,但尝试保存将引发异常:
ActiveRecord::ReadOnlyRecord: Person is marked as readonly
令人惊叹的。这很好用,谢谢你给我的建议,让ActiveRecord
readonly成为一个只读的,在我决定不再是一个纯粹主义者的情况下,它可能会派上用场!
ActiveRecord::ReadOnlyRecord: Person is marked as readonly