PageRenderTime 45ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/integrations/sequel_test.rb

http://github.com/pluginaweek/state_machine
Ruby | 1896 lines | 1497 code | 395 blank | 4 comment | 33 complexity | dc5ddfa8336c574e2e6eb50aafcce199 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
  2. require 'sequel'
  3. require 'logger'
  4. require 'stringio'
  5. # Establish database connection
  6. DB = Sequel.connect(RUBY_PLATFORM == 'java' ? 'jdbc:sqlite::memory:' : 'sqlite:///', :loggers => [Logger.new("#{File.dirname(__FILE__)}/../../sequel.log")])
  7. module SequelTest
  8. class BaseTestCase < Test::Unit::TestCase
  9. def default_test
  10. end
  11. protected
  12. # Creates a new Sequel model (and the associated table)
  13. def new_model(create_table = :foo, &block)
  14. name = create_table || :foo
  15. table_name = "#{name}_#{rand(1000000)}"
  16. table_identifier = Sequel::SQL::Identifier.new(table_name)
  17. if !defined?(Sequel::VERSION) || Gem::Version.new(Sequel::VERSION) <= Gem::Version.new('3.26.0')
  18. class << table_identifier
  19. alias_method :original_to_s, :to_s
  20. def to_s(*args); args.empty? ? inspect : original_to_s(*args); end
  21. end
  22. end
  23. DB.create_table!(table_identifier) do
  24. primary_key :id
  25. column :state, :string
  26. end if create_table
  27. model = Class.new(Sequel::Model) do
  28. self.raise_on_save_failure = false
  29. (class << self; self; end).class_eval do
  30. define_method(:name) { "SequelTest::#{name.to_s.capitalize}" }
  31. define_method(:table_identifier) { table_identifier }
  32. end
  33. set_dataset(DB[table_identifier])
  34. end
  35. model.set_dataset(DB[table_identifier])
  36. model.class_eval(&block) if block_given?
  37. model
  38. end
  39. end
  40. class IntegrationTest < BaseTestCase
  41. def test_should_have_an_integration_name
  42. assert_equal :sequel, StateMachine::Integrations::Sequel.integration_name
  43. end
  44. def test_should_be_available
  45. assert StateMachine::Integrations::Sequel.available?
  46. end
  47. def test_should_match_if_class_inherits_from_sequel
  48. assert StateMachine::Integrations::Sequel.matches?(new_model)
  49. end
  50. def test_should_not_match_if_class_does_not_inherit_from_sequel
  51. assert !StateMachine::Integrations::Sequel.matches?(Class.new)
  52. end
  53. def test_should_have_defaults
  54. assert_equal({:action => :save}, StateMachine::Integrations::Sequel.defaults)
  55. end
  56. def test_should_not_have_a_locale_path
  57. assert_nil StateMachine::Integrations::Sequel.locale_path
  58. end
  59. end
  60. class MachineWithoutDatabaseTest < BaseTestCase
  61. def setup
  62. @model = new_model(false)
  63. end
  64. def test_should_allow_machine_creation
  65. assert_nothing_raised { StateMachine::Machine.new(@model) }
  66. end
  67. end
  68. class MachineUnmigratedTest < BaseTestCase
  69. def setup
  70. @model = new_model(false)
  71. end
  72. def test_should_allow_machine_creation
  73. assert_nothing_raised { StateMachine::Machine.new(@model) }
  74. end
  75. end
  76. class MachineByDefaultTest < BaseTestCase
  77. def setup
  78. @model = new_model
  79. @machine = StateMachine::Machine.new(@model)
  80. end
  81. def test_should_use_save_as_action
  82. assert_equal :save, @machine.action
  83. end
  84. def test_should_use_transactions
  85. assert_equal true, @machine.use_transactions
  86. end
  87. def test_should_not_have_any_before_callbacks
  88. assert_equal 0, @machine.callbacks[:before].size
  89. end
  90. def test_should_not_have_any_after_callbacks
  91. assert_equal 0, @machine.callbacks[:after].size
  92. end
  93. end
  94. class MachineWithStatesTest < BaseTestCase
  95. def setup
  96. @model = new_model
  97. @machine = StateMachine::Machine.new(@model)
  98. @machine.state :first_gear
  99. end
  100. def test_should_humanize_name
  101. assert_equal 'first gear', @machine.state(:first_gear).human_name
  102. end
  103. end
  104. class MachineWithStaticInitialStateTest < BaseTestCase
  105. def setup
  106. @model = new_model(:vehicle) do
  107. attr_accessor :value
  108. end
  109. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  110. end
  111. def test_should_set_initial_state_on_created_object
  112. record = @model.new
  113. assert_equal 'parked', record.state
  114. end
  115. def test_should_still_set_attributes
  116. record = @model.new(:value => 1)
  117. assert_equal 1, record.value
  118. end
  119. def test_should_still_allow_initialize_blocks
  120. block_args = nil
  121. record = @model.new do |*args|
  122. block_args = args
  123. end
  124. assert_equal [record], block_args
  125. end
  126. def test_should_set_attributes_prior_to_initialize_block
  127. state = nil
  128. @model.new do |record|
  129. state = record.state
  130. end
  131. assert_equal 'parked', state
  132. end
  133. def test_should_set_attributes_prior_to_after_initialize_hook
  134. state = nil
  135. @model.class_eval do
  136. define_method(:after_initialize) do
  137. state = self.state
  138. end
  139. end
  140. @model.new
  141. assert_equal 'parked', state
  142. end
  143. def test_should_set_initial_state_before_setting_attributes
  144. @model.class_eval do
  145. attr_accessor :state_during_setter
  146. remove_method :value=
  147. define_method(:value=) do |value|
  148. self.state_during_setter = state
  149. end
  150. end
  151. record = @model.new(:value => 1)
  152. assert_equal 'parked', record.state_during_setter
  153. end
  154. def test_should_not_set_initial_state_after_already_initialized
  155. record = @model.new(:value => 1)
  156. assert_equal 'parked', record.state
  157. record.state = 'idling'
  158. record.set({})
  159. assert_equal 'idling', record.state
  160. end
  161. def test_should_persist_initial_state
  162. record = @model.new
  163. record.save
  164. record.reload
  165. assert_equal 'parked', record.state
  166. end
  167. def test_should_persist_initial_state_on_dup
  168. record = @model.create.dup
  169. record.save
  170. record.reload
  171. assert_equal 'parked', record.state
  172. end
  173. def test_should_use_stored_values_when_loading_from_database
  174. @machine.state :idling
  175. record = @model[@model.create(:state => 'idling').id]
  176. assert_equal 'idling', record.state
  177. end
  178. def test_should_use_stored_values_when_loading_from_database_with_nil_state
  179. @machine.state nil
  180. record = @model[@model.create(:state => nil).id]
  181. assert_nil record.state
  182. end
  183. def test_should_use_stored_values_when_loading_for_many_association
  184. @machine.state :idling
  185. DB.alter_table(@model.table_identifier) do
  186. add_column :owner_id, :integer
  187. end
  188. @model.class_eval { get_db_schema(true) }
  189. SequelTest.const_set('Vehicle', @model)
  190. owner_model = new_model(:owner) do
  191. one_to_many :vehicles, :class_name => 'SequelTest::Vehicle'
  192. end
  193. SequelTest.const_set('Owner', owner_model)
  194. owner = owner_model.create
  195. record = @model.create(:state => 'idling', :owner_id => owner.id)
  196. assert_equal 'idling', owner.vehicles[0].state
  197. end
  198. if defined?(Sequel::VERSION) && Gem::Version.new(Sequel::VERSION) >= Gem::Version.new('3.10.0')
  199. def test_should_use_stored_values_when_loading_for_one_association
  200. @machine.state :idling
  201. DB.alter_table(@model.table_identifier) do
  202. add_column :owner_id, :integer
  203. end
  204. @model.class_eval { get_db_schema(true) }
  205. SequelTest.const_set('Vehicle', @model)
  206. owner_model = new_model(:owner) do
  207. one_to_one :vehicle, :class_name => 'SequelTest::Vehicle'
  208. end
  209. SequelTest.const_set('Owner', owner_model)
  210. owner = owner_model.create
  211. record = @model.create(:state => 'idling', :owner_id => owner.id)
  212. owner.reload
  213. assert_equal 'idling', owner.vehicle.state
  214. end
  215. end
  216. def test_should_use_stored_values_when_loading_for_belongs_to_association
  217. @machine.state :idling
  218. SequelTest.const_set('Vehicle', @model)
  219. driver_model = new_model(:driver) do
  220. DB.alter_table(table_identifier) do
  221. add_column :vehicle_id, :integer
  222. end
  223. get_db_schema(true)
  224. many_to_one :vehicle, :class_name => 'SequelTest::Vehicle'
  225. end
  226. SequelTest.const_set('Driver', driver_model)
  227. record = @model.create(:state => 'idling')
  228. driver = driver_model.create(:vehicle_id => record.id)
  229. assert_equal 'idling', driver.vehicle.state
  230. end
  231. def teardown
  232. SequelTest.class_eval do
  233. remove_const('Vehicle') if defined?(SequelTest::Vehicle)
  234. remove_const('Owner') if defined?(SequelTest::Owner)
  235. remove_const('Driver') if defined?(SequelTest::Driver)
  236. end
  237. super
  238. end
  239. end
  240. class MachineWithDynamicInitialStateTest < BaseTestCase
  241. def setup
  242. @model = new_model do
  243. attr_accessor :value
  244. end
  245. @machine = StateMachine::Machine.new(@model, :initial => lambda {|object| :parked})
  246. @machine.state :parked
  247. end
  248. def test_should_set_initial_state_on_created_object
  249. record = @model.new
  250. assert_equal 'parked', record.state
  251. end
  252. def test_should_still_set_attributes
  253. record = @model.new(:value => 1)
  254. assert_equal 1, record.value
  255. end
  256. def test_should_still_allow_initialize_blocks
  257. block_args = nil
  258. record = @model.new do |*args|
  259. block_args = args
  260. end
  261. assert_equal [record], block_args
  262. end
  263. def test_should_not_have_any_changed_columns
  264. record = @model.new
  265. assert record.changed_columns.empty?
  266. end
  267. def test_should_set_attributes_prior_to_initialize_block
  268. state = nil
  269. @model.new do |record|
  270. state = record.state
  271. end
  272. assert_equal 'parked', state
  273. end
  274. def test_should_set_attributes_prior_to_after_initialize_hook
  275. state = nil
  276. @model.class_eval do
  277. define_method(:after_initialize) do
  278. state = self.state
  279. end
  280. end
  281. @model.new
  282. assert_equal 'parked', state
  283. end
  284. def test_should_set_initial_state_after_setting_attributes
  285. @model.class_eval do
  286. attr_accessor :state_during_setter
  287. remove_method :value=
  288. define_method(:value=) do |value|
  289. self.state_during_setter = state || 'nil'
  290. end
  291. end
  292. record = @model.new(:value => 1)
  293. assert_equal 'nil', record.state_during_setter
  294. end
  295. def test_should_not_set_initial_state_after_already_initialized
  296. record = @model.new(:value => 1)
  297. assert_equal 'parked', record.state
  298. record.state = 'idling'
  299. record.set({})
  300. assert_equal 'idling', record.state
  301. end
  302. def test_should_persist_initial_state
  303. record = @model.new
  304. record.save
  305. record.reload
  306. assert_equal 'parked', record.state
  307. end
  308. def test_should_persist_initial_state_on_dup
  309. record = @model.create.dup
  310. record.save
  311. record.reload
  312. assert_equal 'parked', record.state
  313. end
  314. def test_should_use_stored_values_when_loading_from_database
  315. @machine.state :idling
  316. record = @model[@model.create(:state => 'idling').id]
  317. assert_equal 'idling', record.state
  318. end
  319. def test_should_use_stored_values_when_loading_from_database_with_nil_state
  320. @machine.state nil
  321. record = @model[@model.create(:state => nil).id]
  322. assert_nil record.state
  323. end
  324. end
  325. class MachineWithEventsTest < BaseTestCase
  326. def setup
  327. @model = new_model
  328. @machine = StateMachine::Machine.new(@model)
  329. @machine.event :shift_up
  330. end
  331. def test_should_humanize_name
  332. assert_equal 'shift up', @machine.event(:shift_up).human_name
  333. end
  334. end
  335. class MachineWithSameColumnDefaultTest < BaseTestCase
  336. def setup
  337. @original_stderr, $stderr = $stderr, StringIO.new
  338. @model = new_model(false)
  339. DB.create_table!(@model.table_identifier) do
  340. primary_key :id
  341. column :status, :string, :default => 'parked'
  342. end
  343. @model.class_eval do
  344. set_dataset(DB[table_identifier])
  345. get_db_schema(true)
  346. end
  347. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  348. @record = @model.new
  349. end
  350. def test_should_use_machine_default
  351. assert_equal 'parked', @record.status
  352. end
  353. def test_should_not_generate_a_warning
  354. assert_no_match(/have defined a different default/, $stderr.string)
  355. end
  356. def teardown
  357. $stderr = @original_stderr
  358. end
  359. end
  360. class MachineWithDifferentColumnDefaultTest < BaseTestCase
  361. def setup
  362. @original_stderr, $stderr = $stderr, StringIO.new
  363. @model = new_model(false)
  364. DB.create_table!(@model.table_identifier) do
  365. primary_key :id
  366. column :status, :string, :default => 'idling'
  367. end
  368. @model.class_eval do
  369. set_dataset(DB[table_identifier])
  370. get_db_schema(true)
  371. end
  372. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  373. @record = @model.new
  374. end
  375. def test_should_use_machine_default
  376. assert_equal 'parked', @record.status
  377. end
  378. def test_should_generate_a_warning
  379. assert_match(/Both SequelTest::Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
  380. end
  381. def teardown
  382. $stderr = @original_stderr
  383. end
  384. end
  385. class MachineWithDifferentIntegerColumnDefaultTest < BaseTestCase
  386. def setup
  387. @original_stderr, $stderr = $stderr, StringIO.new
  388. @model = new_model(false)
  389. DB.create_table!(@model.table_identifier) do
  390. primary_key :id
  391. column :status, :integer, :default => 0
  392. end
  393. @model.class_eval do
  394. set_dataset(DB[table_identifier])
  395. get_db_schema(true)
  396. end
  397. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  398. @machine.state :parked, :value => 1
  399. @record = @model.new
  400. end
  401. def test_should_use_machine_default
  402. assert_equal 1, @record.status
  403. end
  404. def test_should_generate_a_warning
  405. assert_match(/Both SequelTest::Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
  406. end
  407. def teardown
  408. $stderr = @original_stderr
  409. end
  410. end
  411. class MachineWithConflictingPredicateTest < BaseTestCase
  412. def setup
  413. @model = new_model do
  414. def state?(*args)
  415. true
  416. end
  417. end
  418. @machine = StateMachine::Machine.new(@model)
  419. @record = @model.new
  420. end
  421. def test_should_not_define_attribute_predicate
  422. assert @record.state?
  423. end
  424. end
  425. class MachineWithColumnStateAttributeTest < BaseTestCase
  426. def setup
  427. @model = new_model
  428. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  429. @machine.other_states(:idling)
  430. @record = @model.new
  431. end
  432. def test_should_not_override_the_column_reader
  433. record = @model.new
  434. record[:state] = 'parked'
  435. assert_equal 'parked', record.state
  436. end
  437. def test_should_not_override_the_column_writer
  438. record = @model.new
  439. record.state = 'parked'
  440. assert_equal 'parked', record[:state]
  441. end
  442. def test_should_have_an_attribute_predicate
  443. assert @record.respond_to?(:state?)
  444. end
  445. def test_should_raise_exception_for_predicate_without_parameters
  446. assert_raise(ArgumentError) { @record.state? }
  447. end
  448. def test_should_return_false_for_predicate_if_does_not_match_current_value
  449. assert !@record.state?(:idling)
  450. end
  451. def test_should_return_true_for_predicate_if_matches_current_value
  452. assert @record.state?(:parked)
  453. end
  454. def test_should_raise_exception_for_predicate_if_invalid_state_specified
  455. assert_raise(IndexError) { @record.state?(:invalid) }
  456. end
  457. end
  458. class MachineWithNonColumnStateAttributeUndefinedTest < BaseTestCase
  459. def setup
  460. @model = new_model do
  461. # Prevent attempts to access the status field
  462. def method_missing(method, *args)
  463. super unless %w(status status=).include?(method.to_s)
  464. end
  465. end
  466. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  467. @machine.other_states(:idling)
  468. @record = @model.new
  469. end
  470. def test_should_not_define_a_reader_attribute_for_the_attribute
  471. assert !@record.respond_to?(:status)
  472. end
  473. def test_should_not_define_a_writer_attribute_for_the_attribute
  474. assert !@record.respond_to?(:status=)
  475. end
  476. def test_should_define_an_attribute_predicate
  477. assert @record.respond_to?(:status?)
  478. end
  479. end
  480. class MachineWithNonColumnStateAttributeDefinedTest < BaseTestCase
  481. def setup
  482. @model = new_model do
  483. attr_accessor :status
  484. end
  485. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  486. @machine.other_states(:idling)
  487. @record = @model.new
  488. end
  489. def test_should_return_false_for_predicate_if_does_not_match_current_value
  490. assert !@record.status?(:idling)
  491. end
  492. def test_should_return_true_for_predicate_if_matches_current_value
  493. assert @record.status?(:parked)
  494. end
  495. def test_should_set_initial_state_on_created_object
  496. assert_equal 'parked', @record.status
  497. end
  498. end
  499. class MachineWithInitializedStateTest < BaseTestCase
  500. def setup
  501. @model = new_model
  502. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  503. @machine.state :idling
  504. end
  505. def test_should_allow_nil_initial_state_when_static
  506. @machine.state nil
  507. record = @model.new(:state => nil)
  508. assert_nil record.state
  509. end
  510. def test_should_allow_nil_initial_state_when_dynamic
  511. @machine.state nil
  512. @machine.initial_state = lambda {:parked}
  513. record = @model.new(:state => nil)
  514. assert_nil record.state
  515. end
  516. def test_should_allow_different_initial_state_when_static
  517. record = @model.new(:state => 'idling')
  518. assert_equal 'idling', record.state
  519. end
  520. def test_should_allow_different_initial_state_when_dynamic
  521. @machine.initial_state = lambda {:parked}
  522. record = @model.new(:state => 'idling')
  523. assert_equal 'idling', record.state
  524. end
  525. def test_should_use_default_state_if_protected
  526. @model.class_eval do
  527. self.strict_param_setting = false
  528. set_restricted_columns :state
  529. end
  530. record = @model.new(:state => 'idling')
  531. assert_equal 'parked', record.state
  532. end
  533. end
  534. class MachineMultipleTest < BaseTestCase
  535. def setup
  536. @model = new_model
  537. DB.alter_table(@model.table_identifier) do
  538. add_column :status, :string
  539. end
  540. @model.class_eval { get_db_schema(true) }
  541. @state_machine = StateMachine::Machine.new(@model, :initial => :parked)
  542. @status_machine = StateMachine::Machine.new(@model, :status, :initial => :idling)
  543. end
  544. def test_should_should_initialize_each_state
  545. record = @model.new
  546. assert_equal 'parked', record.state
  547. assert_equal 'idling', record.status
  548. end
  549. end
  550. class MachineWithAliasedAttributeTest < BaseTestCase
  551. def setup
  552. @model = new_model do
  553. alias_method :vehicle_status, :state
  554. alias_method :vehicle_status=, :state=
  555. end
  556. @machine = StateMachine::Machine.new(@model, :status, :attribute => :vehicle_status)
  557. @machine.state :parked
  558. @record = @model.new
  559. end
  560. def test_should_add_validation_errors_to_custom_attribute
  561. @record.vehicle_status = 'invalid'
  562. assert !@record.valid?
  563. assert_equal ['is invalid'], @record.errors.on(:vehicle_status)
  564. @record.vehicle_status = 'parked'
  565. assert @record.valid?
  566. end
  567. end
  568. class MachineWithLoopbackTest < BaseTestCase
  569. def setup
  570. @model = new_model do
  571. # Simulate timestamps plugin
  572. define_method(:before_update) do
  573. changed_columns = self.changed_columns.dup
  574. super()
  575. self.updated_at = Time.now if changed_columns.any?
  576. end
  577. end
  578. DB.alter_table(@model.table_identifier) do
  579. add_column :updated_at, :datetime
  580. end
  581. @model.class_eval { get_db_schema(true) }
  582. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  583. @machine.event :park
  584. @record = @model.create(:updated_at => Time.now - 1)
  585. @transition = StateMachine::Transition.new(@record, @machine, :park, :parked, :parked)
  586. @timestamp = @record.updated_at
  587. @transition.perform
  588. end
  589. def test_should_update_record
  590. assert_not_equal @timestamp, @record.updated_at
  591. end
  592. end
  593. class MachineWithDirtyAttributesTest < BaseTestCase
  594. def setup
  595. @model = new_model
  596. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  597. @machine.event :ignite
  598. @machine.state :idling
  599. @record = @model.create
  600. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  601. @transition.perform(false)
  602. end
  603. def test_should_include_state_in_changed_attributes
  604. assert_equal [:state], @record.changed_columns
  605. end
  606. def test_should_not_have_changes_when_loaded_from_database
  607. record = @model[@record.id]
  608. assert record.changed_columns.empty?
  609. end
  610. end
  611. class MachineWithDirtyAttributesDuringLoopbackTest < BaseTestCase
  612. def setup
  613. @model = new_model
  614. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  615. @machine.event :park
  616. @record = @model.create
  617. @transition = StateMachine::Transition.new(@record, @machine, :park, :parked, :parked)
  618. @transition.perform(false)
  619. end
  620. def test_should_include_state_in_changed_attributes
  621. assert_equal [:state], @record.changed_columns
  622. end
  623. end
  624. class MachineWithDirtyAttributesAndCustomAttributeTest < BaseTestCase
  625. def setup
  626. @model = new_model
  627. DB.alter_table(@model.table_identifier) do
  628. add_column :status, :string
  629. end
  630. @model.class_eval { get_db_schema(true) }
  631. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  632. @machine.event :ignite
  633. @machine.state :idling
  634. @record = @model.create
  635. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  636. @transition.perform(false)
  637. end
  638. def test_should_include_state_in_changed_attributes
  639. assert_equal [:status], @record.changed_columns
  640. end
  641. end
  642. class MachineWithDirtyAttributeAndCustomAttributesDuringLoopbackTest < BaseTestCase
  643. def setup
  644. @model = new_model
  645. DB.alter_table(@model.table_identifier) do
  646. add_column :status, :string
  647. end
  648. @model.class_eval { get_db_schema(true) }
  649. @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
  650. @machine.event :park
  651. @record = @model.create
  652. @transition = StateMachine::Transition.new(@record, @machine, :park, :parked, :parked)
  653. @transition.perform(false)
  654. end
  655. def test_should_include_state_in_changed_attributes
  656. assert_equal [:status], @record.changed_columns
  657. end
  658. end
  659. class MachineWithDirtyAttributeAndStateEventsTest < BaseTestCase
  660. def setup
  661. @model = new_model
  662. @machine = StateMachine::Machine.new(@model, :initial => :parked)
  663. @machine.event :ignite
  664. @record = @model.create
  665. @record.state_event = 'ignite'
  666. end
  667. def test_should_include_state_in_changed_attributes
  668. assert_equal [:state], @record.changed_columns
  669. end
  670. def test_should_not_include_state_in_changed_attributes_if_nil
  671. @record = @model.create
  672. @record.state_event = nil
  673. assert_equal [], @record.changed_columns
  674. end
  675. end
  676. class MachineWithoutTransactionsTest < BaseTestCase
  677. def setup
  678. @model = new_model
  679. @machine = StateMachine::Machine.new(@model, :use_transactions => false)
  680. end
  681. def test_should_not_rollback_transaction_if_false
  682. @machine.within_transaction(@model.new) do
  683. @model.create
  684. false
  685. end
  686. assert_equal 1, @model.count
  687. end
  688. def test_should_not_rollback_transaction_if_true
  689. @machine.within_transaction(@model.new) do
  690. @model.create
  691. true
  692. end
  693. assert_equal 1, @model.count
  694. end
  695. end
  696. class MachineWithTransactionsTest < BaseTestCase
  697. def setup
  698. @model = new_model
  699. @machine = StateMachine::Machine.new(@model, :use_transactions => true)
  700. end
  701. def test_should_rollback_transaction_if_false
  702. @machine.within_transaction(@model.new) do
  703. @model.create
  704. false
  705. end
  706. assert_equal 0, @model.count
  707. end
  708. def test_should_not_rollback_transaction_if_true
  709. @machine.within_transaction(@model.new) do
  710. @model.create
  711. true
  712. end
  713. assert_equal 1, @model.count
  714. end
  715. end
  716. class MachineWithCallbacksTest < BaseTestCase
  717. def setup
  718. @model = new_model
  719. @machine = StateMachine::Machine.new(@model)
  720. @machine.state :parked, :idling
  721. @machine.event :ignite
  722. @record = @model.new(:state => 'parked')
  723. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  724. end
  725. def test_should_run_before_callbacks
  726. called = false
  727. @machine.before_transition {called = true}
  728. @transition.perform
  729. assert called
  730. end
  731. def test_should_pass_transition_to_before_callbacks_with_one_argument
  732. transition = nil
  733. @machine.before_transition {|arg| transition = arg}
  734. @transition.perform
  735. assert_equal @transition, transition
  736. end
  737. def test_should_pass_transition_to_before_callbacks_with_multiple_arguments
  738. callback_args = nil
  739. @machine.before_transition {|*args| callback_args = args}
  740. @transition.perform
  741. assert_equal [@transition], callback_args
  742. end
  743. def test_should_run_before_callbacks_within_the_context_of_the_record
  744. context = nil
  745. @machine.before_transition {context = self}
  746. @transition.perform
  747. assert_equal @record, context
  748. end
  749. def test_should_run_after_callbacks
  750. called = false
  751. @machine.after_transition {called = true}
  752. @transition.perform
  753. assert called
  754. end
  755. def test_should_pass_transition_to_after_callbacks_with_multiple_arguments
  756. callback_args = nil
  757. @machine.after_transition {|*args| callback_args = args}
  758. @transition.perform
  759. assert_equal [@transition], callback_args
  760. end
  761. def test_should_run_after_callbacks_with_the_context_of_the_record
  762. context = nil
  763. @machine.after_transition {context = self}
  764. @transition.perform
  765. assert_equal @record, context
  766. end
  767. def test_should_run_around_callbacks
  768. before_called = false
  769. after_called = false
  770. ensure_called = 0
  771. @machine.around_transition do |block|
  772. before_called = true
  773. begin
  774. block.call
  775. ensure
  776. ensure_called += 1
  777. end
  778. after_called = true
  779. end
  780. @transition.perform
  781. assert before_called
  782. assert after_called
  783. assert_equal ensure_called, 1
  784. end
  785. def test_should_run_around_callbacks_with_the_context_of_the_record
  786. context = nil
  787. @machine.around_transition {|block| context = self; block.call}
  788. @transition.perform
  789. assert_equal @record, context
  790. end
  791. def test_should_allow_symbolic_callbacks
  792. callback_args = nil
  793. klass = class << @record; self; end
  794. klass.send(:define_method, :after_ignite) do |*args|
  795. callback_args = args
  796. end
  797. @machine.before_transition(:after_ignite)
  798. @transition.perform
  799. assert_equal [@transition], callback_args
  800. end
  801. def test_should_allow_string_callbacks
  802. class << @record
  803. attr_reader :callback_result
  804. end
  805. @machine.before_transition('@callback_result = [1, 2, 3]')
  806. @transition.perform
  807. assert_equal [1, 2, 3], @record.callback_result
  808. end
  809. def test_should_run_in_expected_order
  810. expected = [
  811. :before_transition, :before_validation, :after_validation,
  812. :before_save, :before_create, :after_create, :after_save,
  813. :after_transition
  814. ]
  815. callbacks = []
  816. @model.before_validation { callbacks << :before_validation }
  817. @model.after_validation { callbacks << :after_validation }
  818. @model.before_save { callbacks << :before_save }
  819. @model.before_create { callbacks << :before_create }
  820. @model.after_create { callbacks << :after_create }
  821. @model.after_save { callbacks << :after_save }
  822. if @model.respond_to?(:after_commit)
  823. @model.after_commit { callbacks << :after_commit }
  824. expected << :after_commit
  825. end
  826. @machine.before_transition { callbacks << :before_transition }
  827. @machine.after_transition { callbacks << :after_transition }
  828. @transition.perform
  829. assert_equal expected, callbacks
  830. end
  831. end
  832. class MachineWithFailedBeforeCallbacksTest < BaseTestCase
  833. def setup
  834. callbacks = []
  835. @model = new_model
  836. @machine = StateMachine::Machine.new(@model)
  837. @machine.state :parked, :idling
  838. @machine.event :ignite
  839. @machine.before_transition {callbacks << :before_1; false}
  840. @machine.before_transition {callbacks << :before_2}
  841. @machine.after_transition {callbacks << :after}
  842. @machine.around_transition {|block| callbacks << :around_before; block.call; callbacks << :around_after}
  843. @record = @model.new(:state => 'parked')
  844. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  845. @result = @transition.perform
  846. @callbacks = callbacks
  847. end
  848. def test_should_not_be_successful
  849. assert !@result
  850. end
  851. def test_should_not_change_current_state
  852. assert_equal 'parked', @record.state
  853. end
  854. def test_should_not_run_action
  855. assert @record.new?
  856. end
  857. def test_should_not_run_further_callbacks
  858. assert_equal [:before_1], @callbacks
  859. end
  860. end
  861. class MachineNestedActionTest < BaseTestCase
  862. def setup
  863. @callbacks = []
  864. @model = new_model
  865. @machine = StateMachine::Machine.new(@model)
  866. @machine.event :ignite do
  867. transition :parked => :idling
  868. end
  869. @record = @model.new(:state => 'parked')
  870. end
  871. def test_should_allow_transition_prior_to_creation_if_skipping_action
  872. record = @record
  873. @model.before_create { record.ignite(false) }
  874. result = @record.save
  875. assert result
  876. assert_equal "idling", @record.state
  877. @record.reload
  878. assert_equal "idling", @record.state
  879. end
  880. if !defined?(Sequel::VERSION) || !%w(2.10.0 2.11.0).include?(Sequel::VERSION)
  881. def test_should_allow_transition_after_creation
  882. record = @record
  883. @model.after_create { record.ignite }
  884. result = @record.save
  885. assert result
  886. assert_equal "idling", @record.state
  887. @record.reload
  888. assert_equal "idling", @record.state
  889. end
  890. end
  891. end
  892. class MachineWithFailedActionTest < BaseTestCase
  893. def setup
  894. @model = new_model do
  895. def validate
  896. super
  897. errors[:state] << 'is invalid' unless %w(first_gear).include?(state)
  898. end
  899. end
  900. @machine = StateMachine::Machine.new(@model)
  901. @machine.state :parked, :idling
  902. @machine.event :ignite
  903. callbacks = []
  904. @machine.before_transition {callbacks << :before}
  905. @machine.after_transition {callbacks << :after}
  906. @machine.after_failure {callbacks << :after_failure}
  907. @machine.around_transition {|block| callbacks << :around_before; block.call; callbacks << :around_after}
  908. @record = @model.new(:state => 'parked')
  909. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  910. @result = @transition.perform
  911. @callbacks = callbacks
  912. end
  913. def test_should_not_be_successful
  914. assert !@result
  915. end
  916. def test_should_not_change_current_state
  917. assert_equal 'parked', @record.state
  918. end
  919. def test_should_not_save_record
  920. assert @record.new?
  921. end
  922. def test_should_run_before_callbacks_and_after_callbacks_with_failures
  923. assert_equal [:before, :around_before, :after_failure], @callbacks
  924. end
  925. end
  926. class MachineWithFailedAfterCallbacksTest < BaseTestCase
  927. def setup
  928. callbacks = []
  929. @model = new_model
  930. @machine = StateMachine::Machine.new(@model)
  931. @machine.state :parked, :idling
  932. @machine.event :ignite
  933. @machine.after_transition {callbacks << :after_1; false}
  934. @machine.after_transition {callbacks << :after_2}
  935. @machine.around_transition {|block| callbacks << :around_before; block.call; callbacks << :around_after}
  936. @record = @model.new(:state => 'parked')
  937. @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
  938. @result = @transition.perform
  939. @callbacks = callbacks
  940. end
  941. def test_should_be_successful
  942. assert @result
  943. end
  944. def test_should_change_current_state
  945. assert_equal 'idling', @record.state
  946. end
  947. def test_should_save_record
  948. assert !@record.new?
  949. end
  950. def test_should_not_run_further_after_callbacks
  951. assert_equal [:around_before, :around_after, :after_1], @callbacks
  952. end
  953. end
  954. class MachineWithValidationsTest < BaseTestCase
  955. def setup
  956. @model = new_model
  957. @machine = StateMachine::Machine.new(@model)
  958. @machine.state :parked
  959. @record = @model.new
  960. end
  961. def test_should_invalidate_using_errors
  962. @record.state = 'parked'
  963. @machine.invalidate(@record, :state, :invalid_transition, [[:event, 'park']])
  964. assert_equal ['cannot transition via "park"'], @record.errors.on(:state)
  965. end
  966. def test_should_auto_prefix_custom_attributes_on_invalidation
  967. @machine.invalidate(@record, :event, :invalid)
  968. assert_equal ['is invalid'], @record.errors.on(:state_event)
  969. end
  970. def test_should_clear_errors_on_reset
  971. @record.state = 'parked'
  972. @record.errors.add(:state, 'is invalid')
  973. @machine.reset(@record)
  974. assert_nil @record.errors.on(:id)
  975. end
  976. def test_should_be_valid_if_state_is_known
  977. @record.state = 'parked'
  978. assert @record.valid?
  979. end
  980. def test_should_not_be_valid_if_state_is_unknown
  981. @record.state = 'invalid'
  982. assert !@record.valid?
  983. assert_equal ['state is invalid'], @record.errors.full_messages
  984. end
  985. end
  986. class MachineWithValidationsAndCustomAttributeTest < BaseTestCase
  987. def setup
  988. @model = new_model do
  989. alias_method :status, :state
  990. alias_method :status=, :state=
  991. end
  992. @machine = StateMachine::Machine.new(@model, :status, :attribute => :state)
  993. @machine.state :parked
  994. @record = @model.new
  995. end
  996. def test_should_add_validation_errors_to_custom_attribute
  997. @record.state = 'invalid'
  998. assert !@record.valid?
  999. assert_equal ['state is invalid'], @record.errors.full_messages
  1000. @record.state = 'parked'
  1001. assert @record.valid?
  1002. end
  1003. end
  1004. class MachineErrorsTest < BaseTestCase
  1005. def setup
  1006. @model = new_model
  1007. @machine = StateMachine::Machine.new(@model)
  1008. @record = @model.new
  1009. end
  1010. def test_should_be_able_to_describe_current_errors
  1011. @record.errors.add(:id, 'cannot be blank')
  1012. @record.errors.add(:state, 'is invalid')
  1013. assert_equal ['id cannot be blank', 'state is invalid'], @machine.errors_for(@record).split(', ').sort
  1014. end
  1015. def test_should_describe_as_halted_with_no_errors
  1016. assert_equal 'Transition halted', @machine.errors_for(@record)
  1017. end
  1018. end
  1019. class MachineWithStateDrivenValidationsTest < BaseTestCase
  1020. def setup
  1021. @model = new_model do
  1022. attr_accessor :seatbelt
  1023. end
  1024. @machine = StateMachine::Machine.new(@model)
  1025. @machine.state :first_gear do
  1026. def validate
  1027. super if defined?(super)
  1028. errors[:seatbelt] << 'is not present' if seatbelt.nil?
  1029. end
  1030. end
  1031. @machine.other_states :parked
  1032. end
  1033. def test_should_be_valid_if_validation_fails_outside_state_scope
  1034. record = @model.new(:state => 'parked', :seatbelt => nil)
  1035. assert record.valid?
  1036. end
  1037. def test_should_be_invalid_if_validation_fails_within_state_scope
  1038. record = @model.new(:state => 'first_gear', :seatbelt => nil)
  1039. assert !record.valid?
  1040. end
  1041. def test_should_be_valid_if_validation_succeeds_within_state_scope
  1042. record = @model.new(:state => 'first_gear', :seatbelt => true)
  1043. assert record.valid?
  1044. end
  1045. end
  1046. class MachineWithEventAttributesOnValidationTest < BaseTestCase
  1047. def setup
  1048. @model = new_model
  1049. @machine = StateMachine::Machine.new(@model)
  1050. @machine.event :ignite do
  1051. transition :parked => :idling
  1052. end
  1053. @record = @model.new
  1054. @record.state = 'parked'
  1055. @record.state_event = 'ignite'
  1056. end
  1057. def test_should_fail_if_event_is_invalid
  1058. @record.state_event = 'invalid'
  1059. assert !@record.valid?
  1060. assert_equal ['state_event is invalid'], @record.errors.full_messages
  1061. end
  1062. def test_should_fail_if_event_has_no_transition
  1063. @record.state = 'idling'
  1064. assert !@record.valid?
  1065. assert_equal ['state_event cannot transition when idling'], @record.errors.full_messages
  1066. end
  1067. def test_should_be_successful_if_event_has_transition
  1068. assert @record.valid?
  1069. end
  1070. def test_should_run_before_callbacks
  1071. ran_callback = false
  1072. @machine.before_transition { ran_callback = true }
  1073. @record.valid?
  1074. assert ran_callback
  1075. end
  1076. def test_should_run_around_callbacks_before_yield
  1077. ran_callback = false
  1078. @machine.around_transition {|block| ran_callback = true; block.call }
  1079. begin
  1080. @record.valid?
  1081. rescue ArgumentError
  1082. raise if StateMachine::Transition.pause_supported?
  1083. end
  1084. assert ran_callback
  1085. end
  1086. def test_should_persist_new_state
  1087. @record.valid?
  1088. assert_equal 'idling', @record.state
  1089. end
  1090. def test_should_not_run_after_callbacks
  1091. ran_callback = false
  1092. @machine.after_transition { ran_callback = true }
  1093. @record.valid?
  1094. assert !ran_callback
  1095. end
  1096. def test_should_not_run_after_callbacks_with_failures_disabled_if_validation_fails
  1097. @model.class_eval do
  1098. attr_accessor :seatbelt
  1099. def validate
  1100. super
  1101. errors[:seatbelt] << 'is not present' if seatbelt.nil?
  1102. end
  1103. end
  1104. ran_callback = false
  1105. @machine.after_transition { ran_callback = true }
  1106. @record.valid?
  1107. assert !ran_callback
  1108. end
  1109. def test_should_run_failure_callbacks_if_validation_fails
  1110. @model.class_eval do
  1111. attr_accessor :seatbelt
  1112. def validate
  1113. super
  1114. errors[:seatbelt] << 'is not present' if seatbelt.nil?
  1115. end
  1116. end
  1117. ran_callback = false
  1118. @machine.after_failure { ran_callback = true }
  1119. @record.valid?
  1120. assert ran_callback
  1121. end
  1122. def test_should_not_run_around_callbacks_after_yield
  1123. ran_callback = [false]
  1124. @machine.around_transition {|block| block.call; ran_callback[0] = true }
  1125. begin
  1126. @record.valid?
  1127. rescue ArgumentError
  1128. raise if StateMachine::Transition.pause_supported?
  1129. end
  1130. assert !ran_callback[0]
  1131. end
  1132. def test_should_not_run_around_callbacks_after_yield_with_failures_disabled_if_validation_fails
  1133. @model.class_eval do
  1134. attr_accessor :seatbelt
  1135. def validate
  1136. super
  1137. errors[:seatbelt] << 'is not present' if seatbelt.nil?
  1138. end
  1139. end
  1140. ran_callback = [false]
  1141. @machine.around_transition {|block| block.call; ran_callback[0] = true }
  1142. begin
  1143. @record.valid?
  1144. rescue ArgumentError
  1145. raise if StateMachine::Transition.pause_supported?
  1146. end
  1147. assert !ran_callback[0]
  1148. end
  1149. def test_should_not_run_before_transitions_within_transaction
  1150. @machine.before_transition { self.class.create; raise Sequel::Error::Rollback }
  1151. begin
  1152. @record.valid?
  1153. rescue Sequel::Error::Rollback
  1154. end
  1155. assert_equal 1, @model.count
  1156. end
  1157. end
  1158. class MachineWithEventAttributesOnSaveTest < BaseTestCase
  1159. def setup
  1160. @model = new_model
  1161. @machine = StateMachine::Machine.new(@model)
  1162. @machine.event :ignite do
  1163. transition :parked => :idling
  1164. end
  1165. @record = @model.new
  1166. @record.state = 'parked'
  1167. @record.state_event = 'ignite'
  1168. end
  1169. def test_should_fail_if_event_is_invalid
  1170. @record.state_event = 'invalid'
  1171. assert !@record.save
  1172. end
  1173. def test_should_raise_exception_when_enabled_if_event_is_invalid
  1174. @record.state_event = 'invalid'
  1175. @model.raise_on_save_failure = true
  1176. if defined?(Sequel::BeforeHookFailed)
  1177. assert_raise(Sequel::BeforeHookFailed) { @record.save }
  1178. else
  1179. assert_raise(Sequel::Error) { @record.save }
  1180. end
  1181. end
  1182. def test_should_fail_if_event_has_no_transition
  1183. @record.state = 'idling'
  1184. assert !@record.save
  1185. end
  1186. def test_should_raise_exception_when_enabled_if_event_has_no_transition
  1187. @record.state = 'idling'
  1188. @model.raise_on_save_failure = true
  1189. if defined?(Sequel::BeforeHookFailed)
  1190. assert_raise(Sequel::BeforeHookFailed) { @record.save }
  1191. else
  1192. assert_raise(Sequel::Error) { @record.save }
  1193. end
  1194. end
  1195. def test_should_be_successful_if_event_has_transition
  1196. assert @record.save
  1197. end
  1198. def test_should_run_before_callbacks
  1199. ran_callback = false
  1200. @machine.before_transition { ran_callback = true }
  1201. @record.save
  1202. assert ran_callback
  1203. end
  1204. def test_should_run_before_callbacks_once
  1205. before_count = 0
  1206. @machine.before_transition { before_count += 1 }
  1207. @record.save
  1208. assert_equal 1, before_count
  1209. end
  1210. def test_should_run_around_callbacks_before_yield
  1211. ran_callback = false
  1212. @machine.around_transition {|block| ran_callback = true; block.call }
  1213. @record.save
  1214. assert ran_callback
  1215. end
  1216. def test_should_run_around_callbacks_before_yield_once
  1217. around_before_count = 0
  1218. @machine.around_transition {|block| around_before_count += 1; block.call }
  1219. @record.save
  1220. assert_equal 1, around_before_count
  1221. end
  1222. def test_should_persist_new_state
  1223. @record.save
  1224. assert_equal 'idling', @record.state
  1225. end
  1226. def test_should_run_after_callbacks
  1227. ran_callback = false
  1228. @machine.after_transition { ran_callback = true }
  1229. @record.save
  1230. assert ran_callback
  1231. end
  1232. def test_should_not_run_after_callbacks_with_failures_disabled_if_fails
  1233. @model.before_create {|record| false}
  1234. ran_callback = false
  1235. @machine.after_transition { ran_callback = true }
  1236. @record.save
  1237. assert !ran_callback
  1238. end
  1239. def test_should_run_failure_callbacks_if_fails
  1240. @model.before_create {|record| false}
  1241. ran_callback = false
  1242. @machine.after_failure { ran_callback = true }
  1243. @record.save
  1244. assert ran_callback
  1245. end
  1246. def test_should_run_before_transitions_within_transaction
  1247. @machine.before_transition { self.class.create; raise Sequel::Error::Rollback }
  1248. begin
  1249. @record.save
  1250. rescue Sequel::Error::Rollback
  1251. end
  1252. assert_equal 0, @model.count
  1253. end
  1254. def test_should_not_run_around_callbacks_with_failures_disabled_if_fails
  1255. @model.before_create {|record| false}
  1256. ran_callback = [false]
  1257. @machine.around_transition {|block| block.call; ran_callback[0] = true }
  1258. @record.save
  1259. assert !ran_callback[0]
  1260. end
  1261. def test_should_run_around_callbacks_after_yield
  1262. ran_callback = [false]
  1263. @machine.around_transition {|block| block.call; ran_callback[0] = true }
  1264. @record.save
  1265. assert ran_callback[0]
  1266. end
  1267. def test_should_run_after_transitions_within_transaction
  1268. @machine.after_transition { self.class.create; raise Sequel::Error::Rollback }
  1269. @record.save
  1270. assert_equal 0, @model.count
  1271. end
  1272. def test_should_run_around_transition_within_transaction
  1273. @machine.around_transition {|block| block.call; self.class.create; raise Sequel::Error::Rollback }
  1274. @record.save
  1275. assert_equal 0, @model.count
  1276. end
  1277. def test_should_allow_additional_transitions_to_new_state_in_after_transitions
  1278. @machine.event :park do
  1279. transition :idling => :parked
  1280. end
  1281. @machine.after_transition(:on => :ignite) { park }
  1282. @record.save
  1283. assert_equal 'parked', @record.state
  1284. @record.reload
  1285. assert_equal 'parked', @record.state
  1286. end
  1287. def test_should_allow_additional_transitions_to_previous_state_in_after_transitions
  1288. @machine.event :shift_up do
  1289. transition :idling => :first_gear
  1290. end
  1291. @machine.after_transition(:on => :ignite) { shift_up }
  1292. @record.save
  1293. assert_equal 'first_gear', @record.state
  1294. @record.reload
  1295. assert_equal 'first_gear', @record.state
  1296. end
  1297. def test_should_return_nil_on_manual_rollback
  1298. @machine.before_transition { raise Sequel::Error::Rollback }
  1299. assert_equal nil, @record.save
  1300. end
  1301. end
  1302. if defined?(Sequel::VERSION) && Gem::Version.new(Sequel::VERSION) >= Gem::Version.new('3.4.0')
  1303. class MachineWithEventAttributesOnAutosaveTest < BaseTestCase
  1304. def setup
  1305. @vehicle_model = new_model(:vehicle)
  1306. DB.alter_table(@vehicle_model.table_identifier) do
  1307. add_column :owner_id, :integer
  1308. end
  1309. @vehicle_model.class_eval { get_db_schema(true) }
  1310. SequelTest.const_set('Vehicle', @vehicle_model)
  1311. @owner_model = new_model(:owner) do
  1312. plugin :nested_attributes
  1313. end
  1314. SequelTest.const_set('Owner', @owner_model)
  1315. machine = StateMachine::Machine.new(@vehicle_model)
  1316. machine.event :ignite do
  1317. transition :parked => :idling
  1318. end
  1319. @owner = @owner_model.create
  1320. @vehicle = @vehicle_model.create(:state => 'parked', :owner_id => @owner.id)
  1321. end
  1322. def test_should_persist_many_association
  1323. @owner_model.one_to_many :vehicles, :class_name => 'SequelTest::Vehicle'
  1324. @owner_model.nested_attributes :vehicles
  1325. @owner.vehicles_attributes = [{:id => @vehicle.id, :state_event => 'ignite'}]
  1326. @owner.save
  1327. @vehicle.reload
  1328. assert_equal 'idling', @vehicle.state
  1329. end
  1330. if Gem::Version.new(Sequel::VERSION) >= Gem::Version.new('3.10.0')
  1331. def test_should_persist_one_association
  1332. @owner_model.one_to_one :vehicle, :class_name => 'SequelTest::Vehicle'
  1333. @owner_model.nested_attributes :vehicle
  1334. @owner.vehicle_attributes = {:id => @vehicle.id, :state_event => 'ignite'}
  1335. @owner.save
  1336. @vehicle.reload
  1337. assert_equal 'idling', @vehicle.state
  1338. end
  1339. end
  1340. def teardown
  1341. SequelTest.class_eval do
  1342. remove_const('Vehicle')
  1343. remove_const('Owner')
  1344. end
  1345. super
  1346. end
  1347. end
  1348. end
  1349. class MachineWithEventAttributesOnCustomActionTest < BaseTestCase
  1350. def setup
  1351. @superclass = new_model do
  1352. def persist
  1353. save
  1354. end
  1355. end
  1356. @model = Class.new(@superclass)
  1357. @machine = StateMachine::Machine.new(@model, :action => :persist)
  1358. @machine.event :ignite do
  1359. transition :parked => :idling
  1360. end
  1361. @record = @model.new
  1362. @record.state = 'parked'
  1363. @record.state_event = 'ignite'
  1364. end
  1365. def test_should_not_transition_on_valid?
  1366. @record.valid?
  1367. assert_equal 'parked', @record.state
  1368. end
  1369. def test_should_not_transition_on_save
  1370. @record.save
  1371. assert_equal 'parked', @record.state
  1372. end
  1373. def test_should_transition_on_custom_action
  1374. @record.persist
  1375. assert_equal 'idling', @record.state
  1376. end
  1377. end
  1378. class MachineWithScopesTest < BaseTestCase
  1379. def setup
  1380. @model = new_model
  1381. @machine = StateMachine::Machine.new(@model)
  1382. @machine.state :parked, :first_gear
  1383. @machine.state :idling, :value => lambda {'idling'}

Large files files are truncated, but you can click here to view the full file