diff --git a/lib/statesman/adapters/active_record.rb b/lib/statesman/adapters/active_record.rb index 9fa42438..50beaa3d 100644 --- a/lib/statesman/adapters/active_record.rb +++ b/lib/statesman/adapters/active_record.rb @@ -41,8 +41,8 @@ def create(from, to, metadata = {}) @last_transition = nil end - def history - if transitions_for_parent.loaded? + def history(force_reload: false) + if transitions_for_parent.loaded? && !force_reload # Workaround for Rails bug which causes infinite loop when sorting # already loaded result set. Introduced in rails/rails@b097ebe transitions_for_parent.to_a.sort_by(&:sort_key) @@ -53,7 +53,7 @@ def history def last(force_reload: false) if force_reload - @last_transition = history.last + @last_transition = history(force_reload: true).last else @last_transition ||= history.last end diff --git a/lib/statesman/adapters/memory.rb b/lib/statesman/adapters/memory.rb index 840071b3..e749bd51 100644 --- a/lib/statesman/adapters/memory.rb +++ b/lib/statesman/adapters/memory.rb @@ -4,7 +4,6 @@ module Statesman module Adapters class Memory attr_reader :transition_class - attr_reader :history attr_reader :parent_model # We only accept mode as a parameter to maintain a consistent interface @@ -32,6 +31,10 @@ def last(*) @history.sort_by(&:sort_key).last end + def history(*) + @history + end + private def next_sort_key diff --git a/lib/statesman/adapters/mongoid.rb b/lib/statesman/adapters/mongoid.rb index efc3c74f..ac5ace0f 100644 --- a/lib/statesman/adapters/mongoid.rb +++ b/lib/statesman/adapters/mongoid.rb @@ -32,7 +32,7 @@ def create(from, to, metadata = {}) @last_transition = nil end - def history + def history(*) transitions_for_parent.asc(:sort_key) end diff --git a/spec/statesman/adapters/active_record_spec.rb b/spec/statesman/adapters/active_record_spec.rb index 682e71cb..bdad345f 100644 --- a/spec/statesman/adapters/active_record_spec.rb +++ b/spec/statesman/adapters/active_record_spec.rb @@ -234,17 +234,35 @@ described_class.new(MyActiveRecordModelTransition, model, observer) end - before { alternate_adapter.create(:y, :z, []) } - it "still returns the cached value" do + alternate_adapter.create(:y, :z, []) + expect_any_instance_of(MyActiveRecordModel). to receive(:my_active_record_model_transitions).never expect(adapter.last.to_state).to eq("y") end - context "when explitly not using the cache" do - it "still returns the cached value" do - expect(adapter.last(force_reload: true).to_state).to eq("z") + context "when explicitly not using the cache" do + context "when the transitions are in memory" do + before do + model.my_active_record_model_transitions.load + alternate_adapter.create(:y, :z, []) + end + + it "reloads the value" do + expect(adapter.last(force_reload: true).to_state).to eq("z") + end + end + + context "when the transitions are not in memory" do + before do + model.my_active_record_model_transitions.reset + alternate_adapter.create(:y, :z, []) + end + + it "reloads the value" do + expect(adapter.last(force_reload: true).to_state).to eq("z") + end end end end diff --git a/spec/statesman/adapters/mongoid_spec.rb b/spec/statesman/adapters/mongoid_spec.rb index ca797ca1..71041e67 100644 --- a/spec/statesman/adapters/mongoid_spec.rb +++ b/spec/statesman/adapters/mongoid_spec.rb @@ -48,5 +48,35 @@ end end end + + context "when a new transition has been created elsewhere" do + let(:alternate_adapter) do + described_class.new(MyMongoidModelTransition, model, observer) + end + + context "when explicitly not using the cache" do + context "when the transitions are in memory" do + before do + model.my_mongoid_model_transitions.entries + alternate_adapter.create(:y, :z) + end + + it "reloads the value" do + expect(adapter.last(force_reload: true).to_state).to eq("z") + end + end + + context "when the transitions are not in memory" do + before do + model.my_mongoid_model_transitions.reset + alternate_adapter.create(:y, :z) + end + + it "reloads the value" do + expect(adapter.last(force_reload: true).to_state).to eq("z") + end + end + end + end end end