lee*_*ena 5 rspec ruby-on-rails
我已经定义了after_commit回调update.它不会在rspec中触发.
这是我的回调:
after_commit :notify_trip, :if => Proc.new { |trip| trip.can_send_schedule_notification? }, on: :update
Run Code Online (Sandbox Code Playgroud)
这是我的rspec代码:
@work_order.update_attributes(:status_id => statuses(:scheduled).id, :tour_id => @tour.id)
@work_order.run_callbacks(:commit)
assert_equal 1, ActionMailer::Base.deliveries.size
expect(ActionMailer::Base.deliveries[0].to).to include(@user.email)
expect(ActionMailer::Base.deliveries[0].subject).to include("Your trip has been scheduled!")
Run Code Online (Sandbox Code Playgroud)
这里回调不是调用和ActionMailer::Base.deliveries.size返回0
对此有什么建议吗?
长话短说
@work_order.update_attributes(:status_id => statuses(:scheduled).id, :tour_id => @tour.id)
@work_order.instance_variable_set(:@_start_transaction_state, {})
@work_order.run_callbacks(:commit)
Run Code Online (Sandbox Code Playgroud)
解释
我在 Rails 4.0.1 中也遇到过类似的情况:
@work_order = WorkOrder.create(status_id: 1, order_id: 2)
@work_order.update_attributes(status_id: 4, order_id: 5)
@work_order.run_callbacks(:commit)
Run Code Online (Sandbox Code Playgroud)
当模型实现看起来像这样时:
class WorkOrder < ActiveRecord::Base
after_commit :notify_trip, :if => Proc.new { |trip| trip.can_send_schedule_notification? }, on: :update
after_commit :do_something, on: :create
end
Run Code Online (Sandbox Code Playgroud)
每次我调用时,@work_order.run_callbacks(:commit)它都会在创建方法上运行 after_commit - do_something。发生这种情况的原因是,在@work_order( ) 创建后@work_order = WorkOrder.create(status_id: 1, order_id: 2),调用的实例变量@_start_transaction_state被初始化,但从未被清除。@_start_transaction_state据我通过阅读代码了解到的情况,在 ActiveRecord::Transaction 模块中使用来跟踪事务处理。
因此,在调用之前,run_callbacks如果我们清理干净@_start_transaction_state,那么我们将能够运行after_commit on: update回调
@work_order.instance_variable_set(:@_start_transaction_state, {})
@work_order.run_callbacks(:commit)
Run Code Online (Sandbox Code Playgroud)
还有一个更干净的选择:
@work_order.send(:clear_transaction_record_state)
@work_order.run_callbacks(:commit)
Run Code Online (Sandbox Code Playgroud)
我知道这个解决方案很糟糕,我不确定这是否会带来一些副作用,尤其是嵌套事务,但这是 Rails 4.0.1 中唯一对我有用的变体。
根据文档,您需要使用test_after_commit gem 来after_commit在测试中触发钩子。Rails 5.0+ 不再需要这个。
另一种选择是将以下代码放在 it 块主体的末尾:
subject.run_callbacks(:commit)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2506 次 |
| 最近记录: |