activesupport 3.2.22.5 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +364 -135
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -4
- data/lib/active_support/backtrace_cleaner.rb +33 -25
- data/lib/active_support/basic_object.rb +7 -17
- data/lib/active_support/benchmarkable.rb +19 -15
- data/lib/active_support/buffered_logger.rb +9 -113
- data/lib/active_support/cache/file_store.rb +14 -14
- data/lib/active_support/cache/mem_cache_store.rb +24 -30
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/cache/strategy/local_cache.rb +48 -37
- data/lib/active_support/cache.rb +228 -183
- data/lib/active_support/callbacks.rb +201 -253
- data/lib/active_support/concern.rb +16 -23
- data/lib/active_support/concurrency/latch.rb +27 -0
- data/lib/active_support/configurable.rb +69 -12
- data/lib/active_support/core_ext/array/access.rb +17 -9
- data/lib/active_support/core_ext/array/conversions.rb +115 -55
- data/lib/active_support/core_ext/array/extract_options.rb +2 -2
- data/lib/active_support/core_ext/array/grouping.rb +21 -22
- data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
- data/lib/active_support/core_ext/array/wrap.rb +13 -16
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -24
- data/lib/active_support/core_ext/class/attribute.rb +40 -32
- data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
- data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
- data/lib/active_support/core_ext/class/subclasses.rb +11 -5
- data/lib/active_support/core_ext/date/calculations.rb +44 -187
- data/lib/active_support/core_ext/date/conversions.rb +16 -38
- data/lib/active_support/core_ext/date/zones.rb +25 -2
- data/lib/active_support/core_ext/date.rb +5 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +77 -62
- data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
- data/lib/active_support/core_ext/date_time/zones.rb +11 -8
- data/lib/active_support/core_ext/date_time.rb +4 -0
- data/lib/active_support/core_ext/enumerable.rb +26 -73
- data/lib/active_support/core_ext/file/atomic.rb +27 -11
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/hash/conversions.rb +145 -79
- data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
- data/lib/active_support/core_ext/hash/diff.rb +5 -4
- data/lib/active_support/core_ext/hash/except.rb +1 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
- data/lib/active_support/core_ext/hash/keys.rb +108 -24
- data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
- data/lib/active_support/core_ext/hash/slice.rb +12 -12
- data/lib/active_support/core_ext/hash.rb +0 -1
- data/lib/active_support/core_ext/integer/inflections.rb +13 -1
- data/lib/active_support/core_ext/integer/time.rb +17 -12
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
- data/lib/active_support/core_ext/load_error.rb +7 -5
- data/lib/active_support/core_ext/logger.rb +7 -23
- data/lib/active_support/core_ext/marshal.rb +21 -0
- data/lib/active_support/core_ext/module/aliasing.rb +8 -9
- data/lib/active_support/core_ext/module/anonymous.rb +2 -7
- data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
- data/lib/active_support/core_ext/module/delegation.rb +92 -49
- data/lib/active_support/core_ext/module/deprecation.rb +19 -3
- data/lib/active_support/core_ext/module/introspection.rb +17 -27
- data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
- data/lib/active_support/core_ext/module/remove_method.rb +1 -5
- data/lib/active_support/core_ext/module.rb +1 -3
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
- data/lib/active_support/core_ext/numeric/time.rb +6 -6
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +4 -4
- data/lib/active_support/core_ext/object/blank.rb +7 -23
- data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
- data/lib/active_support/core_ext/object/duplicable.rb +1 -30
- data/lib/active_support/core_ext/object/inclusion.rb +8 -7
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
- data/lib/active_support/core_ext/object/to_json.rb +8 -0
- data/lib/active_support/core_ext/object/to_param.rb +5 -2
- data/lib/active_support/core_ext/object/try.rb +46 -25
- data/lib/active_support/core_ext/object/with_options.rb +7 -8
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/proc.rb +3 -0
- data/lib/active_support/core_ext/range/conversions.rb +0 -2
- data/lib/active_support/core_ext/range/include_range.rb +3 -1
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +0 -2
- data/lib/active_support/core_ext/string/access.rb +95 -90
- data/lib/active_support/core_ext/string/conversions.rb +27 -38
- data/lib/active_support/core_ext/string/encoding.rb +6 -9
- data/lib/active_support/core_ext/string/filters.rb +24 -18
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +70 -60
- data/lib/active_support/core_ext/string/inquiry.rb +2 -2
- data/lib/active_support/core_ext/string/multibyte.rb +41 -64
- data/lib/active_support/core_ext/string/output_safety.rb +59 -51
- data/lib/active_support/core_ext/string/zones.rb +13 -0
- data/lib/active_support/core_ext/string.rb +2 -3
- data/lib/active_support/core_ext/struct.rb +6 -0
- data/lib/active_support/core_ext/thread.rb +74 -0
- data/lib/active_support/core_ext/time/calculations.rb +108 -184
- data/lib/active_support/core_ext/time/conversions.rb +27 -51
- data/lib/active_support/core_ext/time/marshal.rb +0 -27
- data/lib/active_support/core_ext/time/zones.rb +27 -17
- data/lib/active_support/core_ext/time.rb +5 -0
- data/lib/active_support/core_ext/uri.rb +13 -17
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/dependencies/autoload.rb +47 -20
- data/lib/active_support/dependencies.rb +160 -141
- data/lib/active_support/deprecation/behaviors.rb +44 -30
- data/lib/active_support/deprecation/instance_delegator.rb +24 -0
- data/lib/active_support/deprecation/method_wrappers.rb +33 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
- data/lib/active_support/deprecation/reporting.rb +40 -11
- data/lib/active_support/deprecation.rb +39 -14
- data/lib/active_support/descendants_tracker.rb +34 -19
- data/lib/active_support/duration.rb +6 -8
- data/lib/active_support/file_update_checker.rb +63 -47
- data/lib/active_support/gzip.rb +11 -5
- data/lib/active_support/hash_with_indifferent_access.rb +127 -42
- data/lib/active_support/i18n.rb +4 -0
- data/lib/active_support/i18n_railtie.rb +5 -22
- data/lib/active_support/inflections.rb +14 -12
- data/lib/active_support/inflector/inflections.rb +108 -71
- data/lib/active_support/inflector/methods.rb +181 -160
- data/lib/active_support/inflector/transliterate.rb +16 -17
- data/lib/active_support/json/decoding.rb +18 -17
- data/lib/active_support/json/encoding.rb +93 -39
- data/lib/active_support/json/variable.rb +10 -1
- data/lib/active_support/key_generator.rb +75 -0
- data/lib/active_support/lazy_load_hooks.rb +21 -19
- data/lib/active_support/locale/en.yml +100 -3
- data/lib/active_support/log_subscriber/test_helper.rb +18 -15
- data/lib/active_support/log_subscriber.rb +35 -52
- data/lib/active_support/logger.rb +57 -0
- data/lib/active_support/logger_silence.rb +24 -0
- data/lib/active_support/message_encryptor.rb +38 -35
- data/lib/active_support/message_verifier.rb +9 -15
- data/lib/active_support/multibyte/chars.rb +80 -333
- data/lib/active_support/multibyte/unicode.rb +74 -64
- data/lib/active_support/multibyte.rb +5 -28
- data/lib/active_support/notifications/fanout.rb +112 -18
- data/lib/active_support/notifications/instrumenter.rb +33 -14
- data/lib/active_support/notifications.rb +79 -26
- data/lib/active_support/number_helper.rb +637 -0
- data/lib/active_support/ordered_hash.rb +8 -190
- data/lib/active_support/ordered_options.rb +21 -23
- data/lib/active_support/per_thread_registry.rb +52 -0
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +12 -32
- data/lib/active_support/rescuable.rb +9 -4
- data/lib/active_support/string_inquirer.rb +13 -8
- data/lib/active_support/subscriber.rb +93 -0
- data/lib/active_support/tagged_logging.rb +51 -73
- data/lib/active_support/test_case.rb +46 -17
- data/lib/active_support/testing/assertions.rb +56 -26
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_lookup.rb +54 -0
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/deprecation.rb +0 -19
- data/lib/active_support/testing/isolation.rb +29 -58
- data/lib/active_support/testing/pending.rb +5 -43
- data/lib/active_support/testing/setup_and_teardown.rb +6 -92
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/time.rb +6 -21
- data/lib/active_support/time_with_zone.rb +80 -43
- data/lib/active_support/values/time_zone.rb +81 -60
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +9 -11
- data/lib/active_support/xml_mini/libxml.rb +1 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
- data/lib/active_support/xml_mini/nokogiri.rb +1 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
- data/lib/active_support/xml_mini/rexml.rb +6 -8
- data/lib/active_support/xml_mini.rb +35 -17
- data/lib/active_support.rb +8 -21
- metadata +104 -72
- data/lib/active_support/base64.rb +0 -54
- data/lib/active_support/core_ext/array/random_access.rb +0 -30
- data/lib/active_support/core_ext/date/freeze.rb +0 -33
- data/lib/active_support/core_ext/exception.rb +0 -3
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/float/rounding.rb +0 -19
- data/lib/active_support/core_ext/float.rb +0 -1
- data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
- data/lib/active_support/core_ext/io.rb +0 -15
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/synchronization.rb +0 -45
- data/lib/active_support/core_ext/process/daemon.rb +0 -23
- data/lib/active_support/core_ext/process.rb +0 -1
- data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
- data/lib/active_support/core_ext/range/cover.rb +0 -3
- data/lib/active_support/core_ext/rexml.rb +0 -46
- data/lib/active_support/core_ext/string/interpolation.rb +0 -2
- data/lib/active_support/core_ext/string/xchar.rb +0 -18
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
- data/lib/active_support/memoizable.rb +0 -116
- data/lib/active_support/multibyte/exceptions.rb +0 -8
- data/lib/active_support/multibyte/utils.rb +0 -60
- data/lib/active_support/ruby/shim.rb +0 -22
- data/lib/active_support/security_utils.rb +0 -27
- data/lib/active_support/testing/mochaing.rb +0 -7
- data/lib/active_support/testing/performance/jruby.rb +0 -115
- data/lib/active_support/testing/performance/rubinius.rb +0 -113
- data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
- data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
- data/lib/active_support/testing/performance/ruby.rb +0 -152
- data/lib/active_support/testing/performance.rb +0 -317
- data/lib/active_support/time/autoload.rb +0 -5
- data/lib/active_support/whiny_nil.rb +0 -24
|
@@ -1,30 +1,29 @@
|
|
|
1
|
+
require 'thread_safe'
|
|
1
2
|
require 'active_support/concern'
|
|
2
3
|
require 'active_support/descendants_tracker'
|
|
3
|
-
require 'active_support/core_ext/array/wrap'
|
|
4
4
|
require 'active_support/core_ext/class/attribute'
|
|
5
5
|
require 'active_support/core_ext/kernel/reporting'
|
|
6
6
|
require 'active_support/core_ext/kernel/singleton_class'
|
|
7
|
-
require 'active_support/core_ext/object/inclusion'
|
|
8
7
|
|
|
9
8
|
module ActiveSupport
|
|
10
|
-
#
|
|
11
|
-
# The typical use case is to have a base class define a set of callbacks
|
|
12
|
-
# to the other functionality it supplies, so that subclasses can
|
|
13
|
-
# that enhance or modify the base functionality without
|
|
14
|
-
# or redefine methods of the base class.
|
|
9
|
+
# Callbacks are code hooks that are run at key points in an object's lifecycle.
|
|
10
|
+
# The typical use case is to have a base class define a set of callbacks
|
|
11
|
+
# relevant to the other functionality it supplies, so that subclasses can
|
|
12
|
+
# install callbacks that enhance or modify the base functionality without
|
|
13
|
+
# needing to override or redefine methods of the base class.
|
|
15
14
|
#
|
|
16
|
-
# Mixing in this module allows you to define the events in the object's
|
|
17
|
-
# that will support callbacks (via +ClassMethods.define_callbacks+),
|
|
18
|
-
# methods, procs, or callback objects to be called (via
|
|
19
|
-
# and run the installed callbacks at the
|
|
15
|
+
# Mixing in this module allows you to define the events in the object's
|
|
16
|
+
# lifecycle that will support callbacks (via +ClassMethods.define_callbacks+),
|
|
17
|
+
# set the instance methods, procs, or callback objects to be called (via
|
|
18
|
+
# +ClassMethods.set_callback+), and run the installed callbacks at the
|
|
19
|
+
# appropriate times (via +run_callbacks+).
|
|
20
20
|
#
|
|
21
|
-
# Three kinds of callbacks are supported: before callbacks, run before a
|
|
22
|
-
# after callbacks, run after the event; and around callbacks,
|
|
23
|
-
# event, triggering it when they yield. Callback code
|
|
24
|
-
# methods, procs or lambdas, or callback objects
|
|
25
|
-
# methods. See +ClassMethods.set_callback+
|
|
26
|
-
#
|
|
27
|
-
# ==== Example
|
|
21
|
+
# Three kinds of callbacks are supported: before callbacks, run before a
|
|
22
|
+
# certain event; after callbacks, run after the event; and around callbacks,
|
|
23
|
+
# blocks that surround the event, triggering it when they yield. Callback code
|
|
24
|
+
# can be contained in instance methods, procs or lambdas, or callback objects
|
|
25
|
+
# that respond to certain predetermined methods. See +ClassMethods.set_callback+
|
|
26
|
+
# for details.
|
|
28
27
|
#
|
|
29
28
|
# class Record
|
|
30
29
|
# include ActiveSupport::Callbacks
|
|
@@ -55,7 +54,6 @@ module ActiveSupport
|
|
|
55
54
|
# saving...
|
|
56
55
|
# - save
|
|
57
56
|
# saved
|
|
58
|
-
#
|
|
59
57
|
module Callbacks
|
|
60
58
|
extend Concern
|
|
61
59
|
|
|
@@ -63,28 +61,29 @@ module ActiveSupport
|
|
|
63
61
|
extend ActiveSupport::DescendantsTracker
|
|
64
62
|
end
|
|
65
63
|
|
|
64
|
+
CALLBACK_FILTER_TYPES = [:before, :after, :around]
|
|
65
|
+
|
|
66
66
|
# Runs the callbacks for the given event.
|
|
67
67
|
#
|
|
68
68
|
# Calls the before and around callbacks in the order they were set, yields
|
|
69
|
-
# the block (if given one), and then runs the after callbacks in reverse
|
|
70
|
-
#
|
|
71
|
-
# method for each key. See +ClassMethods.define_callbacks+ for more information.
|
|
69
|
+
# the block (if given one), and then runs the after callbacks in reverse
|
|
70
|
+
# order.
|
|
72
71
|
#
|
|
73
|
-
# If the callback chain was halted, returns +false+. Otherwise returns the
|
|
74
|
-
# of the block, or +true+ if no block is given.
|
|
72
|
+
# If the callback chain was halted, returns +false+. Otherwise returns the
|
|
73
|
+
# result of the block, or +true+ if no block is given.
|
|
75
74
|
#
|
|
76
75
|
# run_callbacks :save do
|
|
77
76
|
# save
|
|
78
77
|
# end
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
send(
|
|
78
|
+
def run_callbacks(kind, &block)
|
|
79
|
+
runner_name = self.class.__define_callbacks(kind, self)
|
|
80
|
+
send(runner_name, &block)
|
|
82
81
|
end
|
|
83
82
|
|
|
84
83
|
private
|
|
85
84
|
|
|
86
85
|
# A hook invoked everytime a before callback is halted.
|
|
87
|
-
# This can be
|
|
86
|
+
# This can be overridden in AS::Callback implementors in order
|
|
88
87
|
# to provide better debugging/logging.
|
|
89
88
|
def halted_callback_hook(filter)
|
|
90
89
|
end
|
|
@@ -92,41 +91,37 @@ module ActiveSupport
|
|
|
92
91
|
class Callback #:nodoc:#
|
|
93
92
|
@@_callback_sequence = 0
|
|
94
93
|
|
|
95
|
-
attr_accessor :chain, :filter, :kind, :options, :
|
|
94
|
+
attr_accessor :chain, :filter, :kind, :options, :klass, :raw_filter
|
|
96
95
|
|
|
97
96
|
def initialize(chain, filter, kind, options, klass)
|
|
98
97
|
@chain, @kind, @klass = chain, kind, klass
|
|
98
|
+
deprecate_per_key_option(options)
|
|
99
99
|
normalize_options!(options)
|
|
100
100
|
|
|
101
|
-
@per_key = options.delete(:per_key)
|
|
102
101
|
@raw_filter, @options = filter, options
|
|
103
102
|
@filter = _compile_filter(filter)
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
recompile_options!
|
|
104
|
+
end
|
|
106
105
|
|
|
107
|
-
|
|
106
|
+
def deprecate_per_key_option(options)
|
|
107
|
+
if options[:per_key]
|
|
108
|
+
raise NotImplementedError, ":per_key option is no longer supported. Use generic :if and :unless options instead."
|
|
109
|
+
end
|
|
108
110
|
end
|
|
109
111
|
|
|
110
112
|
def clone(chain, klass)
|
|
111
113
|
obj = super()
|
|
112
114
|
obj.chain = chain
|
|
113
115
|
obj.klass = klass
|
|
114
|
-
obj.per_key = @per_key.dup
|
|
115
116
|
obj.options = @options.dup
|
|
116
|
-
obj.per_key[:if] = @per_key[:if].dup
|
|
117
|
-
obj.per_key[:unless] = @per_key[:unless].dup
|
|
118
117
|
obj.options[:if] = @options[:if].dup
|
|
119
118
|
obj.options[:unless] = @options[:unless].dup
|
|
120
119
|
obj
|
|
121
120
|
end
|
|
122
121
|
|
|
123
122
|
def normalize_options!(options)
|
|
124
|
-
options[:if] = Array
|
|
125
|
-
options[:unless] = Array
|
|
126
|
-
|
|
127
|
-
options[:per_key] ||= {}
|
|
128
|
-
options[:per_key][:if] = Array.wrap(options[:per_key][:if])
|
|
129
|
-
options[:per_key][:unless] = Array.wrap(options[:per_key][:unless])
|
|
123
|
+
options[:if] = Array(options[:if])
|
|
124
|
+
options[:unless] = Array(options[:unless])
|
|
130
125
|
end
|
|
131
126
|
|
|
132
127
|
def name
|
|
@@ -141,44 +136,26 @@ module ActiveSupport
|
|
|
141
136
|
@kind == _kind && @filter == _filter
|
|
142
137
|
end
|
|
143
138
|
|
|
144
|
-
def
|
|
145
|
-
|
|
146
|
-
filter_options[:unless].push(new_options[:if]) if new_options.key?(:if)
|
|
139
|
+
def duplicates?(other)
|
|
140
|
+
matches?(other.kind, other.filter)
|
|
147
141
|
end
|
|
148
142
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
@callback_id = next_id
|
|
154
|
-
@filter = _compile_filter(@raw_filter)
|
|
155
|
-
@compiled_options = _compile_options(@options)
|
|
156
|
-
_compile_per_key_options
|
|
143
|
+
def _update_filter(filter_options, new_options)
|
|
144
|
+
filter_options[:if].concat(Array(new_options[:unless])) if new_options.key?(:unless)
|
|
145
|
+
filter_options[:unless].concat(Array(new_options[:if])) if new_options.key?(:if)
|
|
157
146
|
end
|
|
158
147
|
|
|
159
|
-
def
|
|
160
|
-
|
|
148
|
+
def recompile!(_options)
|
|
149
|
+
deprecate_per_key_option(_options)
|
|
150
|
+
_update_filter(self.options, _options)
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
def _one_time_conditions_valid_#{@callback_id}?
|
|
164
|
-
true if #{key_options}
|
|
165
|
-
end
|
|
166
|
-
RUBY_EVAL
|
|
152
|
+
recompile_options!
|
|
167
153
|
end
|
|
168
154
|
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
def start(key=nil, object=nil)
|
|
172
|
-
return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
|
|
173
|
-
|
|
174
|
-
# options[0] is the compiled form of supplied conditions
|
|
175
|
-
# options[1] is the "end" for the conditional
|
|
176
|
-
#
|
|
155
|
+
# Wraps code with filter
|
|
156
|
+
def apply(code)
|
|
177
157
|
case @kind
|
|
178
158
|
when :before
|
|
179
|
-
# if condition # before_save :filter_name, :if => :condition
|
|
180
|
-
# filter_name
|
|
181
|
-
# end
|
|
182
159
|
<<-RUBY_EVAL
|
|
183
160
|
if !halted && #{@compiled_options}
|
|
184
161
|
# This double assignment is to prevent warnings in 1.9.3 as
|
|
@@ -190,54 +167,20 @@ module ActiveSupport
|
|
|
190
167
|
halted_callback_hook(#{@raw_filter.inspect.inspect})
|
|
191
168
|
end
|
|
192
169
|
end
|
|
170
|
+
#{code}
|
|
193
171
|
RUBY_EVAL
|
|
194
|
-
when :around
|
|
195
|
-
# Compile around filters with conditions into proxy methods
|
|
196
|
-
# that contain the conditions.
|
|
197
|
-
#
|
|
198
|
-
# For `around_save :filter_name, :if => :condition':
|
|
199
|
-
#
|
|
200
|
-
# def _conditional_callback_save_17
|
|
201
|
-
# if condition
|
|
202
|
-
# filter_name do
|
|
203
|
-
# yield self
|
|
204
|
-
# end
|
|
205
|
-
# else
|
|
206
|
-
# yield self
|
|
207
|
-
# end
|
|
208
|
-
# end
|
|
209
|
-
#
|
|
210
|
-
name = "_conditional_callback_#{@kind}_#{next_id}"
|
|
211
|
-
@klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
212
|
-
def #{name}(halted)
|
|
213
|
-
if #{@compiled_options} && !halted
|
|
214
|
-
#{@filter} do
|
|
215
|
-
yield self
|
|
216
|
-
end
|
|
217
|
-
else
|
|
218
|
-
yield self
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
RUBY_EVAL
|
|
222
|
-
"#{name}(halted) do"
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
# This will supply contents for around and after filters, but not
|
|
227
|
-
# before filters (for the backward pass).
|
|
228
|
-
def end(key=nil, object=nil)
|
|
229
|
-
return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
|
|
230
|
-
|
|
231
|
-
case @kind
|
|
232
172
|
when :after
|
|
233
|
-
# after_save :filter_name, :if => :condition
|
|
234
173
|
<<-RUBY_EVAL
|
|
235
|
-
|
|
174
|
+
#{code}
|
|
175
|
+
if #{!chain.config[:skip_after_callbacks_if_terminated] || "!halted"} && #{@compiled_options}
|
|
236
176
|
#{@filter}
|
|
237
177
|
end
|
|
238
178
|
RUBY_EVAL
|
|
239
179
|
when :around
|
|
180
|
+
name = define_conditional_callback
|
|
240
181
|
<<-RUBY_EVAL
|
|
182
|
+
#{name}(halted) do
|
|
183
|
+
#{code}
|
|
241
184
|
value
|
|
242
185
|
end
|
|
243
186
|
RUBY_EVAL
|
|
@@ -246,46 +189,74 @@ module ActiveSupport
|
|
|
246
189
|
|
|
247
190
|
private
|
|
248
191
|
|
|
192
|
+
# Compile around filters with conditions into proxy methods
|
|
193
|
+
# that contain the conditions.
|
|
194
|
+
#
|
|
195
|
+
# For `set_callback :save, :around, :filter_name, if: :condition':
|
|
196
|
+
#
|
|
197
|
+
# def _conditional_callback_save_17
|
|
198
|
+
# if condition
|
|
199
|
+
# filter_name do
|
|
200
|
+
# yield self
|
|
201
|
+
# end
|
|
202
|
+
# else
|
|
203
|
+
# yield self
|
|
204
|
+
# end
|
|
205
|
+
# end
|
|
206
|
+
def define_conditional_callback
|
|
207
|
+
name = "_conditional_callback_#{@kind}_#{next_id}"
|
|
208
|
+
@klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
209
|
+
def #{name}(halted)
|
|
210
|
+
if #{@compiled_options} && !halted
|
|
211
|
+
#{@filter} do
|
|
212
|
+
yield self
|
|
213
|
+
end
|
|
214
|
+
else
|
|
215
|
+
yield self
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
RUBY_EVAL
|
|
219
|
+
name
|
|
220
|
+
end
|
|
221
|
+
|
|
249
222
|
# Options support the same options as filters themselves (and support
|
|
250
223
|
# symbols, string, procs, and objects), so compile a conditional
|
|
251
|
-
# expression based on the options
|
|
252
|
-
def
|
|
224
|
+
# expression based on the options.
|
|
225
|
+
def recompile_options!
|
|
253
226
|
conditions = ["true"]
|
|
254
227
|
|
|
255
228
|
unless options[:if].empty?
|
|
256
|
-
conditions << Array
|
|
229
|
+
conditions << Array(_compile_filter(options[:if]))
|
|
257
230
|
end
|
|
258
231
|
|
|
259
232
|
unless options[:unless].empty?
|
|
260
|
-
conditions << Array
|
|
233
|
+
conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"}
|
|
261
234
|
end
|
|
262
235
|
|
|
263
|
-
conditions.flatten.join(" && ")
|
|
236
|
+
@compiled_options = conditions.flatten.join(" && ")
|
|
264
237
|
end
|
|
265
238
|
|
|
266
239
|
# Filters support:
|
|
267
240
|
#
|
|
268
241
|
# Arrays:: Used in conditions. This is used to specify
|
|
269
242
|
# multiple conditions. Used internally to
|
|
270
|
-
# merge conditions from skip_* filters
|
|
271
|
-
# Symbols:: A method to call
|
|
272
|
-
# Strings:: Some content to evaluate
|
|
273
|
-
# Procs:: A proc to call with the object
|
|
274
|
-
# Objects:: An object with a before_foo method on it to call
|
|
243
|
+
# merge conditions from skip_* filters.
|
|
244
|
+
# Symbols:: A method to call.
|
|
245
|
+
# Strings:: Some content to evaluate.
|
|
246
|
+
# Procs:: A proc to call with the object.
|
|
247
|
+
# Objects:: An object with a <tt>before_foo</tt> method on it to call.
|
|
275
248
|
#
|
|
276
249
|
# All of these objects are compiled into methods and handled
|
|
277
250
|
# the same after this point:
|
|
278
251
|
#
|
|
279
|
-
# Arrays:: Merged together into a single filter
|
|
280
|
-
# Symbols:: Already methods
|
|
281
|
-
# Strings:: class_eval'ed into methods
|
|
282
|
-
# Procs:: define_method'ed into methods
|
|
252
|
+
# Arrays:: Merged together into a single filter.
|
|
253
|
+
# Symbols:: Already methods.
|
|
254
|
+
# Strings:: class_eval'ed into methods.
|
|
255
|
+
# Procs:: define_method'ed into methods.
|
|
283
256
|
# Objects::
|
|
284
257
|
# a method is created that calls the before_foo method
|
|
285
258
|
# on the object.
|
|
286
|
-
#
|
|
287
259
|
def _compile_filter(filter)
|
|
288
|
-
method_name = "_callback_#{@kind}_#{next_id}"
|
|
289
260
|
case filter
|
|
290
261
|
when Array
|
|
291
262
|
filter.map {|f| _compile_filter(f)}
|
|
@@ -294,15 +265,17 @@ module ActiveSupport
|
|
|
294
265
|
when String
|
|
295
266
|
"(#{filter})"
|
|
296
267
|
when Proc
|
|
268
|
+
method_name = "_callback_#{@kind}_#{next_id}"
|
|
297
269
|
@klass.send(:define_method, method_name, &filter)
|
|
298
270
|
return method_name if filter.arity <= 0
|
|
299
271
|
|
|
300
272
|
method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ")
|
|
301
273
|
else
|
|
274
|
+
method_name = "_callback_#{@kind}_#{next_id}"
|
|
302
275
|
@klass.send(:define_method, "#{method_name}_object") { filter }
|
|
303
276
|
|
|
304
277
|
_normalize_legacy_filter(kind, filter)
|
|
305
|
-
scopes = Array
|
|
278
|
+
scopes = Array(chain.config[:scope])
|
|
306
279
|
method_to_call = scopes.map{ |s| s.is_a?(Symbol) ? send(s) : s }.join("_")
|
|
307
280
|
|
|
308
281
|
@klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
@@ -317,10 +290,15 @@ module ActiveSupport
|
|
|
317
290
|
|
|
318
291
|
def _normalize_legacy_filter(kind, filter)
|
|
319
292
|
if !filter.respond_to?(kind) && filter.respond_to?(:filter)
|
|
293
|
+
message = "Filter object with #filter method is deprecated. Define method corresponding " \
|
|
294
|
+
"to filter type (#before, #after or #around)."
|
|
295
|
+
ActiveSupport::Deprecation.warn message
|
|
320
296
|
filter.singleton_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
321
297
|
def #{kind}(context, &block) filter(context, &block) end
|
|
322
298
|
RUBY_EVAL
|
|
323
|
-
elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around
|
|
299
|
+
elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around && !filter.respond_to?(:around)
|
|
300
|
+
message = "Filter object with #before and #after methods is deprecated. Define #around method instead."
|
|
301
|
+
ActiveSupport::Deprecation.warn message
|
|
324
302
|
def filter.around(context)
|
|
325
303
|
should_continue = before(context)
|
|
326
304
|
yield if should_continue
|
|
@@ -330,7 +308,7 @@ module ActiveSupport
|
|
|
330
308
|
end
|
|
331
309
|
end
|
|
332
310
|
|
|
333
|
-
# An Array with a compile method
|
|
311
|
+
# An Array with a compile method.
|
|
334
312
|
class CallbackChain < Array #:nodoc:#
|
|
335
313
|
attr_reader :name, :config
|
|
336
314
|
|
|
@@ -338,87 +316,86 @@ module ActiveSupport
|
|
|
338
316
|
@name = name
|
|
339
317
|
@config = {
|
|
340
318
|
:terminator => "false",
|
|
341
|
-
:rescuable => false,
|
|
342
319
|
:scope => [ :kind ]
|
|
343
|
-
}.merge(config)
|
|
320
|
+
}.merge!(config)
|
|
344
321
|
end
|
|
345
322
|
|
|
346
|
-
def compile
|
|
347
|
-
method =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
each do |callback|
|
|
352
|
-
method << callback.start(key, object)
|
|
323
|
+
def compile
|
|
324
|
+
method = ["value = nil", "halted = false"]
|
|
325
|
+
callbacks = "value = !halted && (!block_given? || yield)"
|
|
326
|
+
reverse_each do |callback|
|
|
327
|
+
callbacks = callback.apply(callbacks)
|
|
353
328
|
end
|
|
329
|
+
method << callbacks
|
|
354
330
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
end
|
|
331
|
+
method << "value"
|
|
332
|
+
method.join("\n")
|
|
333
|
+
end
|
|
359
334
|
|
|
360
|
-
|
|
335
|
+
def append(*callbacks)
|
|
336
|
+
callbacks.each { |c| append_one(c) }
|
|
337
|
+
end
|
|
361
338
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
method << "end"
|
|
366
|
-
end
|
|
339
|
+
def prepend(*callbacks)
|
|
340
|
+
callbacks.each { |c| prepend_one(c) }
|
|
341
|
+
end
|
|
367
342
|
|
|
368
|
-
|
|
369
|
-
method << callback.end(key, object)
|
|
370
|
-
end
|
|
343
|
+
private
|
|
371
344
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
345
|
+
def append_one(callback)
|
|
346
|
+
remove_duplicates(callback)
|
|
347
|
+
push(callback)
|
|
375
348
|
end
|
|
349
|
+
|
|
350
|
+
def prepend_one(callback)
|
|
351
|
+
remove_duplicates(callback)
|
|
352
|
+
unshift(callback)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def remove_duplicates(callback)
|
|
356
|
+
delete_if { |c| callback.duplicates?(c) }
|
|
357
|
+
end
|
|
358
|
+
|
|
376
359
|
end
|
|
377
360
|
|
|
378
361
|
module ClassMethods
|
|
379
|
-
# Generate the internal runner method called by +run_callbacks+.
|
|
380
|
-
def __define_runner(symbol) #:nodoc:
|
|
381
|
-
runner_method = "_run_#{symbol}_callbacks"
|
|
382
|
-
unless private_method_defined?(runner_method)
|
|
383
|
-
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
384
|
-
def #{runner_method}(key = nil, &blk)
|
|
385
|
-
self.class.__run_callback(key, :#{symbol}, self, &blk)
|
|
386
|
-
end
|
|
387
|
-
private :#{runner_method}
|
|
388
|
-
RUBY_EVAL
|
|
389
|
-
end
|
|
390
|
-
end
|
|
391
362
|
|
|
392
|
-
# This method
|
|
393
|
-
#
|
|
394
|
-
#
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
name = __callback_runner_name(key, kind)
|
|
363
|
+
# This method defines callback chain method for the given kind
|
|
364
|
+
# if it was not yet defined.
|
|
365
|
+
# This generated method plays caching role.
|
|
366
|
+
def __define_callbacks(kind, object) #:nodoc:
|
|
367
|
+
name = __callback_runner_name(kind)
|
|
398
368
|
unless object.respond_to?(name, true)
|
|
399
|
-
str = object.send("_#{kind}_callbacks").compile
|
|
369
|
+
str = object.send("_#{kind}_callbacks").compile
|
|
400
370
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
401
371
|
def #{name}() #{str} end
|
|
402
372
|
protected :#{name}
|
|
403
373
|
RUBY_EVAL
|
|
404
374
|
end
|
|
405
|
-
|
|
375
|
+
name
|
|
406
376
|
end
|
|
407
377
|
|
|
408
378
|
def __reset_runner(symbol)
|
|
409
|
-
name = __callback_runner_name(
|
|
379
|
+
name = __callback_runner_name(symbol)
|
|
410
380
|
undef_method(name) if method_defined?(name)
|
|
411
381
|
end
|
|
412
382
|
|
|
413
|
-
def
|
|
414
|
-
|
|
383
|
+
def __callback_runner_name_cache
|
|
384
|
+
@__callback_runner_name_cache ||= ThreadSafe::Cache.new {|cache, kind| cache[kind] = __generate_callback_runner_name(kind) }
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def __generate_callback_runner_name(kind)
|
|
388
|
+
"_run__#{self.name.hash.abs}__#{kind}__callbacks"
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def __callback_runner_name(kind)
|
|
392
|
+
__callback_runner_name_cache[kind]
|
|
415
393
|
end
|
|
416
394
|
|
|
417
395
|
# This is used internally to append, prepend and skip callbacks to the
|
|
418
396
|
# CallbackChain.
|
|
419
|
-
#
|
|
420
397
|
def __update_callbacks(name, filters = [], block = nil) #:nodoc:
|
|
421
|
-
type = filters.first
|
|
398
|
+
type = CALLBACK_FILTER_TYPES.include?(filters.first) ? filters.shift : :before
|
|
422
399
|
options = filters.last.is_a?(Hash) ? filters.pop : {}
|
|
423
400
|
filters.unshift(block) if block
|
|
424
401
|
|
|
@@ -432,8 +409,8 @@ module ActiveSupport
|
|
|
432
409
|
# Install a callback for the given event.
|
|
433
410
|
#
|
|
434
411
|
# set_callback :save, :before, :before_meth
|
|
435
|
-
# set_callback :save, :after, :after_meth, :
|
|
436
|
-
# set_callback :save, :around,
|
|
412
|
+
# set_callback :save, :after, :after_meth, if: :condition
|
|
413
|
+
# set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff }
|
|
437
414
|
#
|
|
438
415
|
# The second arguments indicates whether the callback is to be run +:before+,
|
|
439
416
|
# +:after+, or +:around+ the event. If omitted, +:before+ is assumed. This
|
|
@@ -441,53 +418,29 @@ module ActiveSupport
|
|
|
441
418
|
#
|
|
442
419
|
# set_callback :save, :before_meth
|
|
443
420
|
#
|
|
444
|
-
# The callback can specified as a symbol naming an instance method; as a
|
|
445
|
-
# lambda, or block; as a string to be instance evaluated; or as an
|
|
446
|
-
# responds to a certain method determined by the <tt>:scope</tt>
|
|
447
|
-
# +define_callback+.
|
|
421
|
+
# The callback can specified as a symbol naming an instance method; as a
|
|
422
|
+
# proc, lambda, or block; as a string to be instance evaluated; or as an
|
|
423
|
+
# object that responds to a certain method determined by the <tt>:scope</tt>
|
|
424
|
+
# argument to +define_callback+.
|
|
448
425
|
#
|
|
449
426
|
# If a proc, lambda, or block is given, its body is evaluated in the context
|
|
450
427
|
# of the current object. It can also optionally accept the current object as
|
|
451
428
|
# an argument.
|
|
452
429
|
#
|
|
453
|
-
# Before and around callbacks are called in the order that they are set;
|
|
454
|
-
# callbacks are called in the reverse order.
|
|
455
|
-
#
|
|
430
|
+
# Before and around callbacks are called in the order that they are set;
|
|
431
|
+
# after callbacks are called in the reverse order.
|
|
432
|
+
#
|
|
456
433
|
# Around callbacks can access the return value from the event, if it
|
|
457
434
|
# wasn't halted, from the +yield+ call.
|
|
458
435
|
#
|
|
459
436
|
# ===== Options
|
|
460
437
|
#
|
|
461
|
-
# * <tt>:if</tt> - A symbol naming an instance method or a proc; the
|
|
462
|
-
# will be called only when it returns a true value.
|
|
463
|
-
# * <tt>:unless</tt> - A symbol naming an instance method or a proc; the
|
|
464
|
-
# will be called only when it returns a false value.
|
|
465
|
-
# * <tt>:prepend</tt> - If true
|
|
466
|
-
# chain rather than appended.
|
|
467
|
-
# * <tt>:per_key</tt> - A hash with <tt>:if</tt> and <tt>:unless</tt> options;
|
|
468
|
-
# see "Per-key conditions" below.
|
|
469
|
-
#
|
|
470
|
-
# ===== Per-key conditions
|
|
471
|
-
#
|
|
472
|
-
# When creating or skipping callbacks, you can specify conditions that
|
|
473
|
-
# are always the same for a given key. For instance, in Action Pack,
|
|
474
|
-
# we convert :only and :except conditions into per-key conditions.
|
|
475
|
-
#
|
|
476
|
-
# before_filter :authenticate, :except => "index"
|
|
477
|
-
#
|
|
478
|
-
# becomes
|
|
479
|
-
#
|
|
480
|
-
# set_callback :process_action, :before, :authenticate, :per_key => {:unless => proc {|c| c.action_name == "index"}}
|
|
481
|
-
#
|
|
482
|
-
# Per-key conditions are evaluated only once per use of a given key.
|
|
483
|
-
# In the case of the above example, you would do:
|
|
484
|
-
#
|
|
485
|
-
# run_callbacks(:process_action, action_name) { ... dispatch stuff ... }
|
|
486
|
-
#
|
|
487
|
-
# In that case, each action_name would get its own compiled callback
|
|
488
|
-
# method that took into consideration the per_key conditions. This
|
|
489
|
-
# is a speed improvement for ActionPack.
|
|
490
|
-
#
|
|
438
|
+
# * <tt>:if</tt> - A symbol naming an instance method or a proc; the
|
|
439
|
+
# callback will be called only when it returns a +true+ value.
|
|
440
|
+
# * <tt>:unless</tt> - A symbol naming an instance method or a proc; the
|
|
441
|
+
# callback will be called only when it returns a +false+ value.
|
|
442
|
+
# * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
|
|
443
|
+
# existing chain rather than appended.
|
|
491
444
|
def set_callback(name, *filter_list, &block)
|
|
492
445
|
mapped = nil
|
|
493
446
|
|
|
@@ -496,23 +449,19 @@ module ActiveSupport
|
|
|
496
449
|
Callback.new(chain, filter, type, options.dup, self)
|
|
497
450
|
end
|
|
498
451
|
|
|
499
|
-
|
|
500
|
-
chain.delete_if {|c| c.matches?(type, filter) }
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
options[:prepend] ? chain.unshift(*(mapped.reverse)) : chain.push(*mapped)
|
|
452
|
+
options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped)
|
|
504
453
|
|
|
505
454
|
target.send("_#{name}_callbacks=", chain)
|
|
506
455
|
end
|
|
507
456
|
end
|
|
508
457
|
|
|
509
|
-
# Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
|
|
510
|
-
# options may be passed in order to control when the
|
|
458
|
+
# Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
|
|
459
|
+
# <tt>:unless</tt> options may be passed in order to control when the
|
|
460
|
+
# callback is skipped.
|
|
511
461
|
#
|
|
512
462
|
# class Writer < Person
|
|
513
|
-
# skip_callback :validate, :before, :check_membership, :
|
|
463
|
+
# skip_callback :validate, :before, :check_membership, if: -> { self.age > 18 }
|
|
514
464
|
# end
|
|
515
|
-
#
|
|
516
465
|
def skip_callback(name, *filter_list, &block)
|
|
517
466
|
__update_callbacks(name, filter_list, block) do |target, chain, type, filters, options|
|
|
518
467
|
filters.each do |filter|
|
|
@@ -521,7 +470,7 @@ module ActiveSupport
|
|
|
521
470
|
if filter && options.any?
|
|
522
471
|
new_filter = filter.clone(chain, self)
|
|
523
472
|
chain.insert(chain.index(filter), new_filter)
|
|
524
|
-
new_filter.recompile!(options
|
|
473
|
+
new_filter.recompile!(options)
|
|
525
474
|
end
|
|
526
475
|
|
|
527
476
|
chain.delete(filter)
|
|
@@ -531,7 +480,6 @@ module ActiveSupport
|
|
|
531
480
|
end
|
|
532
481
|
|
|
533
482
|
# Remove all set callbacks for the given event.
|
|
534
|
-
#
|
|
535
483
|
def reset_callbacks(symbol)
|
|
536
484
|
callbacks = send("_#{symbol}_callbacks")
|
|
537
485
|
|
|
@@ -554,24 +502,25 @@ module ActiveSupport
|
|
|
554
502
|
#
|
|
555
503
|
# ===== Options
|
|
556
504
|
#
|
|
557
|
-
# * <tt>:terminator</tt> - Determines when a before filter will halt the
|
|
558
|
-
# chain, preventing following callbacks from being called and
|
|
559
|
-
# triggered. This is a string to be eval'ed. The
|
|
560
|
-
# in the
|
|
505
|
+
# * <tt>:terminator</tt> - Determines when a before filter will halt the
|
|
506
|
+
# callback chain, preventing following callbacks from being called and
|
|
507
|
+
# the event from being triggered. This is a string to be eval'ed. The
|
|
508
|
+
# result of the callback is available in the +result+ variable.
|
|
561
509
|
#
|
|
562
|
-
# define_callbacks :validate, :
|
|
510
|
+
# define_callbacks :validate, terminator: 'result == false'
|
|
563
511
|
#
|
|
564
512
|
# In this example, if any before validate callbacks returns +false+,
|
|
565
|
-
# other callbacks are not executed. Defaults to
|
|
513
|
+
# other callbacks are not executed. Defaults to +false+, meaning no value
|
|
566
514
|
# halts the chain.
|
|
567
515
|
#
|
|
568
|
-
# * <tt>:
|
|
569
|
-
#
|
|
570
|
-
#
|
|
571
|
-
#
|
|
516
|
+
# * <tt>:skip_after_callbacks_if_terminated</tt> - Determines if after
|
|
517
|
+
# callbacks should be terminated by the <tt>:terminator</tt> option. By
|
|
518
|
+
# default after callbacks executed no matter if callback chain was
|
|
519
|
+
# terminated or not. Option makes sense only when <tt>:terminator</tt>
|
|
520
|
+
# option is specified.
|
|
572
521
|
#
|
|
573
|
-
# * <tt>:scope</tt> - Indicates which methods should be executed when an
|
|
574
|
-
# is used as a callback.
|
|
522
|
+
# * <tt>:scope</tt> - Indicates which methods should be executed when an
|
|
523
|
+
# object is used as a callback.
|
|
575
524
|
#
|
|
576
525
|
# class Audit
|
|
577
526
|
# def before(caller)
|
|
@@ -596,29 +545,28 @@ module ActiveSupport
|
|
|
596
545
|
# end
|
|
597
546
|
# end
|
|
598
547
|
#
|
|
599
|
-
# In the above case whenever you save an account the method
|
|
600
|
-
# be called. On the other hand
|
|
548
|
+
# In the above case whenever you save an account the method
|
|
549
|
+
# <tt>Audit#before</tt> will be called. On the other hand
|
|
601
550
|
#
|
|
602
|
-
# define_callbacks :save, :
|
|
551
|
+
# define_callbacks :save, scope: [:kind, :name]
|
|
603
552
|
#
|
|
604
|
-
# would trigger <tt>Audit#before_save</tt> instead. That's constructed
|
|
605
|
-
# <tt>#{kind}_#{name}</tt> on the given instance. In this
|
|
606
|
-
# "name" is "save". In this context +:kind+
|
|
607
|
-
#
|
|
608
|
-
#
|
|
553
|
+
# would trigger <tt>Audit#before_save</tt> instead. That's constructed
|
|
554
|
+
# by calling <tt>#{kind}_#{name}</tt> on the given instance. In this
|
|
555
|
+
# case "kind" is "before" and "name" is "save". In this context +:kind+
|
|
556
|
+
# and +:name+ have special meanings: +:kind+ refers to the kind of
|
|
557
|
+
# callback (before/after/around) and +:name+ refers to the method on
|
|
558
|
+
# which callbacks are being defined.
|
|
609
559
|
#
|
|
610
560
|
# A declaration like
|
|
611
561
|
#
|
|
612
|
-
# define_callbacks :save, :
|
|
562
|
+
# define_callbacks :save, scope: [:name]
|
|
613
563
|
#
|
|
614
564
|
# would call <tt>Audit#save</tt>.
|
|
615
|
-
#
|
|
616
565
|
def define_callbacks(*callbacks)
|
|
617
566
|
config = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
|
|
618
567
|
callbacks.each do |callback|
|
|
619
568
|
class_attribute "_#{callback}_callbacks"
|
|
620
569
|
send("_#{callback}_callbacks=", CallbackChain.new(callback, config))
|
|
621
|
-
__define_runner(callback)
|
|
622
570
|
end
|
|
623
571
|
end
|
|
624
572
|
end
|