### Home Classes Methods

### In Files

- lib/state_machine/state.rb

### Parent

Object

### Methods

- #call
- #context
- #description
- #draw
- #final?
- #human_name
- #inspect
- #matches?
- #value

### Included Modules

- StateMachine::Assertions

### Files

- LICENSE

### Class/Module Index

Quicksearch

- StateMachine
- StateMachine::AllMatcher
- StateMachine::Assertions
- StateMachine::AttributeTransitionCollection
- StateMachine::BlacklistMatcher
- StateMachine::Branch
- StateMachine::Callback
- StateMachine::ClassMethods
- StateMachine::Error
- StateMachine::EvalHelpers
- StateMachine::Event
- StateMachine::EventCollection
- StateMachine::Graph
- StateMachine::InstanceMethods
- StateMachine::IntegrationNotFound
- StateMachine::Integrations
- StateMachine::Integrations::ActiveModel
- StateMachine::Integrations::ActiveModel::Observer
- StateMachine::Integrations::ActiveModel::ObserverUpdate
- StateMachine::Integrations::ActiveRecord
- StateMachine::Integrations::Base
- StateMachine::Integrations::Base::ClassMethods
- StateMachine::Integrations::DataMapper
- StateMachine::Integrations::DataMapper::Observer
- StateMachine::Integrations::MongoMapper
- StateMachine::Integrations::Mongoid
- StateMachine::Integrations::Sequel
- StateMachine::InvalidEvent
- StateMachine::InvalidParallelTransition
- StateMachine::InvalidTransition
- StateMachine::LoopbackMatcher
- StateMachine::Machine
- StateMachine::MachineCollection
- StateMachine::MacroMethods
- StateMachine::Matcher
- StateMachine::MatcherHelpers
- StateMachine::NodeCollection
- StateMachine::Path
- StateMachine::PathCollection
- StateMachine::RailsEngine
- StateMachine::State
- StateMachine::StateCollection
- StateMachine::StateContext
- StateMachine::Transition
- StateMachine::TransitionCollection
- StateMachine::WhitelistMatcher
- StateMachine::YARD
- StateMachine::YARD::Handlers
- StateMachine::YARD::Handlers::Base
- StateMachine::YARD::Handlers::Event
- StateMachine::YARD::Handlers::Machine
- StateMachine::YARD::Handlers::State
- StateMachine::YARD::Handlers::Transition
- Object

No matching classes.

# StateMachine::State

A state defines a value that an attribute can be in after being transitioned 0 or more times. States can represent a value of any type in Ruby, though the most common (and default) type is String.

In addition to defining the machine's value, a state can also define a behavioral context for an object when that object is in the state. See StateMachine::Machine#state for more information about how state-driven behavior can be utilized.

### Attributes

cache[RW]

Whether this state's value should be cached after being evaluated

human_name[W]

The human-readable name for the state

initial[RW]

Whether or not this state is the initial state to use for new objects

initial?[RW]

Whether or not this state is the initial state to use for new objects

machine[RW]

The state machine for which this state is defined

matcher[RW]

A custom lambda block for determining whether a given value matches this state

methods[R]

Tracks all of the methods that have been defined for the machine's owner class when objects are in this state.

Maps :method_name => UnboundMethod

name[R]

The unique identifier for the state used in event and callback definitions

qualified_name[R]

The fully-qualified identifier for the state, scoped by the machine's namespace

value[W]

The value that is written to a machine's attribute when an object transitions into this state

### Public Instance Methods

call(object, method, method_missing = nil, *args, &block) click to toggle source

Calls a method defined in this state's context on the given object. All arguments and any block will be passed into the method defined.

If the method has never been defined for this state, then a NoMethodError will be raised.

    # File lib/state_machine/state.rb, line 216
    def call(object, method, method_missing = nil, *args, &block)
      if machine.states.matches?(object, name) && context_method = methods[method.to_sym]
        # Method is defined by the state: proxy it through
        context_method.bind(object).call(*args, &block)
      else
        # Dispatch to the superclass since the object either isn't in this state
        # or this state doesn't handle the method
        method_missing.call if method_missing
      end
    end

context(&block) click to toggle source

Defines a context for the state which will be enabled on instances of the owner class when the machine is in this state.

This can be called multiple times. Each time a new context is created, a new module will be included in the owner class.

    # File lib/state_machine/state.rb, line 186
    def context(&block)
      machine_name = machine.name

      # Evaluate the method definitions
      context = StateContext.new(self)
      context.class_eval(&block)
      context.instance_methods.each do |method|
        methods[method.to_sym] = context.instance_method(method)

        # Calls the method defined by the current state of the machine
        context.class_eval           remove_method :#{method}          def #{method}(*args, &block)            self.class.state_machine(#{machine_name.inspect}).states.fetch(#{name.inspect}).call(self, #{method.inspect}, lambda {super(*args, &block)}, *args, &block)          end, __FILE__, __LINE__ + 1
      end

      # Include the context so that it can be bound to the owner class (the
      # context is considered an ancestor, so it's allowed to be bound)
      machine.owner_class.class_eval { include context }

      context
    end

