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,5 +1,3 @@
|
|
|
1
|
-
require 'active_support/deprecation'
|
|
2
|
-
|
|
3
1
|
module ActiveSupport
|
|
4
2
|
# A typical module looks like this:
|
|
5
3
|
#
|
|
@@ -7,7 +5,7 @@ module ActiveSupport
|
|
|
7
5
|
# def self.included(base)
|
|
8
6
|
# base.extend ClassMethods
|
|
9
7
|
# base.class_eval do
|
|
10
|
-
# scope :disabled, where(:
|
|
8
|
+
# scope :disabled, -> { where(disabled: true) }
|
|
11
9
|
# end
|
|
12
10
|
# end
|
|
13
11
|
#
|
|
@@ -16,7 +14,8 @@ module ActiveSupport
|
|
|
16
14
|
# end
|
|
17
15
|
# end
|
|
18
16
|
#
|
|
19
|
-
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
|
17
|
+
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
|
18
|
+
# written as:
|
|
20
19
|
#
|
|
21
20
|
# require 'active_support/concern'
|
|
22
21
|
#
|
|
@@ -24,7 +23,7 @@ module ActiveSupport
|
|
|
24
23
|
# extend ActiveSupport::Concern
|
|
25
24
|
#
|
|
26
25
|
# included do
|
|
27
|
-
# scope :disabled, where(:
|
|
26
|
+
# scope :disabled, -> { where(disabled: true) }
|
|
28
27
|
# end
|
|
29
28
|
#
|
|
30
29
|
# module ClassMethods
|
|
@@ -32,8 +31,9 @@ module ActiveSupport
|
|
|
32
31
|
# end
|
|
33
32
|
# end
|
|
34
33
|
#
|
|
35
|
-
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
|
36
|
-
# module which depends on the former, we would typically write the
|
|
34
|
+
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
|
35
|
+
# and a +Bar+ module which depends on the former, we would typically write the
|
|
36
|
+
# following:
|
|
37
37
|
#
|
|
38
38
|
# module Foo
|
|
39
39
|
# def self.included(base)
|
|
@@ -56,11 +56,11 @@ module ActiveSupport
|
|
|
56
56
|
# include Bar # Bar is the module that Host really needs
|
|
57
57
|
# end
|
|
58
58
|
#
|
|
59
|
-
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
|
60
|
-
# these from +Host+ directly including +Foo+ in +Bar+:
|
|
59
|
+
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
|
60
|
+
# could try to hide these from +Host+ directly including +Foo+ in +Bar+:
|
|
61
61
|
#
|
|
62
62
|
# module Bar
|
|
63
|
-
# include Foo
|
|
63
|
+
# include Foo
|
|
64
64
|
# def self.included(base)
|
|
65
65
|
# base.method_injected_by_foo
|
|
66
66
|
# end
|
|
@@ -70,18 +70,17 @@ module ActiveSupport
|
|
|
70
70
|
# include Bar
|
|
71
71
|
# end
|
|
72
72
|
#
|
|
73
|
-
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
|
74
|
-
# not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
|
73
|
+
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
|
74
|
+
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
|
75
|
+
# module dependencies are properly resolved:
|
|
75
76
|
#
|
|
76
77
|
# require 'active_support/concern'
|
|
77
78
|
#
|
|
78
79
|
# module Foo
|
|
79
80
|
# extend ActiveSupport::Concern
|
|
80
81
|
# included do
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
# ...
|
|
84
|
-
# end
|
|
82
|
+
# def self.method_injected_by_foo
|
|
83
|
+
# ...
|
|
85
84
|
# end
|
|
86
85
|
# end
|
|
87
86
|
# end
|
|
@@ -98,9 +97,8 @@ module ActiveSupport
|
|
|
98
97
|
# class Host
|
|
99
98
|
# include Bar # works, Bar takes care now of its dependencies
|
|
100
99
|
# end
|
|
101
|
-
#
|
|
102
100
|
module Concern
|
|
103
|
-
def self.extended(base)
|
|
101
|
+
def self.extended(base) #:nodoc:
|
|
104
102
|
base.instance_variable_set("@_dependencies", [])
|
|
105
103
|
end
|
|
106
104
|
|
|
@@ -113,11 +111,6 @@ module ActiveSupport
|
|
|
113
111
|
@_dependencies.each { |dep| base.send(:include, dep) }
|
|
114
112
|
super
|
|
115
113
|
base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
|
|
116
|
-
if const_defined?("InstanceMethods")
|
|
117
|
-
base.send :include, const_get("InstanceMethods")
|
|
118
|
-
ActiveSupport::Deprecation.warn "The InstanceMethods module inside ActiveSupport::Concern will be " \
|
|
119
|
-
"no longer included automatically. Please define instance methods directly in #{self} instead.", caller
|
|
120
|
-
end
|
|
121
114
|
base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
|
|
122
115
|
end
|
|
123
116
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'monitor'
|
|
3
|
+
|
|
4
|
+
module ActiveSupport
|
|
5
|
+
module Concurrency
|
|
6
|
+
class Latch
|
|
7
|
+
def initialize(count = 1)
|
|
8
|
+
@count = count
|
|
9
|
+
@lock = Monitor.new
|
|
10
|
+
@cv = @lock.new_cond
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def release
|
|
14
|
+
@lock.synchronize do
|
|
15
|
+
@count -= 1 if @count > 0
|
|
16
|
+
@cv.broadcast if @count.zero?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def await
|
|
21
|
+
@lock.synchronize do
|
|
22
|
+
@cv.wait_while { @count > 0 }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
require 'active_support/concern'
|
|
2
2
|
require 'active_support/ordered_options'
|
|
3
|
-
require 'active_support/core_ext/kernel/singleton_class'
|
|
4
|
-
require 'active_support/core_ext/module/delegation'
|
|
5
3
|
require 'active_support/core_ext/array/extract_options'
|
|
6
4
|
|
|
7
5
|
module ActiveSupport
|
|
@@ -15,7 +13,7 @@ module ActiveSupport
|
|
|
15
13
|
self.class.compile_methods!(keys)
|
|
16
14
|
end
|
|
17
15
|
|
|
18
|
-
#
|
|
16
|
+
# Compiles reader methods so we don't have to go through method_missing.
|
|
19
17
|
def self.compile_methods!(keys)
|
|
20
18
|
keys.reject { |m| method_defined?(m) }.each do |key|
|
|
21
19
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
@@ -39,29 +37,89 @@ module ActiveSupport
|
|
|
39
37
|
yield config
|
|
40
38
|
end
|
|
41
39
|
|
|
42
|
-
# Allows you to add shortcut so that you don't have to refer to attribute
|
|
43
|
-
# Also look at the example for config to contrast.
|
|
40
|
+
# Allows you to add shortcut so that you don't have to refer to attribute
|
|
41
|
+
# through config. Also look at the example for config to contrast.
|
|
42
|
+
#
|
|
43
|
+
# Defines both class and instance config accessors.
|
|
44
44
|
#
|
|
45
45
|
# class User
|
|
46
46
|
# include ActiveSupport::Configurable
|
|
47
47
|
# config_accessor :allowed_access
|
|
48
48
|
# end
|
|
49
49
|
#
|
|
50
|
+
# User.allowed_access # => nil
|
|
51
|
+
# User.allowed_access = false
|
|
52
|
+
# User.allowed_access # => false
|
|
53
|
+
#
|
|
50
54
|
# user = User.new
|
|
55
|
+
# user.allowed_access # => false
|
|
51
56
|
# user.allowed_access = true
|
|
52
57
|
# user.allowed_access # => true
|
|
53
58
|
#
|
|
59
|
+
# User.allowed_access # => false
|
|
60
|
+
#
|
|
61
|
+
# The attribute name must be a valid method name in Ruby.
|
|
62
|
+
#
|
|
63
|
+
# class User
|
|
64
|
+
# include ActiveSupport::Configurable
|
|
65
|
+
# config_accessor :"1_Badname"
|
|
66
|
+
# end
|
|
67
|
+
# # => NameError: invalid config attribute name
|
|
68
|
+
#
|
|
69
|
+
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
|
70
|
+
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
|
71
|
+
#
|
|
72
|
+
# class User
|
|
73
|
+
# include ActiveSupport::Configurable
|
|
74
|
+
# config_accessor :allowed_access, instance_reader: false, instance_writer: false
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# User.allowed_access = false
|
|
78
|
+
# User.allowed_access # => false
|
|
79
|
+
#
|
|
80
|
+
# User.new.allowed_access = true # => NoMethodError
|
|
81
|
+
# User.new.allowed_access # => NoMethodError
|
|
82
|
+
#
|
|
83
|
+
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
|
|
84
|
+
#
|
|
85
|
+
# class User
|
|
86
|
+
# include ActiveSupport::Configurable
|
|
87
|
+
# config_accessor :allowed_access, instance_accessor: false
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# User.allowed_access = false
|
|
91
|
+
# User.allowed_access # => false
|
|
92
|
+
#
|
|
93
|
+
# User.new.allowed_access = true # => NoMethodError
|
|
94
|
+
# User.new.allowed_access # => NoMethodError
|
|
95
|
+
#
|
|
96
|
+
# Also you can pass a block to set up the attribute with a default value.
|
|
97
|
+
#
|
|
98
|
+
# class User
|
|
99
|
+
# include ActiveSupport::Configurable
|
|
100
|
+
# config_accessor :hair_colors do
|
|
101
|
+
# [:brown, :black, :blonde, :red]
|
|
102
|
+
# end
|
|
103
|
+
# end
|
|
104
|
+
#
|
|
105
|
+
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
|
54
106
|
def config_accessor(*names)
|
|
55
107
|
options = names.extract_options!
|
|
56
108
|
|
|
57
109
|
names.each do |name|
|
|
58
|
-
|
|
59
|
-
writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
|
110
|
+
raise NameError.new('invalid config attribute name') unless name =~ /^[_A-Za-z]\w*$/
|
|
60
111
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class_eval
|
|
112
|
+
reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
|
|
113
|
+
writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
|
114
|
+
|
|
115
|
+
singleton_class.class_eval reader, __FILE__, reader_line
|
|
116
|
+
singleton_class.class_eval writer, __FILE__, writer_line
|
|
117
|
+
|
|
118
|
+
unless options[:instance_accessor] == false
|
|
119
|
+
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
|
|
120
|
+
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
|
|
121
|
+
end
|
|
122
|
+
send("#{name}=", yield) if block_given?
|
|
65
123
|
end
|
|
66
124
|
end
|
|
67
125
|
end
|
|
@@ -81,7 +139,6 @@ module ActiveSupport
|
|
|
81
139
|
#
|
|
82
140
|
# user.config.allowed_access # => true
|
|
83
141
|
# user.config.level # => 1
|
|
84
|
-
#
|
|
85
142
|
def config
|
|
86
143
|
@_config ||= self.class.config.inheritable_copy
|
|
87
144
|
end
|
|
@@ -1,40 +1,48 @@
|
|
|
1
1
|
class Array
|
|
2
2
|
# Returns the tail of the array from +position+.
|
|
3
3
|
#
|
|
4
|
-
# %w( a b c d ).from(0) # =>
|
|
5
|
-
# %w( a b c d ).from(2) # =>
|
|
6
|
-
# %w( a b c d ).from(10) # =>
|
|
7
|
-
# %w().from(0) # =>
|
|
4
|
+
# %w( a b c d ).from(0) # => ["a", "b", "c", "d"]
|
|
5
|
+
# %w( a b c d ).from(2) # => ["c", "d"]
|
|
6
|
+
# %w( a b c d ).from(10) # => []
|
|
7
|
+
# %w().from(0) # => []
|
|
8
8
|
def from(position)
|
|
9
9
|
self[position, length] || []
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# Returns the beginning of the array up to +position+.
|
|
13
13
|
#
|
|
14
|
-
# %w( a b c d ).to(0) # =>
|
|
15
|
-
# %w( a b c d ).to(2) # =>
|
|
16
|
-
# %w( a b c d ).to(10) # =>
|
|
17
|
-
# %w().to(0) # =>
|
|
14
|
+
# %w( a b c d ).to(0) # => ["a"]
|
|
15
|
+
# %w( a b c d ).to(2) # => ["a", "b", "c"]
|
|
16
|
+
# %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
|
|
17
|
+
# %w().to(0) # => []
|
|
18
18
|
def to(position)
|
|
19
|
-
|
|
19
|
+
first position + 1
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# Equal to <tt>self[1]</tt>.
|
|
23
|
+
#
|
|
24
|
+
# %w( a b c d e ).second # => "b"
|
|
23
25
|
def second
|
|
24
26
|
self[1]
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
# Equal to <tt>self[2]</tt>.
|
|
30
|
+
#
|
|
31
|
+
# %w( a b c d e ).third # => "c"
|
|
28
32
|
def third
|
|
29
33
|
self[2]
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
# Equal to <tt>self[3]</tt>.
|
|
37
|
+
#
|
|
38
|
+
# %w( a b c d e ).fourth # => "d"
|
|
33
39
|
def fourth
|
|
34
40
|
self[3]
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
# Equal to <tt>self[4]</tt>.
|
|
44
|
+
#
|
|
45
|
+
# %w( a b c d e ).fifth # => "e"
|
|
38
46
|
def fifth
|
|
39
47
|
self[4]
|
|
40
48
|
end
|
|
@@ -1,41 +1,99 @@
|
|
|
1
1
|
require 'active_support/xml_mini'
|
|
2
2
|
require 'active_support/core_ext/hash/keys'
|
|
3
|
-
require 'active_support/core_ext/hash/reverse_merge'
|
|
4
3
|
require 'active_support/core_ext/string/inflections'
|
|
4
|
+
require 'active_support/core_ext/object/to_param'
|
|
5
|
+
require 'active_support/core_ext/object/to_query'
|
|
5
6
|
|
|
6
7
|
class Array
|
|
7
|
-
# Converts the array to a comma-separated sentence where the last element is
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
8
|
+
# Converts the array to a comma-separated sentence where the last element is
|
|
9
|
+
# joined by the connector word.
|
|
10
|
+
#
|
|
11
|
+
# You can pass the following options to change the default behavior. If you
|
|
12
|
+
# pass an option key that doesn't exist in the list below, it will raise an
|
|
13
|
+
# <tt>ArgumentError</tt>.
|
|
14
|
+
#
|
|
15
|
+
# ==== Options
|
|
16
|
+
#
|
|
17
|
+
# * <tt>:words_connector</tt> - The sign or word used to join the elements
|
|
18
|
+
# in arrays with two or more elements (default: ", ").
|
|
19
|
+
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
|
20
|
+
# in arrays with two elements (default: " and ").
|
|
21
|
+
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
|
|
22
|
+
# in arrays with three or more elements (default: ", and ").
|
|
23
|
+
# * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
|
|
24
|
+
# the connector options defined on the 'support.array' namespace in the
|
|
25
|
+
# corresponding dictionary file.
|
|
26
|
+
#
|
|
27
|
+
# ==== Examples
|
|
28
|
+
#
|
|
29
|
+
# [].to_sentence # => ""
|
|
30
|
+
# ['one'].to_sentence # => "one"
|
|
31
|
+
# ['one', 'two'].to_sentence # => "one and two"
|
|
32
|
+
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
|
|
33
|
+
#
|
|
34
|
+
# ['one', 'two'].to_sentence(passing: 'invalid option')
|
|
35
|
+
# # => ArgumentError: Unknown key :passing
|
|
36
|
+
#
|
|
37
|
+
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
|
38
|
+
# # => "one-two"
|
|
39
|
+
#
|
|
40
|
+
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
|
|
41
|
+
# # => "one or two or at least three"
|
|
42
|
+
#
|
|
43
|
+
# Using <tt>:locale</tt> option:
|
|
44
|
+
#
|
|
45
|
+
# # Given this locale dictionary:
|
|
46
|
+
# #
|
|
47
|
+
# # es:
|
|
48
|
+
# # support:
|
|
49
|
+
# # array:
|
|
50
|
+
# # words_connector: " o "
|
|
51
|
+
# # two_words_connector: " y "
|
|
52
|
+
# # last_word_connector: " o al menos "
|
|
53
|
+
#
|
|
54
|
+
# ['uno', 'dos'].to_sentence(locale: :es)
|
|
55
|
+
# # => "uno y dos"
|
|
56
|
+
#
|
|
57
|
+
# ['uno', 'dos', 'tres'].to_sentence(locale: :es)
|
|
58
|
+
# # => "uno o dos o al menos tres"
|
|
11
59
|
def to_sentence(options = {})
|
|
60
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
|
61
|
+
|
|
62
|
+
default_connectors = {
|
|
63
|
+
:words_connector => ', ',
|
|
64
|
+
:two_words_connector => ' and ',
|
|
65
|
+
:last_word_connector => ', and '
|
|
66
|
+
}
|
|
12
67
|
if defined?(I18n)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale])
|
|
16
|
-
else
|
|
17
|
-
default_words_connector = ", "
|
|
18
|
-
default_two_words_connector = " and "
|
|
19
|
-
default_last_word_connector = ", and "
|
|
68
|
+
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
|
|
69
|
+
default_connectors.merge!(i18n_connectors)
|
|
20
70
|
end
|
|
21
|
-
|
|
22
|
-
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
|
23
|
-
options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
|
|
71
|
+
options = default_connectors.merge!(options)
|
|
24
72
|
|
|
25
73
|
case length
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
74
|
+
when 0
|
|
75
|
+
''
|
|
76
|
+
when 1
|
|
77
|
+
self[0].to_s.dup
|
|
78
|
+
when 2
|
|
79
|
+
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
|
80
|
+
else
|
|
81
|
+
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
|
34
82
|
end
|
|
35
83
|
end
|
|
36
84
|
|
|
37
85
|
# Converts a collection of elements into a formatted string by calling
|
|
38
|
-
# <tt>to_s</tt> on all elements and joining them:
|
|
86
|
+
# <tt>to_s</tt> on all elements and joining them. Having this model:
|
|
87
|
+
#
|
|
88
|
+
# class Blog < ActiveRecord::Base
|
|
89
|
+
# def to_s
|
|
90
|
+
# title
|
|
91
|
+
# end
|
|
92
|
+
# end
|
|
93
|
+
#
|
|
94
|
+
# Blog.all.map(&:title) #=> ["First Post", "Second Post", "Third post"]
|
|
95
|
+
#
|
|
96
|
+
# <tt>to_formatted_s</tt> shows us:
|
|
39
97
|
#
|
|
40
98
|
# Blog.all.to_formatted_s # => "First PostSecond PostThird Post"
|
|
41
99
|
#
|
|
@@ -45,14 +103,14 @@ class Array
|
|
|
45
103
|
# Blog.all.to_formatted_s(:db) # => "1,2,3"
|
|
46
104
|
def to_formatted_s(format = :default)
|
|
47
105
|
case format
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else
|
|
52
|
-
collect { |element| element.id }.join(",")
|
|
53
|
-
end
|
|
106
|
+
when :db
|
|
107
|
+
if empty?
|
|
108
|
+
'null'
|
|
54
109
|
else
|
|
55
|
-
|
|
110
|
+
collect { |element| element.id }.join(',')
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
to_default_s
|
|
56
114
|
end
|
|
57
115
|
end
|
|
58
116
|
alias_method :to_default_s, :to_s
|
|
@@ -86,20 +144,20 @@ class Array
|
|
|
86
144
|
# </project>
|
|
87
145
|
# </projects>
|
|
88
146
|
#
|
|
89
|
-
# Otherwise the root element is "
|
|
147
|
+
# Otherwise the root element is "objects":
|
|
90
148
|
#
|
|
91
|
-
# [{:
|
|
149
|
+
# [{ foo: 1, bar: 2}, { baz: 3}].to_xml
|
|
92
150
|
#
|
|
93
151
|
# <?xml version="1.0" encoding="UTF-8"?>
|
|
94
|
-
# <
|
|
95
|
-
# <
|
|
152
|
+
# <objects type="array">
|
|
153
|
+
# <object>
|
|
96
154
|
# <bar type="integer">2</bar>
|
|
97
155
|
# <foo type="integer">1</foo>
|
|
98
|
-
# </
|
|
99
|
-
# <
|
|
156
|
+
# </object>
|
|
157
|
+
# <object>
|
|
100
158
|
# <baz type="integer">3</baz>
|
|
101
|
-
# </
|
|
102
|
-
# </
|
|
159
|
+
# </object>
|
|
160
|
+
# </objects>
|
|
103
161
|
#
|
|
104
162
|
# If the collection is empty the root element is "nil-classes" by default:
|
|
105
163
|
#
|
|
@@ -110,7 +168,7 @@ class Array
|
|
|
110
168
|
#
|
|
111
169
|
# To ensure a meaningful root element use the <tt>:root</tt> option:
|
|
112
170
|
#
|
|
113
|
-
# customer_with_no_projects.projects.to_xml(:
|
|
171
|
+
# customer_with_no_projects.projects.to_xml(root: 'projects')
|
|
114
172
|
#
|
|
115
173
|
# <?xml version="1.0" encoding="UTF-8"?>
|
|
116
174
|
# <projects type="array"/>
|
|
@@ -120,7 +178,7 @@ class Array
|
|
|
120
178
|
#
|
|
121
179
|
# The +options+ hash is passed downwards:
|
|
122
180
|
#
|
|
123
|
-
# Message.all.to_xml(:
|
|
181
|
+
# Message.all.to_xml(skip_types: true)
|
|
124
182
|
#
|
|
125
183
|
# <?xml version="1.0" encoding="UTF-8"?>
|
|
126
184
|
# <messages>
|
|
@@ -138,27 +196,29 @@ class Array
|
|
|
138
196
|
|
|
139
197
|
options = options.dup
|
|
140
198
|
options[:indent] ||= 2
|
|
141
|
-
options[:builder] ||= Builder::XmlMarkup.new(:
|
|
142
|
-
options[:root] ||=
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
199
|
+
options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
|
|
200
|
+
options[:root] ||= \
|
|
201
|
+
if first.class != Hash && all? { |e| e.is_a?(first.class) }
|
|
202
|
+
underscored = ActiveSupport::Inflector.underscore(first.class.name)
|
|
203
|
+
ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
|
|
204
|
+
else
|
|
205
|
+
'objects'
|
|
206
|
+
end
|
|
148
207
|
|
|
149
208
|
builder = options[:builder]
|
|
150
209
|
builder.instruct! unless options.delete(:skip_instruct)
|
|
151
210
|
|
|
152
211
|
root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
|
|
153
212
|
children = options.delete(:children) || root.singularize
|
|
213
|
+
attributes = options[:skip_types] ? {} : { type: 'array' }
|
|
154
214
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
215
|
+
if empty?
|
|
216
|
+
builder.tag!(root, attributes)
|
|
217
|
+
else
|
|
218
|
+
builder.tag!(root, attributes) do
|
|
219
|
+
each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
|
|
220
|
+
yield builder if block_given?
|
|
221
|
+
end
|
|
161
222
|
end
|
|
162
223
|
end
|
|
163
|
-
|
|
164
224
|
end
|
|
@@ -17,8 +17,8 @@ class Array
|
|
|
17
17
|
# args.extract_options!
|
|
18
18
|
# end
|
|
19
19
|
#
|
|
20
|
-
# options(1, 2)
|
|
21
|
-
# options(1, 2, :
|
|
20
|
+
# options(1, 2) # => {}
|
|
21
|
+
# options(1, 2, a: :b) # => {:a=>:b}
|
|
22
22
|
def extract_options!
|
|
23
23
|
if last.is_a?(Hash) && last.extractable_options?
|
|
24
24
|
pop
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
require 'enumerator'
|
|
2
|
-
|
|
3
1
|
class Array
|
|
4
2
|
# Splits or iterates over the array in groups of size +number+,
|
|
5
3
|
# padding any remaining slots with +fill_with+ unless it is +false+.
|
|
6
4
|
#
|
|
7
|
-
# %w(1 2 3 4 5 6 7).in_groups_of(3) {|group| p group}
|
|
5
|
+
# %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
|
|
8
6
|
# ["1", "2", "3"]
|
|
9
7
|
# ["4", "5", "6"]
|
|
10
|
-
# ["7",
|
|
8
|
+
# ["7", "8", "9"]
|
|
9
|
+
# ["10", nil, nil]
|
|
11
10
|
#
|
|
12
|
-
# %w(1 2 3).in_groups_of(2, ' ') {|group| p group}
|
|
11
|
+
# %w(1 2 3 4 5).in_groups_of(2, ' ') {|group| p group}
|
|
13
12
|
# ["1", "2"]
|
|
14
|
-
# ["3", "
|
|
13
|
+
# ["3", "4"]
|
|
14
|
+
# ["5", " "]
|
|
15
15
|
#
|
|
16
|
-
# %w(1 2 3).in_groups_of(2, false) {|group| p group}
|
|
16
|
+
# %w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
|
|
17
17
|
# ["1", "2"]
|
|
18
|
-
# ["3"]
|
|
18
|
+
# ["3", "4"]
|
|
19
|
+
# ["5"]
|
|
19
20
|
def in_groups_of(number, fill_with = nil)
|
|
20
21
|
if fill_with == false
|
|
21
22
|
collection = self
|
|
@@ -44,10 +45,10 @@ class Array
|
|
|
44
45
|
# ["5", "6", "7", nil]
|
|
45
46
|
# ["8", "9", "10", nil]
|
|
46
47
|
#
|
|
47
|
-
# %w(1 2 3 4 5 6 7).in_groups(3, ' ') {|group| p group}
|
|
48
|
-
# ["1", "2", "3"]
|
|
49
|
-
# ["
|
|
50
|
-
# ["
|
|
48
|
+
# %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, ' ') {|group| p group}
|
|
49
|
+
# ["1", "2", "3", "4"]
|
|
50
|
+
# ["5", "6", "7", " "]
|
|
51
|
+
# ["8", "9", "10", " "]
|
|
51
52
|
#
|
|
52
53
|
# %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
|
|
53
54
|
# ["1", "2", "3"]
|
|
@@ -57,7 +58,7 @@ class Array
|
|
|
57
58
|
# size / number gives minor group size;
|
|
58
59
|
# size % number gives how many objects need extra accommodation;
|
|
59
60
|
# each group hold either division or division + 1 items.
|
|
60
|
-
division = size
|
|
61
|
+
division = size.div number
|
|
61
62
|
modulo = size % number
|
|
62
63
|
|
|
63
64
|
# create a new array avoiding dup
|
|
@@ -66,9 +67,9 @@ class Array
|
|
|
66
67
|
|
|
67
68
|
number.times do |index|
|
|
68
69
|
length = division + (modulo > 0 && modulo > index ? 1 : 0)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
groups << last_group = slice(start, length)
|
|
71
|
+
last_group << fill_with if fill_with != false &&
|
|
72
|
+
modulo > 0 && length == division
|
|
72
73
|
start += length
|
|
73
74
|
end
|
|
74
75
|
|
|
@@ -82,13 +83,11 @@ class Array
|
|
|
82
83
|
# Divides the array into one or more subarrays based on a delimiting +value+
|
|
83
84
|
# or the result of an optional block.
|
|
84
85
|
#
|
|
85
|
-
# [1, 2, 3, 4, 5].split(3)
|
|
86
|
-
# (1..10).to_a.split { |i| i % 3 == 0 }
|
|
87
|
-
def split(value = nil)
|
|
88
|
-
using_block = block_given?
|
|
89
|
-
|
|
86
|
+
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
|
|
87
|
+
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
|
|
88
|
+
def split(value = nil, &block)
|
|
90
89
|
inject([[]]) do |results, element|
|
|
91
|
-
if
|
|
90
|
+
if block && block.call(element) || value == element
|
|
92
91
|
results << []
|
|
93
92
|
else
|
|
94
93
|
results.last << element
|