diff --git a/README.md b/README.md index 511c25a0..18007f5b 100644 --- a/README.md +++ b/README.md @@ -797,6 +797,24 @@ class Vehicle end ``` +#### Transition labels + +If you would prefer a custom label on a graphviz generated graph, specify +the `:graph_label` option on the transition statement. + +For example: + +```ruby + +class Vehicle + state_machine :initial => :parked do + + state :parked do + transition :to => :idling, :on => [:ignite, :shift_up], :if => :seatbelt_on?, :graph_label => "Seatbelt is ON" + end +end +``` + #### Transition context Some flexibility is provided around the context in which transitions can be diff --git a/lib/state_machine/branch.rb b/lib/state_machine/branch.rb index 56c5cafe..2d952acd 100644 --- a/lib/state_machine/branch.rb +++ b/lib/state_machine/branch.rb @@ -29,12 +29,16 @@ class Branch # * +from+ / +except_from+ # * +to+ / +except_to+ attr_reader :known_states - + + # An optional, custom, label to add to the graph when drawing the branch. + attr_reader :graph_label + # Creates a new branch def initialize(options = {}) #:nodoc: # Build conditionals @if_condition = options.delete(:if) @unless_condition = options.delete(:unless) + @graph_label = options.delete(:graph_label) # Build event requirement @event_requirement = build_matcher(options, :on, :except_on) diff --git a/lib/state_machine/event.rb b/lib/state_machine/event.rb index 6ddaa7db..c8efc720 100644 --- a/lib/state_machine/event.rb +++ b/lib/state_machine/event.rb @@ -194,7 +194,7 @@ def reset @branches = [] @known_states = [] end - + # Draws a representation of this event on the given graph. This will # create 1 or more edges on the graph for each branch (i.e. transition) # configured. @@ -205,12 +205,18 @@ def reset def draw(graph, options = {}) valid_states = machine.states.by_priority.map {|state| state.name} branches.each do |branch| - branch.draw(graph, options[:human_name] ? human_name : name, valid_states) + branch.draw(graph, graph_label(branch, options), valid_states) end true end + def graph_label(branch, options = {}) + graph_label_name = (options[:human_name] ? human_name : name).to_s + + branch.graph_label ? branch.graph_label : graph_label_name + end + # Generates a nicely formatted description of this event's contents. # # For example, diff --git a/lib/state_machine/graph.rb b/lib/state_machine/graph.rb index c73a56ce..ef9497c0 100644 --- a/lib/state_machine/graph.rb +++ b/lib/state_machine/graph.rb @@ -86,7 +86,7 @@ def v0_api? # The ruby-graphviz version data def version - Constants::RGV_VERSION.split('.') + GraphViz::Constants::RGV_VERSION.split('.') end end end diff --git a/state_machine.gemspec b/state_machine.gemspec index 1b7614b6..164f4143 100644 --- a/state_machine.gemspec +++ b/state_machine.gemspec @@ -17,6 +17,8 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w(README.md CHANGELOG.md LICENSE) s.add_development_dependency("rake") + s.add_development_dependency("test-unit") s.add_development_dependency("simplecov") + s.add_development_dependency("ruby-graphviz") s.add_development_dependency("appraisal", "~> 0.5.0") end diff --git a/test/unit/event_test.rb b/test/unit/event_test.rb index 1bf92cc4..7fe8306f 100644 --- a/test/unit/event_test.rb +++ b/test/unit/event_test.rb @@ -1170,6 +1170,28 @@ def test_should_use_event_name_for_edge_label end end + class EventDrawingWithCustomBranchLabelTest < Test::Unit::TestCase + def setup + states = [:parked, :idling] + + @machine = StateMachine::Machine.new(Class.new, :initial => :parked) + @machine.other_states(*states) + + graph = StateMachine::Graph.new('test') + states.each {|state| graph.add_nodes(state.to_s)} + + @machine.events << @event = StateMachine::Event.new(@machine , :park, :human_name => 'Park') + @event.transition :parked => :idling, :graph_label => "extra graph label" + + @event.draw(graph, :human_name => true) + @edge = graph.get_edge_at_index(0) + end + + def test_should_use_event_human_name_for_edge_label + assert_equal 'extra graph label', @edge['label'].to_s.gsub('"', '') + end + end + class EventDrawingWithHumanNameTest < Test::Unit::TestCase def setup states = [:parked, :idling] diff --git a/test/unit/machine_test.rb b/test/unit/machine_test.rb index 066fc1d5..8463f084 100644 --- a/test/unit/machine_test.rb +++ b/test/unit/machine_test.rb @@ -3261,7 +3261,7 @@ def test_should_allow_orientation_to_be_portrait assert_equal 'TB', graph['rankdir'].to_s.gsub('"', '') end - if Constants::RGV_VERSION != '0.9.0' + if GraphViz::Constants::RGV_VERSION != '0.9.0' def test_should_allow_human_names_to_be_displayed @machine.event :ignite, :human_name => 'Ignite' @machine.state :parked, :human_name => 'Parked'