首页 > 解决方案 > 在 ruby​​ gem 中保存和重用数据的有效方法

问题描述

我正在使用一个 ruby​​ gem,它本质上是一个业务逻辑层,并在从外部服务(通过 API)收集数据后运行自定义规则。

从外部服务收集的这些数据保存为我的一个 ruby​​ 类中的实例变量,并且逻辑只是在其上运行。像这样的东西:

@data = gather_data_from_service

在本地开发过程中,每次做一些代码更改并测试它都必须等待 10 分钟才能抓取这些数据,这很烦人。有没有办法可以保存和重复使用它?寻找一些建议。谢谢!

这是gather_data_from_service返回的内容:(它是一个红宝石对象列表)

[#MyLibrary::ClassA
    @id: 'xxx',
    @name: 'ppp', 
 #MyLibrary::ClassA
    @id: 'yo',
    @name,
 #MyLibrary::ClassA
   -----,
 #MyLibrary::ClassA
   -----]

PS:我从服务中收集的数据需要很长时间才能迭代其所有资源并做出响应(我认为我无法对此进行改进)。

标签: ruby-on-railsruby

解决方案


你在这里有几个选择,但基本上可以归结为有一个假的或模拟的课程。

一个例子是围绕您的数据获取编写一个适配器类,您可以将其换成假加载器。假设您的 API 是 JSON,您可以将一些数据存储在 JSON 文件中,然后像这样加载它:

class RemoteData
  def data
    @data = gather_data_from_service
  end
end

class MemoryData
  def data
    @data = fetch_data
  end

  def fetch_data
    JSON.parse(File.read('path/to/fixtures/data.json'))
  end
end

如果您的响应数据更复杂,您还可以考虑围绕它编写包装类。然后你可以根据环境设置类。这仅适用于查询。如果你也需要测试命令,你可以编写一个 spy 类。

class Spy
  cattr_accessor :data do
    []
  end

  def post(params)
    data << params
  end
end

spy = Spy.new
spy.post(hello: :world)
Spy.deliveries.include?({ hello: :world })

其他选项可能是编写一个像fake_stripe gem这样的假文件,或者使用Webmock来模拟 HTTP 请求。

这里也解释了mock、fake 和 spy之间的区别。

编辑

您仍然可以使用某种模拟或伪造,您只需要首先考虑某种序列化数据的方法。最具扩展性和可读性的方法仍然是将其序列化为 JSON。您可以像这样使用例如猴子补丁自己实现它。

class MyClass::A
  def serialize
    {}.tap do |result|
      instance_variables.map do |var|
        result[var.to_s.delete("@")] = instance_variable_get(var)
      end
    end
  end
end

MyClass::A.new(id: 1).serialize
# { id: 1 }

更裸机的方法可能是使用例如Marshal dump

A = Struct.new(:id)
serialized = Marshal.dump(A.new(id: 1))
# "\x04\bS:\x06A\x06:\aid{\x06;\x06i\x06"
Marshal.load(serialized)
# => #<struct A id={:id=>1}>

推荐阅读