我有一个测试套件,用于测试Rails模型的行为,并且在模型中添加了一些回调以测试其中一个属性的更改。在添加回调之前,这些测试工作正常(该回调除了将属性值打印到控制台之外,什么也不做)。添加回调之后,object.save!我称之为的方法不再有效。在调用save!的方法的上下文中,显然会更新记录并保存对象。但是,当我在方法完成后找到该记录时,该对象不变。保存不会引发任何错误!所以有点令人困惑:
我正在测试两个对象,一个“分支”对象,该对象实现包含分支的“ ApprovalNodes”的有序列表。将新节点添加到分支后,分支将在其组成节点上调用save。但是,尽管使用了save方法,但是当存在回调时,不会保存更改的节点之一。
节点代码:
%AllUsersAppData%
分支代码:
class ApprovalNode < ApplicationRecord
before_update :before_update_handler
after_update :after_update_handler
around_update :around_update_handler
belongs_to :branch, optional: true
belongs_to :user
belongs_to :approval
enum decision: { not_started: -1, pending: 0, approved: 1, declined: 2, abstained: 3, cut_off: 4 }
def decided?
return false if self.pending?
return true
end
private
def handler(phase)
puts phase.capitalize
puts "decision value: #{self.decision}"
puts "changes: #{self.changes}"
puts "will save_change: #{self.will_save_change_to_attribute?(:decision)}"
puts "changed attributes: #{self.changed_attributes}"
end
def before_update_handler
handler("before update") if self.will_save_change_to_attribute?(:decision)
true
end
def after_update_handler
handler("after Update") if self.will_save_change_to_attribute?(:decision)
true
end
def around_update_handler
handler("around update") if self.will_save_change_to_attribute?(:decision)
true
end
end
RSpec测试失败(删除回调后成功)。
class Branch < ApplicationRecord
belongs_to :approval
has_many :approval_nodes
# param [ApprovalNode] node
def append_node(node)
old_last_node = nil
if node.branch_id != self.id
raise "Branch Id must match node.branch_id"
end
if self.node_count == 0
self.first_node_id = node.id
self.last_node_id = node.id
node.next_node_id = nil
node.prev_node_id = nil
else
old_last_node = ApprovalNode.find(self.last_node_id)
# ! this change does not get persisted when save! is called
# when handlers are present in ApprovalNode code.
# When handlers are removed, this works as expected.
old_last_node.next_node_id = node.id
old_last_node.save!
node.prev_node_id = old_last_node.id
self.last_node_id = node.id
end
node.save!
self.node_count += 1
self.save!
return node
end
end
NodeWorkflow中测试调用的Helper方法:
it 'keeps track of next and last nodes properly' do
wf= NodeWorkflow.new(branch)
node1 = wf.append_node(user1.id)
expect(node1.next_node_id).to be_nil
expect(node1.prev_node_id).to be_nil
node2 = wf.append_node(user2.id)
node1.reload
expect(node1.next_node_id).to eq(node2.id) #FAILS HERE node1.next_node_id is nil
expect(node1.prev_node_id).to be_nil
expect(node2.next_node_id).to be_nil
expect(node2.prev_node_id).to eq(node1.id)
end