0

我们正在维护几个Rails应用程序,这些应用程序都带来类似的问题,因此我们没有一个很好的解决方案:所有这些应用程序都包含需要对外部进行API调用的模型服务在他们的生命周期中。在回调中组织API调用

可能的情况:

  • 用户正在更新
  • 产品后更新订阅电子报订户名单,成功创建
  • 价格的报价与外部的购物系统是同步的,当添加这些CAL:在搜索指数更新

我们exprienced什么是一个很好的解决方案后, ls到该模型的after_*回调。由于这个测试速度很快,所以现在所有的工厂都必须处理API调用。

我正在寻找组织这些API调用的好方法。你们如何做到这一点?我们想出了

的想法,我认为不是真正的理想:

  • 移动这些回调到控制器。现在,他们很容易被遗忘,当创建一个对象
  • 产生一个异步工作者来处理API调用。然后,每一个甚至是小应用程序都需要延迟工作队列的开销,比如sidekiq。

回答

2

如果您担心测试可能put the callback methods into a separate class并在测试过程中模拟回调类。下面是使用RSpec的一个例子,下面给出FooFooCallbacks类:

class Foo < ActiveRecord::Base 
    after_save FooCallbacks 
end 

class FooCallbacks 
    def self.after_save 
    fail "Call to external API" 
    end 
end 

您可以编写并成功运行一个像这样的规格:

describe Foo do 

    before do 
    allow(FooCallbacks).to receive(:after_save) 
    end 

    it "should not invoke real APIs" do 
    Foo.create 
    end 

end 
1

这是怎样我现在做到了,劝后:

Foo

class Foo < ActiveRecord::Base 
    before_save Foo::DataSync 
end 

Foo:DataSync看起来是这样的:

class Foo::DataSync 
    def self.before_save(foo) 
    ...do the API-Calls... 
    end 
end 

现在在RSpec的测试我添加了这个:

spec_helper.rb

config.before(:each) do 
    Foo::DataSync.stub(:before_save) 
end 

注意config.before(:suite)是行不通的,因为Foo:DataSync不是那个装时间。

现在foo_spec.rb只包含了这一点:

describe Foo::DataSync do 
    let!(:foo) {create(:foo)} 

    before do 
    Foo::DataSync.unstub(:before_save) 
    end 

    after do 
    Foo::DataSync.stub(:before_save) 
    end 

    describe "#before_save" do 
    ...my examples... 
    end 
end 

describe Foo do 
    let(:foo) {create(:foo)} 

    it "will sync its data before every save" do 
    expect(Foo::DataSync).to receive(:before_save).with(foo) 

    foo.save 
    end 
end 

Foo::DataSync可以这样测试