description(options = {}) click to toggle source

Generates a human-readable description of this state's name / value:

For example,

    State.new(machine, :parked).description                               # => "parked"
    State.new(machine, :parked, :value => :parked).description            # => "parked"
    State.new(machine, :parked, :value => nil).description                # => "parked (nil)"
    State.new(machine, :parked, :value => 1).description                  # => "parked (1)"
    State.new(machine, :parked, :value => lambda {Time.now}).description  # => "parked (*)

Configuration options:

- `:human_name` - Whether to use this state's human name in the description or just the internal name

    # File lib/state_machine/state.rb, line 132
    def description(options = {})
      label = options[:human_name] ? human_name : name
      description = label ? label.to_s : label.inspect
      description << " (#{@value.is_a?(Proc) ? '*' : @value.inspect})" unless name.to_s == @value.to_s
      description
    end

draw(graph, options = {}) click to toggle source

Draws a representation of this state on the given machine. This will create a new node on the graph with the following properties:

- `label` - The human-friendly description of the state.

- `width` - The width of the node. Always 1.

- `height` - The height of the node. Always 1.

- `shape` - The actual shape of the node. If the state is a final state, then "doublecircle", otherwise "ellipse".

Configuration options:

- `:human_name` - Whether to use the state's human name for the node's label that gets drawn on the graph

    # File lib/state_machine/state.rb, line 238
    def draw(graph, options = {})
      node = graph.add_nodes(name ? name.to_s : 'nil',
        :label => description(options),
        :width => '1',
        :height => '1',
        :shape => final? ? 'doublecircle' : 'ellipse'
      )

      # Add open arrow for initial state
      graph.add_edges(graph.add_nodes('starting_state', :shape => 'point'), node) if initial?

      true
    end

final?() click to toggle source

Determines whether there are any states that can be transitioned to from this state. If there are none, then this state is considered final. Any objects in a final state will remain so forever given the current machine's definition.

    # File lib/state_machine/state.rb, line 103
    def final?
      !machine.events.any? do |event|
        event.branches.any? do |branch|
          branch.state_requirements.any? do |requirement|
            requirement[:from].matches?(name) && !requirement[:to].matches?(name, :from => name)
          end
        end
      end
    end

human_name(klass = @machine.owner_class) click to toggle source

Transforms the state name into a more human-readable format, such as "first gear" instead of "first_gear"

    # File lib/state_machine/state.rb, line 115
    def human_name(klass = @machine.owner_class)
      @human_name.is_a?(Proc) ? @human_name.call(self, klass) : @human_name
    end

inspect() click to toggle source

Generates a nicely formatted description of this state's contents.

For example,

    state = StateMachine::State.new(machine, :parked, :value => 1, :initial => true)
    state   # => #<StateMachine::State name=:parked value=1 initial=true context=[]>

    # File lib/state_machine/state.rb, line 258
    def inspect
      attributes = [[:name, name], [:value, @value], [:initial, initial?], [:context, methods.keys]]
      "#<#{self.class} #{attributes.map {|attr, value| "#{attr}=#{value.inspect}"} * ' '}>"
    end

matches?(other_value) click to toggle source

Determines whether this state matches the given value. If no matcher is configured, then this will check whether the values are equivalent. Otherwise, the matcher will determine the result.

For example,

    # Without a matcher
    state = State.new(machine, :parked, :value => 1)
    state.matches?(1)           # => true
    state.matches?(2)           # => false

    # With a matcher
    state = State.new(machine, :parked, :value => lambda {Time.now}, :if => lambda {|value| !value.nil?})
    state.matches?(nil)         # => false
    state.matches?(Time.now)    # => true

    # File lib/state_machine/state.rb, line 177
    def matches?(other_value)
      matcher ? matcher.call(other_value) : other_value == value
    end

value(eval = true) click to toggle source

The value that represents this state. This will optionally evaluate the original block if it's a lambda block. Otherwise, the static value is returned.

For example,

    State.new(machine, :parked, :value => 1).value                        # => 1
    State.new(machine, :parked, :value => lambda {Time.now}).value        # => Tue Jan 01 00:00:00 UTC 2008
    State.new(machine, :parked, :value => lambda {Time.now}).value(false) # => <Proc:0xb6ea7ca0@...>

    # File lib/state_machine/state.rb, line 148
    def value(eval = true)
      if @value.is_a?(Proc) && eval
        if cache_value?
          @value = @value.call
          machine.states.update(self)
          @value
        else
          @value.call
        end
      else
        @value
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.