state_machine 0.9.4 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +20 -0
- data/LICENSE +1 -1
- data/README.rdoc +74 -4
- data/Rakefile +3 -3
- data/lib/state_machine.rb +51 -24
- data/lib/state_machine/{guard.rb → branch.rb} +34 -40
- data/lib/state_machine/callback.rb +13 -18
- data/lib/state_machine/error.rb +13 -0
- data/lib/state_machine/eval_helpers.rb +3 -0
- data/lib/state_machine/event.rb +67 -30
- data/lib/state_machine/event_collection.rb +20 -3
- data/lib/state_machine/extensions.rb +3 -3
- data/lib/state_machine/integrations.rb +7 -0
- data/lib/state_machine/integrations/active_model.rb +149 -59
- data/lib/state_machine/integrations/active_model/versions.rb +30 -0
- data/lib/state_machine/integrations/active_record.rb +74 -148
- data/lib/state_machine/integrations/active_record/locale.rb +0 -7
- data/lib/state_machine/integrations/active_record/versions.rb +149 -0
- data/lib/state_machine/integrations/base.rb +64 -0
- data/lib/state_machine/integrations/data_mapper.rb +50 -39
- data/lib/state_machine/integrations/data_mapper/observer.rb +47 -12
- data/lib/state_machine/integrations/data_mapper/versions.rb +62 -0
- data/lib/state_machine/integrations/mongo_mapper.rb +37 -64
- data/lib/state_machine/integrations/mongo_mapper/locale.rb +4 -0
- data/lib/state_machine/integrations/mongo_mapper/versions.rb +102 -0
- data/lib/state_machine/integrations/mongoid.rb +297 -0
- data/lib/state_machine/integrations/mongoid/locale.rb +4 -0
- data/lib/state_machine/integrations/mongoid/versions.rb +18 -0
- data/lib/state_machine/integrations/sequel.rb +99 -55
- data/lib/state_machine/integrations/sequel/versions.rb +40 -0
- data/lib/state_machine/machine.rb +273 -136
- data/lib/state_machine/machine_collection.rb +21 -13
- data/lib/state_machine/node_collection.rb +6 -1
- data/lib/state_machine/path.rb +120 -0
- data/lib/state_machine/path_collection.rb +90 -0
- data/lib/state_machine/state.rb +28 -9
- data/lib/state_machine/state_collection.rb +1 -1
- data/lib/state_machine/transition.rb +65 -6
- data/lib/state_machine/transition_collection.rb +1 -1
- data/test/files/en.yml +8 -0
- data/test/functional/state_machine_test.rb +15 -2
- data/test/unit/branch_test.rb +890 -0
- data/test/unit/callback_test.rb +9 -36
- data/test/unit/error_test.rb +43 -0
- data/test/unit/event_collection_test.rb +67 -33
- data/test/unit/event_test.rb +165 -38
- data/test/unit/integrations/active_model_test.rb +103 -3
- data/test/unit/integrations/active_record_test.rb +90 -43
- data/test/unit/integrations/base_test.rb +87 -0
- data/test/unit/integrations/data_mapper_test.rb +105 -44
- data/test/unit/integrations/mongo_mapper_test.rb +261 -64
- data/test/unit/integrations/mongoid_test.rb +1529 -0
- data/test/unit/integrations/sequel_test.rb +33 -49
- data/test/unit/integrations_test.rb +4 -0
- data/test/unit/invalid_event_test.rb +15 -2
- data/test/unit/invalid_parallel_transition_test.rb +18 -0
- data/test/unit/invalid_transition_test.rb +72 -2
- data/test/unit/machine_collection_test.rb +55 -61
- data/test/unit/machine_test.rb +388 -26
- data/test/unit/node_collection_test.rb +14 -4
- data/test/unit/path_collection_test.rb +266 -0
- data/test/unit/path_test.rb +485 -0
- data/test/unit/state_collection_test.rb +30 -0
- data/test/unit/state_test.rb +82 -35
- data/test/unit/transition_collection_test.rb +48 -44
- data/test/unit/transition_test.rb +198 -41
- metadata +111 -74
- data/test/unit/guard_test.rb +0 -909
@@ -0,0 +1,30 @@
|
|
1
|
+
module StateMachine
|
2
|
+
module Integrations #:nodoc:
|
3
|
+
module ActiveModel
|
4
|
+
version '2.x' do
|
5
|
+
def self.active?
|
6
|
+
!defined?(::ActiveModel::VERSION) || ::ActiveModel::VERSION::MAJOR == 2
|
7
|
+
end
|
8
|
+
|
9
|
+
def define_validation_hook
|
10
|
+
action = self.action
|
11
|
+
define_helper(:instance, :valid?) do |machine, object, _super, *|
|
12
|
+
object.class.state_machines.transitions(object, action, :after => false).perform { _super.call }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
version '3.0.x' do
|
18
|
+
def self.active?
|
19
|
+
defined?(::ActiveModel::VERSION) && ::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR == 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_validation_hook
|
23
|
+
# +around+ callbacks don't have direct access to results until AS 3.1
|
24
|
+
owner_class.set_callback(:validation, :after, 'value', :prepend => true)
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'state_machine/integrations/active_model'
|
2
|
+
|
1
3
|
module StateMachine
|
2
4
|
module Integrations #:nodoc:
|
3
5
|
# Adds support for integrating state machines with ActiveRecord models.
|
@@ -219,15 +221,15 @@ module StateMachine
|
|
219
221
|
# *are* supported. For example, if a transition for a record's +state+
|
220
222
|
# attribute changes the state from +parked+ to +idling+ via the +ignite+
|
221
223
|
# event, the following observer methods are supported:
|
222
|
-
# * before/
|
223
|
-
# * before/
|
224
|
-
# * before/
|
225
|
-
# * before/
|
226
|
-
# * before/
|
227
|
-
# * before/
|
228
|
-
# * before/
|
229
|
-
# * before/
|
230
|
-
# * before/
|
224
|
+
# * before/after/after_failure_to-_ignite_from_parked_to_idling
|
225
|
+
# * before/after/after_failure_to-_ignite_from_parked
|
226
|
+
# * before/after/after_failure_to-_ignite_to_idling
|
227
|
+
# * before/after/after_failure_to-_ignite
|
228
|
+
# * before/after/after_failure_to-_transition_state_from_parked_to_idling
|
229
|
+
# * before/after/after_failure_to-_transition_state_from_parked
|
230
|
+
# * before/after/after_failure_to-_transition_state_to_idling
|
231
|
+
# * before/after/after_failure_to-_transition_state
|
232
|
+
# * before/after/after_failure_to-_transition
|
231
233
|
#
|
232
234
|
# The following class shows an example of some of these hooks:
|
233
235
|
#
|
@@ -313,8 +315,11 @@ module StateMachine
|
|
313
315
|
# events:
|
314
316
|
# park: 'estacionarse'
|
315
317
|
module ActiveRecord
|
318
|
+
include Base
|
316
319
|
include ActiveModel
|
317
320
|
|
321
|
+
require 'state_machine/integrations/active_record/versions'
|
322
|
+
|
318
323
|
# The default options to use for state machines using this integration
|
319
324
|
@defaults = {:action => :save}
|
320
325
|
|
@@ -327,83 +332,50 @@ module StateMachine
|
|
327
332
|
|
328
333
|
def self.extended(base) #:nodoc:
|
329
334
|
require 'active_record/version'
|
330
|
-
|
331
|
-
|
332
|
-
::ActiveRecord::Observer.class_eval do
|
333
|
-
include StateMachine::Integrations::ActiveModel::Observer
|
334
|
-
end unless ::ActiveRecord::Observer < StateMachine::Integrations::ActiveModel::Observer
|
335
|
-
|
336
|
-
if defined?(I18n)
|
337
|
-
locale = "#{File.dirname(__FILE__)}/active_record/locale.rb"
|
338
|
-
I18n.load_path.unshift(locale) unless I18n.load_path.include?(locale)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
# Adds a validation error to the given object
|
343
|
-
def invalidate(object, attribute, message, values = [])
|
344
|
-
if defined?(I18n)
|
345
|
-
super
|
346
|
-
else
|
347
|
-
object.errors.add(self.attribute(attribute), generate_message(message, values))
|
348
|
-
end
|
335
|
+
super
|
349
336
|
end
|
350
337
|
|
351
338
|
protected
|
352
|
-
#
|
353
|
-
def
|
354
|
-
|
355
|
-
end
|
356
|
-
|
357
|
-
# Always adds validation support
|
358
|
-
def supports_validations?
|
359
|
-
true
|
339
|
+
# The name of this integration
|
340
|
+
def integration
|
341
|
+
:active_record
|
360
342
|
end
|
361
343
|
|
362
|
-
#
|
363
|
-
def
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
# Only adds dirty tracking support if ActiveRecord supports it
|
368
|
-
def supports_dirty_tracking?(object)
|
369
|
-
defined?(::ActiveRecord::Dirty) && object.respond_to?("#{attribute}_changed?") || super
|
344
|
+
# Loads locale files needed for translations
|
345
|
+
def load_locale
|
346
|
+
load_i18n_version
|
347
|
+
super
|
370
348
|
end
|
371
349
|
|
372
|
-
#
|
373
|
-
|
374
|
-
|
350
|
+
# Loads the version of the i18n library so that that proper
|
351
|
+
# interpolation syntax can be used
|
352
|
+
def load_i18n_version
|
353
|
+
begin
|
354
|
+
require 'i18n/version'
|
355
|
+
rescue Exception => ex
|
356
|
+
end
|
375
357
|
end
|
376
358
|
|
377
|
-
#
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
{:default => @messages[message]}
|
384
|
-
end
|
359
|
+
# Loads extensions to ActiveRecord's Observers
|
360
|
+
def load_observer_extensions
|
361
|
+
super
|
362
|
+
::ActiveRecord::Observer.class_eval do
|
363
|
+
include StateMachine::Integrations::ActiveModel::Observer
|
364
|
+
end unless ::ActiveRecord::Observer < StateMachine::Integrations::ActiveModel::Observer
|
385
365
|
end
|
386
366
|
|
387
|
-
# Only
|
388
|
-
def
|
389
|
-
|
390
|
-
super
|
391
|
-
else
|
392
|
-
value ? value.to_s.humanize.downcase : 'nil'
|
393
|
-
end
|
367
|
+
# Only runs validations on the action if using <tt>:save</tt>
|
368
|
+
def runs_validations_on_action?
|
369
|
+
action == :save
|
394
370
|
end
|
395
371
|
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
|
400
|
-
|
401
|
-
|
372
|
+
# Only allows state initialization on new records that aren't being
|
373
|
+
# created with a set of attributes that includes this machine's
|
374
|
+
# attribute.
|
375
|
+
def initialize_state?(object, options)
|
376
|
+
if object.new_record? && !object.instance_variable_defined?('@initialized_state_machines')
|
377
|
+
object.instance_variable_set('@initialized_state_machines', true)
|
402
378
|
super
|
403
|
-
elsif ::ActiveRecord::VERSION::MINOR == 3 && ::ActiveRecord::VERSION::TINY >= 2
|
404
|
-
klass.self_and_descendants_from_active_record
|
405
|
-
else
|
406
|
-
klass.self_and_descendents_from_active_record
|
407
379
|
end
|
408
380
|
end
|
409
381
|
|
@@ -411,66 +383,37 @@ module StateMachine
|
|
411
383
|
# initial state of the machine *before* any attributes are set on the
|
412
384
|
# object
|
413
385
|
def define_state_initializer
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
if new_record? && !@initialized_state_machines
|
426
|
-
@initialized_state_machines = true
|
427
|
-
|
428
|
-
ignore = if new_attributes
|
429
|
-
attributes = new_attributes.dup
|
430
|
-
attributes.stringify_keys!
|
431
|
-
if ::ActiveRecord::VERSION::MAJOR >= 3
|
432
|
-
sanitize_for_mass_assignment(attributes).keys
|
433
|
-
else
|
434
|
-
remove_attributes_protected_from_mass_assignment(attributes).keys
|
435
|
-
end
|
436
|
-
else
|
437
|
-
[]
|
438
|
-
end
|
439
|
-
|
440
|
-
initialize_state_machines(:dynamic => false, :ignore => ignore)
|
441
|
-
super
|
442
|
-
initialize_state_machines(:dynamic => true, :ignore => ignore)
|
443
|
-
else
|
444
|
-
super
|
445
|
-
end
|
446
|
-
end
|
447
|
-
end_eval
|
386
|
+
# Ensure that the attributes setter gets used to force initialization
|
387
|
+
# of the state machines
|
388
|
+
define_helper(:instance, :initialize) do |machine, object, _super, *args|
|
389
|
+
_super.call(args.shift || {}, *args)
|
390
|
+
end
|
391
|
+
|
392
|
+
# Hooks in to attribute initialization to set the states *prior*
|
393
|
+
# to the attributes being set
|
394
|
+
define_helper(:instance, :attributes=) do |machine, object, _super, new_attributes, *|
|
395
|
+
object.class.state_machines.initialize_states(object, :attributes => new_attributes) { _super.call }
|
396
|
+
end
|
448
397
|
end
|
449
398
|
|
450
|
-
#
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
# Still use class_eval here instance of define_instance_method since
|
457
|
-
# we need to be able to call +super+
|
458
|
-
@instance_helper_module.class_eval do
|
459
|
-
define_method("#{name}?") do |*args|
|
460
|
-
args.empty? ? super(*args) : self.class.state_machine(name).states.matches?(self, *args)
|
461
|
-
end
|
399
|
+
# Uses around callbacks to run state events if using the :save hook
|
400
|
+
def define_action_hook
|
401
|
+
if action_hook == :save
|
402
|
+
owner_class.set_callback(:save, :around, self, :prepend => true)
|
403
|
+
else
|
404
|
+
super
|
462
405
|
end
|
463
406
|
end
|
464
407
|
|
465
|
-
#
|
466
|
-
def
|
467
|
-
|
408
|
+
# Runs state events around the machine's :save action
|
409
|
+
def around_save(object)
|
410
|
+
object.class.state_machines.transitions(object, action).perform { yield }
|
468
411
|
end
|
469
412
|
|
470
413
|
# Creates a scope for finding records *with* a particular state or
|
471
414
|
# states for the attribute
|
472
415
|
def create_with_scope(name)
|
473
|
-
define_scope(name, lambda {|values| {
|
416
|
+
define_scope(name, lambda {|values| {attribute => values}})
|
474
417
|
end
|
475
418
|
|
476
419
|
# Creates a scope for finding records *without* a particular state or
|
@@ -478,7 +421,7 @@ module StateMachine
|
|
478
421
|
def create_without_scope(name)
|
479
422
|
define_scope(name, lambda {|values|
|
480
423
|
connection = owner_class.connection
|
481
|
-
|
424
|
+
["#{connection.quote_table_name(owner_class.table_name)}.#{connection.quote_column_name(attribute)} NOT IN (?)", values]
|
482
425
|
})
|
483
426
|
end
|
484
427
|
|
@@ -489,33 +432,16 @@ module StateMachine
|
|
489
432
|
object.class.transaction {raise ::ActiveRecord::Rollback unless yield}
|
490
433
|
end
|
491
434
|
|
492
|
-
private
|
493
435
|
# Defines a new named scope with the given name
|
494
436
|
def define_scope(name, scope)
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
# being used within the evaluation of a dynamic named scope, the
|
504
|
-
# scope must be generated manually. It's necessary to have access
|
505
|
-
# to the model so that the state names can be translated to their
|
506
|
-
# associated values and so that inheritance is respected properly.
|
507
|
-
owner_class.named_scope(name)
|
508
|
-
owner_class.scopes[name] = lambda do |model, *states|
|
509
|
-
machine_states = model.state_machine(machine_name).states
|
510
|
-
values = states.flatten.map {|state| machine_states.fetch(state).value}
|
511
|
-
|
512
|
-
::ActiveRecord::NamedScope::Scope.new(model, scope.call(values))
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
# Prevent the Machine class from wrapping the scope
|
517
|
-
false
|
518
|
-
end
|
437
|
+
lambda {|model, values| model.where(scope.call(values))}
|
438
|
+
end
|
439
|
+
|
440
|
+
# ActiveModel's use of method_missing / respond_to for attribute methods
|
441
|
+
# breaks both ancestor lookups and defined?(super). Need to special-case
|
442
|
+
# the existence of query attribute methods.
|
443
|
+
def owner_class_ancestor_has_method?(method)
|
444
|
+
method == "#{name}?" || super
|
519
445
|
end
|
520
446
|
end
|
521
447
|
end
|
@@ -2,13 +2,6 @@ filename = "#{File.dirname(__FILE__)}/../active_model/locale.rb"
|
|
2
2
|
translations = eval(IO.read(filename), binding, filename)
|
3
3
|
translations[:en][:activerecord] = translations[:en].delete(:activemodel)
|
4
4
|
|
5
|
-
# Only ActiveRecord 2.3.5+ can pull i18n >= 0.1.3 from system-wide gems (and
|
6
|
-
# therefore possibly have I18n::VERSION available)
|
7
|
-
begin
|
8
|
-
require 'i18n/version'
|
9
|
-
rescue Exception => ex
|
10
|
-
end unless ::ActiveRecord::VERSION::MAJOR == 2 && (::ActiveRecord::VERSION::MINOR < 3 || ::ActiveRecord::VERSION::TINY < 5)
|
11
|
-
|
12
5
|
# Only i18n 0.4.0+ has the new %{key} syntax
|
13
6
|
if !defined?(I18n::VERSION) || I18n::VERSION < '0.4.0'
|
14
7
|
translations[:en][:activerecord][:errors][:messages].each do |key, message|
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module StateMachine
|
2
|
+
module Integrations #:nodoc:
|
3
|
+
module ActiveRecord
|
4
|
+
version '2.x' do
|
5
|
+
def self.active?
|
6
|
+
::ActiveRecord::VERSION::MAJOR == 2
|
7
|
+
end
|
8
|
+
|
9
|
+
def load_locale
|
10
|
+
super if defined?(I18n)
|
11
|
+
end
|
12
|
+
|
13
|
+
def define_scope(name, scope)
|
14
|
+
if owner_class.respond_to?(:named_scope)
|
15
|
+
name = name.to_sym
|
16
|
+
machine_name = self.name
|
17
|
+
|
18
|
+
# Since ActiveRecord does not allow direct access to the model
|
19
|
+
# being used within the evaluation of a dynamic named scope, the
|
20
|
+
# scope must be generated manually. It's necessary to have access
|
21
|
+
# to the model so that the state names can be translated to their
|
22
|
+
# associated values and so that inheritance is respected properly.
|
23
|
+
owner_class.named_scope(name)
|
24
|
+
owner_class.scopes[name] = lambda do |model, *states|
|
25
|
+
machine_states = model.state_machine(machine_name).states
|
26
|
+
values = states.flatten.map {|state| machine_states.fetch(state).value}
|
27
|
+
|
28
|
+
::ActiveRecord::NamedScope::Scope.new(model, :conditions => scope.call(values))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Prevent the Machine class from wrapping the scope
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def invalidate(object, attribute, message, values = [])
|
37
|
+
if defined?(I18n)
|
38
|
+
super
|
39
|
+
else
|
40
|
+
object.errors.add(self.attribute(attribute), generate_message(message, values))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def translate(klass, key, value)
|
45
|
+
if defined?(I18n)
|
46
|
+
super
|
47
|
+
else
|
48
|
+
value ? value.to_s.humanize.downcase : 'nil'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def supports_observers?
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
def supports_validations?
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def supports_mass_assignment_security?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def i18n_scope(klass)
|
65
|
+
:activerecord
|
66
|
+
end
|
67
|
+
|
68
|
+
def action_hook
|
69
|
+
action == :save ? :create_or_update : super
|
70
|
+
end
|
71
|
+
|
72
|
+
def filter_attributes(object, attributes)
|
73
|
+
object.send(:remove_attributes_protected_from_mass_assignment, attributes)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
version '2.0 - 2.2.x' do
|
78
|
+
def self.active?
|
79
|
+
::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR < 3
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_error_message_options(object, attribute, message)
|
83
|
+
{:default => @messages[message]}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
version '2.0 - 2.3.1' do
|
88
|
+
def self.active?
|
89
|
+
::ActiveRecord::VERSION::MAJOR == 2 && (::ActiveRecord::VERSION::MINOR < 3 || ::ActiveRecord::VERSION::TINY < 2)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ancestors_for(klass)
|
93
|
+
klass.self_and_descendents_from_active_record
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
version '2.0 - 2.3.4' do
|
98
|
+
def self.active?
|
99
|
+
::ActiveRecord::VERSION::MAJOR == 2 && (::ActiveRecord::VERSION::MINOR < 3 || ::ActiveRecord::VERSION::TINY < 5)
|
100
|
+
end
|
101
|
+
|
102
|
+
def load_i18n_version
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
version '2.0.x' do
|
107
|
+
def self.active?
|
108
|
+
::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR == 0
|
109
|
+
end
|
110
|
+
|
111
|
+
def supports_dirty_tracking?(object)
|
112
|
+
false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
version '2.1.x - 2.3.x' do
|
117
|
+
def self.active?
|
118
|
+
::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR > 0
|
119
|
+
end
|
120
|
+
|
121
|
+
def supports_dirty_tracking?(object)
|
122
|
+
object.respond_to?("#{attribute}_changed?")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
version '2.3.2 - 2.3.x' do
|
127
|
+
def self.active?
|
128
|
+
::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR == 3 && ::ActiveRecord::VERSION::TINY >= 2
|
129
|
+
end
|
130
|
+
|
131
|
+
def ancestors_for(klass)
|
132
|
+
klass.self_and_descendants_from_active_record
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
version '3.0.x' do
|
137
|
+
def self.active?
|
138
|
+
::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR == 0
|
139
|
+
end
|
140
|
+
|
141
|
+
def define_action_hook
|
142
|
+
# +around+ callbacks don't have direct access to results until AS 3.1
|
143
|
+
owner_class.set_callback(:save, :after, 'value', :prepend => true) if action_hook == :save
|
144
|
+
super
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|