activesupport 4.0.13 → 4.2.11.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +406 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -2
- data/lib/active_support/backtrace_cleaner.rb +8 -8
- data/lib/active_support/benchmarkable.rb +0 -10
- data/lib/active_support/cache/file_store.rb +32 -22
- data/lib/active_support/cache/mem_cache_store.rb +5 -7
- data/lib/active_support/cache/memory_store.rb +1 -0
- data/lib/active_support/cache/strategy/local_cache.rb +11 -30
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/cache.rb +75 -41
- data/lib/active_support/callbacks.rb +482 -261
- data/lib/active_support/concern.rb +23 -7
- data/lib/active_support/configurable.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +11 -1
- data/lib/active_support/core_ext/array/conversions.rb +2 -17
- data/lib/active_support/core_ext/array/grouping.rb +29 -12
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -15
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +16 -0
- data/lib/active_support/core_ext/class/attribute.rb +1 -2
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -170
- data/lib/active_support/core_ext/class/delegating_attributes.rb +13 -8
- data/lib/active_support/core_ext/class/subclasses.rb +0 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/calculations.rb +10 -0
- data/lib/active_support/core_ext/date/conversions.rb +9 -1
- data/lib/active_support/core_ext/date/zones.rb +2 -33
- data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -11
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +45 -22
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/date_time/zones.rb +3 -21
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +17 -1
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/compact.rb +24 -0
- data/lib/active_support/core_ext/hash/conversions.rb +9 -8
- data/lib/active_support/core_ext/hash/except.rb +8 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
- data/lib/active_support/core_ext/hash/keys.rb +25 -19
- data/lib/active_support/core_ext/hash/slice.rb +8 -2
- data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
- data/lib/active_support/core_ext/hash.rb +2 -1
- data/lib/active_support/core_ext/integer/time.rb +0 -15
- data/lib/active_support/core_ext/kernel/concern.rb +10 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +13 -2
- data/lib/active_support/core_ext/kernel.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +4 -1
- data/lib/active_support/core_ext/marshal.rb +8 -5
- data/lib/active_support/core_ext/module/aliasing.rb +2 -2
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +53 -25
- data/lib/active_support/core_ext/module/deprecation.rb +0 -2
- data/lib/active_support/core_ext/module/introspection.rb +0 -16
- data/lib/active_support/core_ext/module/method_transplanting.rb +13 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +11 -3
- data/lib/active_support/core_ext/numeric/time.rb +4 -29
- data/lib/active_support/core_ext/object/blank.rb +44 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
- data/lib/active_support/core_ext/object/duplicable.rb +72 -33
- data/lib/active_support/core_ext/object/inclusion.rb +16 -15
- data/lib/active_support/core_ext/object/itself.rb +15 -0
- data/lib/active_support/core_ext/object/json.rb +197 -0
- data/lib/active_support/core_ext/object/to_query.rb +14 -6
- data/lib/active_support/core_ext/object/try.rb +36 -14
- data/lib/active_support/core_ext/object/with_options.rb +30 -3
- data/lib/active_support/core_ext/object.rb +2 -1
- data/lib/active_support/core_ext/string/access.rb +35 -35
- data/lib/active_support/core_ext/string/conversions.rb +10 -9
- data/lib/active_support/core_ext/string/exclude.rb +3 -3
- data/lib/active_support/core_ext/string/filters.rb +51 -3
- data/lib/active_support/core_ext/string/inflections.rb +15 -10
- data/lib/active_support/core_ext/string/output_safety.rb +97 -33
- data/lib/active_support/core_ext/string/zones.rb +1 -0
- data/lib/active_support/core_ext/thread.rb +12 -5
- data/lib/active_support/core_ext/time/calculations.rb +47 -68
- data/lib/active_support/core_ext/time/compatibility.rb +14 -0
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/zones.rb +2 -20
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/dependencies/autoload.rb +1 -1
- data/lib/active_support/dependencies.rb +64 -25
- data/lib/active_support/deprecation/behaviors.rb +4 -4
- data/lib/active_support/deprecation.rb +4 -4
- data/lib/active_support/duration.rb +55 -11
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/hash_with_indifferent_access.rb +39 -11
- data/lib/active_support/i18n.rb +4 -4
- data/lib/active_support/i18n_railtie.rb +1 -7
- data/lib/active_support/inflections.rb +6 -1
- data/lib/active_support/inflector/inflections.rb +19 -19
- data/lib/active_support/inflector/methods.rb +66 -25
- data/lib/active_support/json/decoding.rb +15 -22
- data/lib/active_support/json/encoding.rb +125 -286
- data/lib/active_support/key_generator.rb +8 -10
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +1 -1
- data/lib/active_support/logger.rb +51 -1
- data/lib/active_support/logger_silence.rb +7 -4
- data/lib/active_support/logger_thread_safe_level.rb +32 -0
- data/lib/active_support/message_encryptor.rb +14 -6
- data/lib/active_support/message_verifier.rb +16 -12
- data/lib/active_support/multibyte/chars.rb +2 -3
- data/lib/active_support/multibyte/unicode.rb +46 -58
- data/lib/active_support/notifications/fanout.rb +12 -7
- data/lib/active_support/notifications/instrumenter.rb +2 -1
- data/lib/active_support/notifications.rb +11 -6
- data/lib/active_support/number_helper/number_converter.rb +182 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +23 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +87 -0
- data/lib/active_support/number_helper.rb +32 -324
- data/lib/active_support/ordered_options.rb +8 -0
- data/lib/active_support/per_thread_registry.rb +13 -10
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/subscriber.rb +35 -3
- data/lib/active_support/test_case.rb +52 -19
- data/lib/active_support/testing/assertions.rb +1 -31
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/constant_lookup.rb +1 -5
- data/lib/active_support/testing/declarative.rb +7 -21
- data/lib/active_support/testing/isolation.rb +29 -69
- data/lib/active_support/testing/setup_and_teardown.rb +17 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -2
- data/lib/active_support/testing/time_helpers.rb +134 -0
- data/lib/active_support/time.rb +0 -2
- data/lib/active_support/time_with_zone.rb +60 -40
- data/lib/active_support/values/time_zone.rb +101 -101
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +4 -7
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/libxml.rb +1 -3
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
- data/lib/active_support/xml_mini/nokogiri.rb +1 -3
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +33 -15
- data/lib/active_support.rb +27 -2
- metadata +43 -43
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
class Module
|
4
|
+
# = Bite-sized separation of concerns
|
5
|
+
#
|
6
|
+
# We often find ourselves with a medium-sized chunk of behavior that we'd
|
7
|
+
# like to extract, but only mix in to a single class.
|
8
|
+
#
|
9
|
+
# Extracting a plain old Ruby object to encapsulate it and collaborate or
|
10
|
+
# delegate to the original object is often a good choice, but when there's
|
11
|
+
# no additional state to encapsulate or we're making DSL-style declarations
|
12
|
+
# about the parent class, introducing new collaborators can obfuscate rather
|
13
|
+
# than simplify.
|
14
|
+
#
|
15
|
+
# The typical route is to just dump everything in a monolithic class, perhaps
|
16
|
+
# with a comment, as a least-bad alternative. Using modules in separate files
|
17
|
+
# means tedious sifting to get a big-picture view.
|
18
|
+
#
|
19
|
+
# = Dissatisfying ways to separate small concerns
|
20
|
+
#
|
21
|
+
# == Using comments:
|
22
|
+
#
|
23
|
+
# class Todo
|
24
|
+
# # Other todo implementation
|
25
|
+
# # ...
|
26
|
+
#
|
27
|
+
# ## Event tracking
|
28
|
+
# has_many :events
|
29
|
+
#
|
30
|
+
# before_create :track_creation
|
31
|
+
# after_destroy :track_deletion
|
32
|
+
#
|
33
|
+
# private
|
34
|
+
# def track_creation
|
35
|
+
# # ...
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# == With an inline module:
|
40
|
+
#
|
41
|
+
# Noisy syntax.
|
42
|
+
#
|
43
|
+
# class Todo
|
44
|
+
# # Other todo implementation
|
45
|
+
# # ...
|
46
|
+
#
|
47
|
+
# module EventTracking
|
48
|
+
# extend ActiveSupport::Concern
|
49
|
+
#
|
50
|
+
# included do
|
51
|
+
# has_many :events
|
52
|
+
# before_create :track_creation
|
53
|
+
# after_destroy :track_deletion
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# private
|
57
|
+
# def track_creation
|
58
|
+
# # ...
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# include EventTracking
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# == Mix-in noise exiled to its own file:
|
65
|
+
#
|
66
|
+
# Once our chunk of behavior starts pushing the scroll-to-understand it's
|
67
|
+
# boundary, we give in and move it to a separate file. At this size, the
|
68
|
+
# overhead feels in good proportion to the size of our extraction, despite
|
69
|
+
# diluting our at-a-glance sense of how things really work.
|
70
|
+
#
|
71
|
+
# class Todo
|
72
|
+
# # Other todo implementation
|
73
|
+
# # ...
|
74
|
+
#
|
75
|
+
# include TodoEventTracking
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# = Introducing Module#concerning
|
79
|
+
#
|
80
|
+
# By quieting the mix-in noise, we arrive at a natural, low-ceremony way to
|
81
|
+
# separate bite-sized concerns.
|
82
|
+
#
|
83
|
+
# class Todo
|
84
|
+
# # Other todo implementation
|
85
|
+
# # ...
|
86
|
+
#
|
87
|
+
# concerning :EventTracking do
|
88
|
+
# included do
|
89
|
+
# has_many :events
|
90
|
+
# before_create :track_creation
|
91
|
+
# after_destroy :track_deletion
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# private
|
95
|
+
# def track_creation
|
96
|
+
# # ...
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# Todo.ancestors
|
102
|
+
# # => Todo, Todo::EventTracking, Object
|
103
|
+
#
|
104
|
+
# This small step has some wonderful ripple effects. We can
|
105
|
+
# * grok the behavior of our class in one glance,
|
106
|
+
# * clean up monolithic junk-drawer classes by separating their concerns, and
|
107
|
+
# * stop leaning on protected/private for crude "this is internal stuff" modularity.
|
108
|
+
module Concerning
|
109
|
+
# Define a new concern and mix it in.
|
110
|
+
def concerning(topic, &block)
|
111
|
+
include concern(topic, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# A low-cruft shortcut to define a concern.
|
115
|
+
#
|
116
|
+
# concern :EventTracking do
|
117
|
+
# ...
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# is equivalent to
|
121
|
+
#
|
122
|
+
# module EventTracking
|
123
|
+
# extend ActiveSupport::Concern
|
124
|
+
#
|
125
|
+
# ...
|
126
|
+
# end
|
127
|
+
def concern(topic, &module_definition)
|
128
|
+
const_set topic, Module.new {
|
129
|
+
extend ::ActiveSupport::Concern
|
130
|
+
module_eval(&module_definition)
|
131
|
+
}
|
132
|
+
end
|
133
|
+
end
|
134
|
+
include Concerning
|
135
|
+
end
|
@@ -1,7 +1,32 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
class Module
|
4
|
+
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
|
5
|
+
# option is not used.
|
6
|
+
class DelegationError < NoMethodError; end
|
7
|
+
|
8
|
+
RUBY_RESERVED_WORDS = Set.new(
|
9
|
+
%w(alias and BEGIN begin break case class def defined? do else elsif END
|
10
|
+
end ensure false for if in module next nil not or redo rescue retry
|
11
|
+
return self super then true undef unless until when while yield)
|
12
|
+
).freeze
|
13
|
+
|
14
|
+
DELEGATION_RESERVED_KEYWORDS = Set.new(
|
15
|
+
%w(_ arg args block)
|
16
|
+
)
|
17
|
+
|
18
|
+
DELEGATION_RESERVED_METHOD_NAMES = Set.new(
|
19
|
+
RUBY_RESERVED_WORDS + DELEGATION_RESERVED_KEYWORDS
|
20
|
+
).freeze
|
21
|
+
|
2
22
|
# Provides a +delegate+ class method to easily expose contained objects'
|
3
23
|
# public methods as your own.
|
4
24
|
#
|
25
|
+
# ==== Options
|
26
|
+
# * <tt>:to</tt> - Specifies the target object
|
27
|
+
# * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
|
28
|
+
# * <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ to be raised
|
29
|
+
#
|
5
30
|
# The macro receives one or more method names (specified as symbols or
|
6
31
|
# strings) and the name of the target object via the <tt>:to</tt> option
|
7
32
|
# (also a symbol or string).
|
@@ -129,6 +154,8 @@ class Module
|
|
129
154
|
#
|
130
155
|
# Foo.new("Bar").name # raises NoMethodError: undefined method `name'
|
131
156
|
#
|
157
|
+
# The target method must be public, otherwise it will raise +NoMethodError+.
|
158
|
+
#
|
132
159
|
def delegate(*methods)
|
133
160
|
options = methods.pop
|
134
161
|
unless options.is_a?(Hash) && to = options[:to]
|
@@ -152,46 +179,47 @@ class Module
|
|
152
179
|
line = line.to_i
|
153
180
|
|
154
181
|
to = to.to_s
|
155
|
-
to =
|
182
|
+
to = "self.#{to}" if RUBY_RESERVED_WORDS.include?(to)
|
156
183
|
|
157
184
|
methods.each do |method|
|
158
185
|
# Attribute writer methods only accept one argument. Makes sure []=
|
159
186
|
# methods still accept two arguments.
|
160
187
|
definition = (method =~ /[^\]]=$/) ? 'arg' : '*args, &block'
|
161
188
|
|
162
|
-
# The following generated
|
189
|
+
# The following generated method calls the target exactly once, storing
|
163
190
|
# the returned value in a dummy variable.
|
164
191
|
#
|
165
192
|
# Reason is twofold: On one hand doing less calls is in general better.
|
166
193
|
# On the other hand it could be that the target has side-effects,
|
167
|
-
# whereas
|
194
|
+
# whereas conceptually, from the user point of view, the delegator should
|
168
195
|
# be doing one call.
|
169
196
|
if allow_nil
|
170
|
-
|
171
|
-
def #{method_prefix}#{method}(#{definition})
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
197
|
+
method_def = [
|
198
|
+
"def #{method_prefix}#{method}(#{definition})",
|
199
|
+
"_ = #{to}",
|
200
|
+
"if !_.nil? || nil.respond_to?(:#{method})",
|
201
|
+
" _.#{method}(#{definition})",
|
202
|
+
"end",
|
203
|
+
"end"
|
204
|
+
].join ';'
|
178
205
|
else
|
179
|
-
exception = %(raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
|
206
|
+
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
|
180
207
|
|
181
|
-
|
182
|
-
def #{method_prefix}#{method}(#{definition})
|
183
|
-
|
184
|
-
|
185
|
-
rescue NoMethodError => e
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
EOS
|
208
|
+
method_def = [
|
209
|
+
"def #{method_prefix}#{method}(#{definition})",
|
210
|
+
" _ = #{to}",
|
211
|
+
" _.#{method}(#{definition})",
|
212
|
+
"rescue NoMethodError => e",
|
213
|
+
" if _.nil? && e.name == :#{method}",
|
214
|
+
" #{exception}",
|
215
|
+
" else",
|
216
|
+
" raise",
|
217
|
+
" end",
|
218
|
+
"end"
|
219
|
+
].join ';'
|
194
220
|
end
|
221
|
+
|
222
|
+
module_eval(method_def, file, line)
|
195
223
|
end
|
196
224
|
end
|
197
225
|
end
|
@@ -59,20 +59,4 @@ class Module
|
|
59
59
|
def local_constants #:nodoc:
|
60
60
|
constants(false)
|
61
61
|
end
|
62
|
-
|
63
|
-
# *DEPRECATED*: Use +local_constants+ instead.
|
64
|
-
#
|
65
|
-
# Returns the names of the constants defined locally as strings.
|
66
|
-
#
|
67
|
-
# module M
|
68
|
-
# X = 1
|
69
|
-
# end
|
70
|
-
# M.local_constant_names # => ["X"]
|
71
|
-
#
|
72
|
-
# This method is useful for forward compatibility, since Ruby 1.8 returns
|
73
|
-
# constant names as strings, whereas 1.9 returns them as symbols.
|
74
|
-
def local_constant_names
|
75
|
-
ActiveSupport::Deprecation.warn 'Module#local_constant_names is deprecated, use Module#local_constants instead'
|
76
|
-
local_constants.map { |c| c.to_s }
|
77
|
-
end
|
78
62
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Module
|
2
|
+
###
|
3
|
+
# TODO: remove this after 1.9 support is dropped
|
4
|
+
def methods_transplantable? # :nodoc:
|
5
|
+
x = Module.new {
|
6
|
+
def foo; end # :nodoc:
|
7
|
+
}
|
8
|
+
Module.new { define_method :bar, x.instance_method(:foo) }
|
9
|
+
true
|
10
|
+
rescue TypeError
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
@@ -4,6 +4,7 @@ require 'active_support/core_ext/module/anonymous'
|
|
4
4
|
require 'active_support/core_ext/module/reachable'
|
5
5
|
require 'active_support/core_ext/module/attribute_accessors'
|
6
6
|
require 'active_support/core_ext/module/attr_internal'
|
7
|
+
require 'active_support/core_ext/module/concerning'
|
7
8
|
require 'active_support/core_ext/module/delegation'
|
8
9
|
require 'active_support/core_ext/module/deprecation'
|
9
10
|
require 'active_support/core_ext/module/remove_method'
|
@@ -41,7 +41,7 @@ class Numeric
|
|
41
41
|
# 1000.to_s(:percentage, delimiter: '.', separator: ',') # => 1.000,000%
|
42
42
|
# 302.24398923423.to_s(:percentage, precision: 5) # => 302.24399%
|
43
43
|
# 1000.to_s(:percentage, locale: :fr) # => 1 000,000%
|
44
|
-
# 100.to_s(:percentage, format: '%n %') # => 100 %
|
44
|
+
# 100.to_s(:percentage, format: '%n %') # => 100.000 %
|
45
45
|
#
|
46
46
|
# Delimited:
|
47
47
|
# 12345678.to_s(:delimited) # => 12,345,678
|
@@ -78,7 +78,7 @@ class Numeric
|
|
78
78
|
# 1234567.to_s(:human_size, precision: 2) # => 1.2 MB
|
79
79
|
# 483989.to_s(:human_size, precision: 2) # => 470 KB
|
80
80
|
# 1234567.to_s(:human_size, precision: 2, separator: ',') # => 1,2 MB
|
81
|
-
# 1234567890123.to_s(:human_size, precision: 5) # => "1.
|
81
|
+
# 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
|
82
82
|
# 524288000.to_s(:human_size, precision: 5) # => "500 MB"
|
83
83
|
#
|
84
84
|
# Human-friendly format:
|
@@ -118,7 +118,15 @@ class Numeric
|
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
-
[Float,
|
121
|
+
klasses = [Float, BigDecimal]
|
122
|
+
# Ruby 2.4+ unifies Fixnum & Bignum into Integer.
|
123
|
+
if 0.class == Integer
|
124
|
+
klasses << Integer
|
125
|
+
else
|
126
|
+
klasses << Fixnum << Bignum
|
127
|
+
end
|
128
|
+
|
129
|
+
klasses.each do |klass|
|
122
130
|
klass.send(:alias_method, :to_default_s, :to_s)
|
123
131
|
|
124
132
|
klass.send(:define_method, :to_s) do |*args|
|
@@ -16,21 +16,6 @@ class Numeric
|
|
16
16
|
#
|
17
17
|
# # equivalent to Time.current.advance(months: 4, years: 5)
|
18
18
|
# (4.months + 5.years).from_now
|
19
|
-
#
|
20
|
-
# While these methods provide precise calculation when used as in the examples above, care
|
21
|
-
# should be taken to note that this is not true if the result of `months', `years', etc is
|
22
|
-
# converted before use:
|
23
|
-
#
|
24
|
-
# # equivalent to 30.days.to_i.from_now
|
25
|
-
# 1.month.to_i.from_now
|
26
|
-
#
|
27
|
-
# # equivalent to 365.25.days.to_f.from_now
|
28
|
-
# 1.year.to_f.from_now
|
29
|
-
#
|
30
|
-
# In such cases, Ruby's core
|
31
|
-
# Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
|
32
|
-
# Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
|
33
|
-
# date and time arithmetic.
|
34
19
|
def seconds
|
35
20
|
ActiveSupport::Duration.new(self, [[:seconds, self]])
|
36
21
|
end
|
@@ -61,19 +46,9 @@ class Numeric
|
|
61
46
|
end
|
62
47
|
alias :fortnight :fortnights
|
63
48
|
|
64
|
-
#
|
65
|
-
|
66
|
-
|
49
|
+
# Used with the standard time durations, like 1.hour.in_milliseconds --
|
50
|
+
# so we can feed them to JavaScript functions like getTime().
|
51
|
+
def in_milliseconds
|
52
|
+
self * 1000
|
67
53
|
end
|
68
|
-
|
69
|
-
# Reads best with argument: 10.minutes.until(time)
|
70
|
-
alias :until :ago
|
71
|
-
|
72
|
-
# Reads best with argument: 10.minutes.since(time)
|
73
|
-
def since(time = ::Time.current)
|
74
|
-
time + self
|
75
|
-
end
|
76
|
-
|
77
|
-
# Reads best without arguments: 10.minutes.from_now
|
78
|
-
alias :from_now :since
|
79
54
|
end
|
@@ -2,38 +2,44 @@
|
|
2
2
|
|
3
3
|
class Object
|
4
4
|
# An object is blank if it's false, empty, or a whitespace string.
|
5
|
-
# For example, '', ' ', +nil+, [], and {} are all blank.
|
5
|
+
# For example, +false+, '', ' ', +nil+, [], and {} are all blank.
|
6
6
|
#
|
7
|
-
# This simplifies
|
7
|
+
# This simplifies
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# !address || address.empty?
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# to
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# address.blank?
|
14
|
+
#
|
15
|
+
# @return [true, false]
|
14
16
|
def blank?
|
15
|
-
respond_to?(:empty?) ? empty? : !self
|
17
|
+
respond_to?(:empty?) ? !!empty? : !self
|
16
18
|
end
|
17
19
|
|
18
|
-
# An object is present if it's not
|
20
|
+
# An object is present if it's not blank.
|
21
|
+
#
|
22
|
+
# @return [true, false]
|
19
23
|
def present?
|
20
24
|
!blank?
|
21
25
|
end
|
22
26
|
|
23
|
-
# Returns
|
24
|
-
# <tt>object.presence</tt> is equivalent to
|
27
|
+
# Returns the receiver if it's present otherwise returns +nil+.
|
28
|
+
# <tt>object.presence</tt> is equivalent to
|
25
29
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
30
|
+
# object.present? ? object : nil
|
31
|
+
#
|
32
|
+
# For example, something like
|
29
33
|
#
|
30
34
|
# state = params[:state] if params[:state].present?
|
31
35
|
# country = params[:country] if params[:country].present?
|
32
36
|
# region = state || country || 'US'
|
33
37
|
#
|
34
|
-
#
|
38
|
+
# becomes
|
35
39
|
#
|
36
40
|
# region = params[:state].presence || params[:country].presence || 'US'
|
41
|
+
#
|
42
|
+
# @return [Object]
|
37
43
|
def presence
|
38
44
|
self if present?
|
39
45
|
end
|
@@ -43,6 +49,8 @@ class NilClass
|
|
43
49
|
# +nil+ is blank:
|
44
50
|
#
|
45
51
|
# nil.blank? # => true
|
52
|
+
#
|
53
|
+
# @return [true]
|
46
54
|
def blank?
|
47
55
|
true
|
48
56
|
end
|
@@ -52,6 +60,8 @@ class FalseClass
|
|
52
60
|
# +false+ is blank:
|
53
61
|
#
|
54
62
|
# false.blank? # => true
|
63
|
+
#
|
64
|
+
# @return [true]
|
55
65
|
def blank?
|
56
66
|
true
|
57
67
|
end
|
@@ -61,6 +71,8 @@ class TrueClass
|
|
61
71
|
# +true+ is not blank:
|
62
72
|
#
|
63
73
|
# true.blank? # => false
|
74
|
+
#
|
75
|
+
# @return [false]
|
64
76
|
def blank?
|
65
77
|
false
|
66
78
|
end
|
@@ -71,6 +83,8 @@ class Array
|
|
71
83
|
#
|
72
84
|
# [].blank? # => true
|
73
85
|
# [1,2,3].blank? # => false
|
86
|
+
#
|
87
|
+
# @return [true, false]
|
74
88
|
alias_method :blank?, :empty?
|
75
89
|
end
|
76
90
|
|
@@ -79,18 +93,28 @@ class Hash
|
|
79
93
|
#
|
80
94
|
# {}.blank? # => true
|
81
95
|
# { key: 'value' }.blank? # => false
|
96
|
+
#
|
97
|
+
# @return [true, false]
|
82
98
|
alias_method :blank?, :empty?
|
83
99
|
end
|
84
100
|
|
85
101
|
class String
|
102
|
+
BLANK_RE = /\A[[:space:]]*\z/
|
103
|
+
|
86
104
|
# A string is blank if it's empty or contains whitespaces only:
|
87
105
|
#
|
88
|
-
# ''.blank?
|
89
|
-
# ' '.blank?
|
90
|
-
#
|
91
|
-
# '
|
106
|
+
# ''.blank? # => true
|
107
|
+
# ' '.blank? # => true
|
108
|
+
# "\t\n\r".blank? # => true
|
109
|
+
# ' blah '.blank? # => false
|
110
|
+
#
|
111
|
+
# Unicode whitespace is supported:
|
112
|
+
#
|
113
|
+
# "\u00a0".blank? # => true
|
114
|
+
#
|
115
|
+
# @return [true, false]
|
92
116
|
def blank?
|
93
|
-
|
117
|
+
BLANK_RE === self
|
94
118
|
end
|
95
119
|
end
|
96
120
|
|
@@ -99,6 +123,8 @@ class Numeric #:nodoc:
|
|
99
123
|
#
|
100
124
|
# 1.blank? # => false
|
101
125
|
# 0.blank? # => false
|
126
|
+
#
|
127
|
+
# @return [false]
|
102
128
|
def blank?
|
103
129
|
false
|
104
130
|
end
|
@@ -8,8 +8,8 @@ class Object
|
|
8
8
|
# dup = object.deep_dup
|
9
9
|
# dup.instance_variable_set(:@a, 1)
|
10
10
|
#
|
11
|
-
# object.instance_variable_defined?(:@a)
|
12
|
-
# dup.instance_variable_defined?(:@a)
|
11
|
+
# object.instance_variable_defined?(:@a) # => false
|
12
|
+
# dup.instance_variable_defined?(:@a) # => true
|
13
13
|
def deep_dup
|
14
14
|
duplicable? ? dup : self
|
15
15
|
end
|
@@ -22,8 +22,8 @@ class Array
|
|
22
22
|
# dup = array.deep_dup
|
23
23
|
# dup[1][2] = 4
|
24
24
|
#
|
25
|
-
# array[1][2]
|
26
|
-
# dup[1][2]
|
25
|
+
# array[1][2] # => nil
|
26
|
+
# dup[1][2] # => 4
|
27
27
|
def deep_dup
|
28
28
|
map { |it| it.deep_dup }
|
29
29
|
end
|
@@ -36,8 +36,8 @@ class Hash
|
|
36
36
|
# dup = hash.deep_dup
|
37
37
|
# dup[:a][:c] = 'c'
|
38
38
|
#
|
39
|
-
# hash[:a][:c]
|
40
|
-
# dup[:a][:c]
|
39
|
+
# hash[:a][:c] # => nil
|
40
|
+
# dup[:a][:c] # => "c"
|
41
41
|
def deep_dup
|
42
42
|
each_with_object(dup) do |(key, value), hash|
|
43
43
|
hash[key.deep_dup] = value.deep_dup
|