From ae989c4170e2ea769e92a54bb431c80c2be30d36 Mon Sep 17 00:00:00 2001 From: Grey Baker Date: Tue, 26 Jul 2016 10:45:03 +0100 Subject: [PATCH] Handle custom transition association names gracefully Previously, statesman required the association with the transition class to use the exact name of the transition class, unless a `transition_name` was specified along with the `transition_class`. This PR updates the way we look for the association with the transition class so as `transition_name` no longer needs to be overridden to work with custom named associations. --- .../adapters/active_record_queries.rb | 8 ++++- lib/statesman/exceptions.rb | 1 + .../adapters/active_record_queries_spec.rb | 32 ++++++++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/statesman/adapters/active_record_queries.rb b/lib/statesman/adapters/active_record_queries.rb index ce9ee544..3e4e8e42 100644 --- a/lib/statesman/adapters/active_record_queries.rb +++ b/lib/statesman/adapters/active_record_queries.rb @@ -38,7 +38,13 @@ def transition_name end def transition_reflection - reflect_on_association(transition_name) + reflect_on_all_associations(:has_many).each do |value| + return value if value.klass == transition_class + end + + raise MissingTransitionAssociation, + "Could not find has_many association between #{self.class} " \ + "and #{transition_class}." end def model_foreign_key diff --git a/lib/statesman/exceptions.rb b/lib/statesman/exceptions.rb index e490c904..8ec2bf63 100644 --- a/lib/statesman/exceptions.rb +++ b/lib/statesman/exceptions.rb @@ -5,6 +5,7 @@ class InvalidCallbackError < StandardError; end class GuardFailedError < StandardError; end class TransitionFailedError < StandardError; end class TransitionConflictError < StandardError; end + class MissingTransitionAssociation < StandardError; end class UnserializedMetadataError < StandardError def initialize(transition_class_name) diff --git a/spec/statesman/adapters/active_record_queries_spec.rb b/spec/statesman/adapters/active_record_queries_spec.rb index 8968cfb7..660a2a65 100644 --- a/spec/statesman/adapters/active_record_queries_spec.rb +++ b/spec/statesman/adapters/active_record_queries_spec.rb @@ -125,14 +125,18 @@ def self.initial_state end end - context "with a transition name" do + context "with a custom name for the transition association" do before do + # Switch to using OtherActiveRecordModelTransition, so the existing + # relation with MyActiveRecordModelTransition doesn't interfere with + # this spec. MyActiveRecordModel.send(:has_many, :custom_name, - class_name: 'MyActiveRecordModelTransition') + class_name: 'OtherActiveRecordModelTransition') + MyActiveRecordModel.class_eval do - def self.transition_name - :custom_name + def self.transition_class + OtherActiveRecordModelTransition end end end @@ -142,4 +146,24 @@ def self.transition_name specify { expect { query }.to_not raise_error } end end + + context "with no association with the transition class" do + before do + class UnknownModelTransition < OtherActiveRecordModelTransition; end + + MyActiveRecordModel.class_eval do + def self.transition_class + UnknownModelTransition + end + end + end + + describe ".in_state" do + subject(:query) { MyActiveRecordModel.in_state(:succeeded) } + + it "raises a helpful error" do + expect { query }.to raise_error(Statesman::MissingTransitionAssociation) + end + end + end end