class Vehicle < ActiveRecord::Base belongs_to :auto_shop belongs_to :highway attr_accessor :force_idle # Defines the state machine for the state of the vehicle state_machine :state, :initial => Proc.new {|vehicle| vehicle.force_idle ? 'idling' : 'parked'} do before_exit 'parked', :put_on_seatbelt after_enter 'parked', Proc.new {|vehicle| vehicle.update_attribute(:seatbelt_on, false)} before_enter 'stalled', :increase_insurance_premium event :park do transition :to => 'parked', :from => %w(idling first_gear) end event :ignite do transition :to => 'stalled', :from => 'stalled' transition :to => 'idling', :from => 'parked' end event :idle do transition :to => 'idling', :from => 'first_gear' end event :shift_up do transition :to => 'first_gear', :from => 'idling' transition :to => 'second_gear', :from => 'first_gear' transition :to => 'third_gear', :from => 'second_gear' end event :shift_down do transition :to => 'second_gear', :from => 'third_gear' transition :to => 'first_gear', :from => 'second_gear' end event :crash, :after => :tow! do transition :to => 'stalled', :from => %w(first_gear second_gear third_gear), :if => Proc.new {|vehicle| vehicle.auto_shop.available?} end event :repair, :after => :fix! do transition :to => 'parked', :from => 'stalled', :if => :auto_shop_busy? end end # Tows the vehicle to the auto shop def tow! auto_shop.tow_vehicle! end # Fixes the vehicle; it will no longer be in the auto shop def fix! auto_shop.fix_vehicle! end private # Safety first! Puts on our seatbelt def put_on_seatbelt self.seatbelt_on = true end # We crashed! Increase the insurance premium on the vehicle def increase_insurance_premium update_attribute(:insurance_premium, self.insurance_premium + 100) end # Is the auto shop currently servicing another customer? def auto_shop_busy? auto_shop.busy? end end