activesupport 3.2.22.5 → 4.0.0.beta1

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.

Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +325 -136
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -2
  5. data/lib/active_support.rb +8 -21
  6. data/lib/active_support/backtrace_cleaner.rb +33 -25
  7. data/lib/active_support/basic_object.rb +7 -17
  8. data/lib/active_support/benchmarkable.rb +19 -15
  9. data/lib/active_support/buffered_logger.rb +9 -113
  10. data/lib/active_support/cache.rb +203 -171
  11. data/lib/active_support/cache/file_store.rb +12 -12
  12. data/lib/active_support/cache/mem_cache_store.rb +24 -30
  13. data/lib/active_support/cache/memory_store.rb +2 -0
  14. data/lib/active_support/callbacks.rb +195 -247
  15. data/lib/active_support/concern.rb +16 -23
  16. data/lib/active_support/concurrency/latch.rb +27 -0
  17. data/lib/active_support/configurable.rb +69 -12
  18. data/lib/active_support/core_ext.rb +1 -0
  19. data/lib/active_support/core_ext/array.rb +0 -1
  20. data/lib/active_support/core_ext/array/access.rb +17 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +113 -55
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +21 -22
  24. data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
  25. data/lib/active_support/core_ext/array/wrap.rb +11 -14
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +7 -24
  27. data/lib/active_support/core_ext/class/attribute.rb +12 -8
  28. data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
  29. data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
  30. data/lib/active_support/core_ext/class/subclasses.rb +11 -5
  31. data/lib/active_support/core_ext/date.rb +6 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +34 -188
  33. data/lib/active_support/core_ext/date/conversions.rb +16 -38
  34. data/lib/active_support/core_ext/date/infinite_comparable.rb +5 -0
  35. data/lib/active_support/core_ext/date/zones.rb +25 -2
  36. data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
  37. data/lib/active_support/core_ext/date_time.rb +5 -0
  38. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
  39. data/lib/active_support/core_ext/date_time/calculations.rb +73 -65
  40. data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
  41. data/lib/active_support/core_ext/date_time/infinite_comparable.rb +5 -0
  42. data/lib/active_support/core_ext/date_time/zones.rb +11 -8
  43. data/lib/active_support/core_ext/enumerable.rb +26 -73
  44. data/lib/active_support/core_ext/file.rb +0 -1
  45. data/lib/active_support/core_ext/file/atomic.rb +27 -11
  46. data/lib/active_support/core_ext/hash.rb +0 -1
  47. data/lib/active_support/core_ext/hash/conversions.rb +145 -79
  48. data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
  49. data/lib/active_support/core_ext/hash/diff.rb +5 -4
  50. data/lib/active_support/core_ext/hash/except.rb +1 -9
  51. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
  52. data/lib/active_support/core_ext/hash/keys.rb +108 -24
  53. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  54. data/lib/active_support/core_ext/hash/slice.rb +12 -12
  55. data/lib/active_support/core_ext/infinite_comparable.rb +35 -0
  56. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  57. data/lib/active_support/core_ext/integer/time.rb +17 -12
  58. data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
  59. data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
  60. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  61. data/lib/active_support/core_ext/load_error.rb +7 -5
  62. data/lib/active_support/core_ext/logger.rb +7 -23
  63. data/lib/active_support/core_ext/marshal.rb +19 -0
  64. data/lib/active_support/core_ext/module.rb +1 -3
  65. data/lib/active_support/core_ext/module/aliasing.rb +8 -9
  66. data/lib/active_support/core_ext/module/anonymous.rb +2 -7
  67. data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
  68. data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
  69. data/lib/active_support/core_ext/module/delegation.rb +57 -40
  70. data/lib/active_support/core_ext/module/deprecation.rb +19 -3
  71. data/lib/active_support/core_ext/module/introspection.rb +17 -27
  72. data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
  73. data/lib/active_support/core_ext/module/remove_method.rb +1 -5
  74. data/lib/active_support/core_ext/numeric.rb +2 -0
  75. data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
  76. data/lib/active_support/core_ext/numeric/infinite_comparable.rb +9 -0
  77. data/lib/active_support/core_ext/numeric/time.rb +6 -6
  78. data/lib/active_support/core_ext/object.rb +1 -0
  79. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  80. data/lib/active_support/core_ext/object/blank.rb +7 -23
  81. data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
  82. data/lib/active_support/core_ext/object/duplicable.rb +1 -30
  83. data/lib/active_support/core_ext/object/inclusion.rb +6 -6
  84. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  85. data/lib/active_support/core_ext/object/to_json.rb +8 -0
  86. data/lib/active_support/core_ext/object/to_param.rb +5 -2
  87. data/lib/active_support/core_ext/object/try.rb +46 -25
  88. data/lib/active_support/core_ext/object/with_options.rb +7 -8
  89. data/lib/active_support/core_ext/proc.rb +3 -0
  90. data/lib/active_support/core_ext/range.rb +0 -2
  91. data/lib/active_support/core_ext/range/conversions.rb +0 -2
  92. data/lib/active_support/core_ext/range/include_range.rb +1 -1
  93. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  94. data/lib/active_support/core_ext/string.rb +2 -2
  95. data/lib/active_support/core_ext/string/access.rb +95 -90
  96. data/lib/active_support/core_ext/string/conversions.rb +29 -38
  97. data/lib/active_support/core_ext/string/encoding.rb +6 -9
  98. data/lib/active_support/core_ext/string/filters.rb +24 -18
  99. data/lib/active_support/core_ext/string/indent.rb +43 -0
  100. data/lib/active_support/core_ext/string/inflections.rb +70 -60
  101. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  102. data/lib/active_support/core_ext/string/multibyte.rb +41 -64
  103. data/lib/active_support/core_ext/string/output_safety.rb +59 -51
  104. data/lib/active_support/core_ext/string/zones.rb +13 -0
  105. data/lib/active_support/core_ext/struct.rb +6 -0
  106. data/lib/active_support/core_ext/thread.rb +74 -0
  107. data/lib/active_support/core_ext/time.rb +6 -0
  108. data/lib/active_support/core_ext/time/calculations.rb +105 -193
  109. data/lib/active_support/core_ext/time/conversions.rb +27 -51
  110. data/lib/active_support/core_ext/time/infinite_comparable.rb +5 -0
  111. data/lib/active_support/core_ext/time/marshal.rb +0 -27
  112. data/lib/active_support/core_ext/time/zones.rb +27 -17
  113. data/lib/active_support/core_ext/uri.rb +13 -17
  114. data/lib/active_support/dependencies.rb +160 -141
  115. data/lib/active_support/dependencies/autoload.rb +47 -20
  116. data/lib/active_support/deprecation.rb +39 -14
  117. data/lib/active_support/deprecation/behaviors.rb +44 -30
  118. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  119. data/lib/active_support/deprecation/method_wrappers.rb +33 -18
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
  121. data/lib/active_support/deprecation/reporting.rb +40 -11
  122. data/lib/active_support/descendants_tracker.rb +34 -19
  123. data/lib/active_support/duration.rb +6 -8
  124. data/lib/active_support/file_update_checker.rb +63 -47
  125. data/lib/active_support/gzip.rb +11 -5
  126. data/lib/active_support/hash_with_indifferent_access.rb +112 -37
  127. data/lib/active_support/i18n.rb +4 -0
  128. data/lib/active_support/i18n_railtie.rb +5 -22
  129. data/lib/active_support/inflections.rb +14 -12
  130. data/lib/active_support/inflector/inflections.rb +108 -71
  131. data/lib/active_support/inflector/methods.rb +181 -160
  132. data/lib/active_support/inflector/transliterate.rb +16 -17
  133. data/lib/active_support/json/decoding.rb +18 -17
  134. data/lib/active_support/json/encoding.rb +93 -39
  135. data/lib/active_support/json/variable.rb +10 -1
  136. data/lib/active_support/key_generator.rb +75 -0
  137. data/lib/active_support/lazy_load_hooks.rb +21 -19
  138. data/lib/active_support/locale/en.yml +100 -3
  139. data/lib/active_support/log_subscriber.rb +56 -36
  140. data/lib/active_support/log_subscriber/test_helper.rb +18 -15
  141. data/lib/active_support/logger.rb +57 -0
  142. data/lib/active_support/logger_silence.rb +24 -0
  143. data/lib/active_support/message_encryptor.rb +32 -29
  144. data/lib/active_support/message_verifier.rb +8 -14
  145. data/lib/active_support/multibyte.rb +5 -28
  146. data/lib/active_support/multibyte/chars.rb +80 -333
  147. data/lib/active_support/multibyte/unicode.rb +74 -64
  148. data/lib/active_support/notifications.rb +57 -25
  149. data/lib/active_support/notifications/fanout.rb +105 -18
  150. data/lib/active_support/notifications/instrumenter.rb +32 -13
  151. data/lib/active_support/number_helper.rb +636 -0
  152. data/lib/active_support/ordered_hash.rb +8 -190
  153. data/lib/active_support/ordered_options.rb +21 -23
  154. data/lib/active_support/proxy_object.rb +13 -0
  155. data/lib/active_support/rails.rb +27 -0
  156. data/lib/active_support/railtie.rb +12 -32
  157. data/lib/active_support/rescuable.rb +9 -4
  158. data/lib/active_support/string_inquirer.rb +13 -8
  159. data/lib/active_support/tagged_logging.rb +51 -73
  160. data/lib/active_support/test_case.rb +46 -17
  161. data/lib/active_support/testing/assertions.rb +56 -26
  162. data/lib/active_support/testing/autorun.rb +5 -0
  163. data/lib/active_support/testing/constant_lookup.rb +52 -0
  164. data/lib/active_support/testing/declarative.rb +1 -1
  165. data/lib/active_support/testing/deprecation.rb +0 -19
  166. data/lib/active_support/testing/isolation.rb +25 -58
  167. data/lib/active_support/testing/pending.rb +5 -43
  168. data/lib/active_support/testing/setup_and_teardown.rb +6 -92
  169. data/lib/active_support/testing/tagged_logging.rb +25 -0
  170. data/lib/active_support/time.rb +6 -21
  171. data/lib/active_support/time_with_zone.rb +78 -43
  172. data/lib/active_support/values/time_zone.rb +77 -58
  173. data/lib/active_support/values/unicode_tables.dat +0 -0
  174. data/lib/active_support/version.rb +4 -4
  175. data/lib/active_support/xml_mini.rb +35 -17
  176. data/lib/active_support/xml_mini/jdom.rb +9 -17
  177. data/lib/active_support/xml_mini/libxml.rb +1 -2
  178. data/lib/active_support/xml_mini/libxmlsax.rb +1 -2
  179. data/lib/active_support/xml_mini/nokogiri.rb +1 -2
  180. data/lib/active_support/xml_mini/nokogirisax.rb +1 -2
  181. data/lib/active_support/xml_mini/rexml.rb +6 -8
  182. metadata +107 -77
  183. data/lib/active_support/base64.rb +0 -54
  184. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  185. data/lib/active_support/core_ext/date/freeze.rb +0 -33
  186. data/lib/active_support/core_ext/exception.rb +0 -3
  187. data/lib/active_support/core_ext/file/path.rb +0 -5
  188. data/lib/active_support/core_ext/float.rb +0 -1
  189. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  190. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
  191. data/lib/active_support/core_ext/io.rb +0 -15
  192. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  193. data/lib/active_support/core_ext/module/synchronization.rb +0 -45
  194. data/lib/active_support/core_ext/process.rb +0 -1
  195. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  196. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  197. data/lib/active_support/core_ext/range/cover.rb +0 -3
  198. data/lib/active_support/core_ext/rexml.rb +0 -46
  199. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  200. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  201. data/lib/active_support/memoizable.rb +0 -116
  202. data/lib/active_support/multibyte/exceptions.rb +0 -8
  203. data/lib/active_support/multibyte/utils.rb +0 -60
  204. data/lib/active_support/ruby/shim.rb +0 -22
  205. data/lib/active_support/security_utils.rb +0 -27
  206. data/lib/active_support/testing/mochaing.rb +0 -7
  207. data/lib/active_support/testing/performance.rb +0 -317
  208. data/lib/active_support/testing/performance/jruby.rb +0 -115
  209. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  210. data/lib/active_support/testing/performance/ruby.rb +0 -152
  211. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  212. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  213. data/lib/active_support/time/autoload.rb +0 -5
  214. data/lib/active_support/whiny_nil.rb +0 -24
@@ -1,20 +1,26 @@
1
1
  class Hash
2
2
  # Returns a new hash with +self+ and +other_hash+ merged recursively.
3
3
  #
4
- # h1 = {:x => {:y => [4,5,6]}, :z => [7,8,9]}
5
- # h2 = {:x => {:y => [7,8,9]}, :z => "xyz"}
4
+ # h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
5
+ # h2 = { x: { y: [7,8,9] }, z: 'xyz' }
6
6
  #
7
- # h1.deep_merge(h2) #=> { :x => {:y => [7, 8, 9]}, :z => "xyz" }
8
- # h2.deep_merge(h1) #=> { :x => {:y => [4, 5, 6]}, :z => [7, 8, 9] }
9
- def deep_merge(other_hash)
10
- dup.deep_merge!(other_hash)
7
+ # h1.deep_merge(h2) #=> {x: {y: [7, 8, 9]}, z: "xyz"}
8
+ # h2.deep_merge(h1) #=> {x: {y: [4, 5, 6]}, z: [7, 8, 9]}
9
+ # h1.deep_merge(h2) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
10
+ # #=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
11
+ def deep_merge(other_hash, &block)
12
+ dup.deep_merge!(other_hash, &block)
11
13
  end
12
14
 
13
15
  # Same as +deep_merge+, but modifies +self+.
14
- def deep_merge!(other_hash)
16
+ def deep_merge!(other_hash, &block)
15
17
  other_hash.each_pair do |k,v|
16
18
  tv = self[k]
17
- self[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v
19
+ if tv.is_a?(Hash) && v.is_a?(Hash)
20
+ self[k] = tv.deep_merge(v, &block)
21
+ else
22
+ self[k] = block && tv ? block.call(k, tv, v) : v
23
+ end
18
24
  end
19
25
  self
20
26
  end
@@ -1,13 +1,14 @@
1
1
  class Hash
2
2
  # Returns a hash that represents the difference between two hashes.
3
3
  #
4
- # Examples:
5
- #
6
4
  # {1 => 2}.diff(1 => 2) # => {}
7
5
  # {1 => 2}.diff(1 => 3) # => {1 => 2}
8
6
  # {}.diff(1 => 2) # => {1 => 2}
9
7
  # {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
10
- def diff(h2)
11
- dup.delete_if { |k, v| h2[k] == v }.merge!(h2.dup.delete_if { |k, v| has_key?(k) })
8
+ def diff(other)
9
+ ActiveSupport::Deprecation.warn "Hash#diff is no longer used inside of Rails, and is being deprecated with no replacement. If you're using it to compare hashes for the purpose of testing, please use MiniTest's assert_equal instead."
10
+ dup.
11
+ delete_if { |k, v| other[k] == v }.
12
+ merge!(other.dup.delete_if { |k, v| has_key?(k) })
12
13
  end
13
14
  end
@@ -2,15 +2,7 @@ class Hash
2
2
  # Return a hash that includes everything but the given keys. This is useful for
3
3
  # limiting a set of parameters to everything but a few known toggles:
4
4
  #
5
- # @person.update_attributes(params[:person].except(:admin))
6
- #
7
- # If the receiver responds to +convert_key+, the method is called on each of the
8
- # arguments. This allows +except+ to play nice with hashes with indifferent access
9
- # for instance:
10
- #
11
- # {:a => 1}.with_indifferent_access.except(:a) # => {}
12
- # {:a => 1}.with_indifferent_access.except("a") # => {}
13
- #
5
+ # @person.update(params[:person].except(:admin))
14
6
  def except(*keys)
15
7
  dup.except!(*keys)
16
8
  end
@@ -1,10 +1,10 @@
1
1
  require 'active_support/hash_with_indifferent_access'
2
2
 
3
3
  class Hash
4
+
4
5
  # Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
5
6
  #
6
- # {:a => 1}.with_indifferent_access["a"] # => 1
7
- #
7
+ # { a: 1 }.with_indifferent_access['a'] # => 1
8
8
  def with_indifferent_access
9
9
  ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
10
10
  end
@@ -16,8 +16,7 @@ class Hash
16
16
  # converting to an <tt>ActiveSupport::HashWithIndifferentAccess</tt> would not be
17
17
  # desirable.
18
18
  #
19
- # b = {:b => 1}
20
- # {:a => b}.with_indifferent_access["a"] # calls b.nested_under_indifferent_access
21
- #
19
+ # b = { b: 1 }
20
+ # { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
22
21
  alias nested_under_indifferent_access with_indifferent_access
23
22
  end
@@ -1,54 +1,138 @@
1
1
  class Hash
2
+ # Return a new hash with all keys converted using the block operation.
3
+ #
4
+ # hash = { name: 'Rob', age: '28' }
5
+ #
6
+ # hash.transform_keys{ |key| key.to_s.upcase }
7
+ # # => { "NAME" => "Rob", "AGE" => "28" }
8
+ def transform_keys
9
+ result = {}
10
+ each_key do |key|
11
+ result[yield(key)] = self[key]
12
+ end
13
+ result
14
+ end
15
+
16
+ # Destructively convert all keys using the block operations.
17
+ # Same as transform_keys but modifies +self+.
18
+ def transform_keys!
19
+ keys.each do |key|
20
+ self[yield(key)] = delete(key)
21
+ end
22
+ self
23
+ end
24
+
2
25
  # Return a new hash with all keys converted to strings.
3
26
  #
4
- # { :name => 'Rob', :years => '28' }.stringify_keys
5
- # #=> { "name" => "Rob", "years" => "28" }
27
+ # hash = { name: 'Rob', age: '28' }
28
+ #
29
+ # hash.stringify_keys
30
+ # #=> { "name" => "Rob", "age" => "28" }
6
31
  def stringify_keys
7
- dup.stringify_keys!
32
+ transform_keys{ |key| key.to_s }
8
33
  end
9
34
 
10
35
  # Destructively convert all keys to strings. Same as
11
36
  # +stringify_keys+, but modifies +self+.
12
37
  def stringify_keys!
13
- keys.each do |key|
14
- self[key.to_s] = delete(key)
15
- end
16
- self
38
+ transform_keys!{ |key| key.to_s }
17
39
  end
18
40
 
19
41
  # Return a new hash with all keys converted to symbols, as long as
20
42
  # they respond to +to_sym+.
21
43
  #
22
- # { 'name' => 'Rob', 'years' => '28' }.symbolize_keys
23
- # #=> { :name => "Rob", :years => "28" }
44
+ # hash = { 'name' => 'Rob', 'age' => '28' }
45
+ #
46
+ # hash.symbolize_keys
47
+ # #=> { name: "Rob", age: "28" }
24
48
  def symbolize_keys
25
- dup.symbolize_keys!
49
+ transform_keys{ |key| key.to_sym rescue key }
26
50
  end
51
+ alias_method :to_options, :symbolize_keys
27
52
 
28
53
  # Destructively convert all keys to symbols, as long as they respond
29
54
  # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
30
55
  def symbolize_keys!
31
- keys.each do |key|
32
- self[(key.to_sym rescue key) || key] = delete(key)
33
- end
34
- self
56
+ transform_keys!{ |key| key.to_sym rescue key }
35
57
  end
36
-
37
- alias_method :to_options, :symbolize_keys
38
58
  alias_method :to_options!, :symbolize_keys!
39
59
 
40
- # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
41
- # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
42
- # as keys, this will fail.
60
+ # Validate all keys in a hash match <tt>*valid_keys</tt>, raising ArgumentError
61
+ # on a mismatch. Note that keys are NOT treated indifferently, meaning if you
62
+ # use strings for keys but assert symbols as keys, this will fail.
43
63
  #
44
- # ==== Examples
45
- # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
46
- # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key: name"
47
- # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
64
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
65
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
66
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
48
67
  def assert_valid_keys(*valid_keys)
49
68
  valid_keys.flatten!
50
69
  each_key do |k|
51
- raise(ArgumentError, "Unknown key: #{k}") unless valid_keys.include?(k)
70
+ raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
71
+ end
72
+ end
73
+
74
+ # Return a new hash with all keys converted by the block operation.
75
+ # This includes the keys from the root hash and from all
76
+ # nested hashes.
77
+ #
78
+ # hash = { person: { name: 'Rob', age: '28' } }
79
+ #
80
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
81
+ # # => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }
82
+ def deep_transform_keys(&block)
83
+ result = {}
84
+ each do |key, value|
85
+ result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
86
+ end
87
+ result
88
+ end
89
+
90
+ # Destructively convert all keys by using the block operation.
91
+ # This includes the keys from the root hash and from all
92
+ # nested hashes.
93
+ def deep_transform_keys!(&block)
94
+ keys.each do |key|
95
+ value = delete(key)
96
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
52
97
  end
98
+ self
99
+ end
100
+
101
+ # Return a new hash with all keys converted to strings.
102
+ # This includes the keys from the root hash and from all
103
+ # nested hashes.
104
+ #
105
+ # hash = { person: { name: 'Rob', age: '28' } }
106
+ #
107
+ # hash.deep_stringify_keys
108
+ # # => { "person" => { "name" => "Rob", "age" => "28" } }
109
+ def deep_stringify_keys
110
+ deep_transform_keys{ |key| key.to_s }
111
+ end
112
+
113
+ # Destructively convert all keys to strings.
114
+ # This includes the keys from the root hash and from all
115
+ # nested hashes.
116
+ def deep_stringify_keys!
117
+ deep_transform_keys!{ |key| key.to_s }
118
+ end
119
+
120
+ # Return a new hash with all keys converted to symbols, as long as
121
+ # they respond to +to_sym+. This includes the keys from the root hash
122
+ # and from all nested hashes.
123
+ #
124
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
125
+ #
126
+ # hash.deep_symbolize_keys
127
+ # # => { person: { name: "Rob", age: "28" } }
128
+ def deep_symbolize_keys
129
+ deep_transform_keys{ |key| key.to_sym rescue key }
130
+ end
131
+
132
+ # Destructively convert all keys to symbols, as long as they respond
133
+ # to +to_sym+. This includes the keys from the root hash and from all
134
+ # nested hashes.
135
+ def deep_symbolize_keys!
136
+ deep_transform_keys!{ |key| key.to_sym rescue key }
53
137
  end
54
138
  end
@@ -1,11 +1,11 @@
1
1
  class Hash
2
2
  # Merges the caller into +other_hash+. For example,
3
3
  #
4
- # options = options.reverse_merge(:size => 25, :velocity => 10)
4
+ # options = options.reverse_merge(size: 25, velocity: 10)
5
5
  #
6
6
  # is equivalent to
7
7
  #
8
- # options = {:size => 25, :velocity => 10}.merge(options)
8
+ # options = { size: 25, velocity: 10 }.merge(options)
9
9
  #
10
10
  # This is particularly useful for initializing an options hash
11
11
  # with default values.
@@ -18,6 +18,5 @@ class Hash
18
18
  # right wins if there is no left
19
19
  merge!( other_hash ){|key,left,right| left }
20
20
  end
21
-
22
21
  alias_method :reverse_update, :reverse_merge!
23
22
  end
@@ -3,7 +3,7 @@ class Hash
3
3
  # limiting an options hash to valid keys before passing to a method:
4
4
  #
5
5
  # def search(criteria = {})
6
- # assert_valid_keys(:mass, :velocity, :time)
6
+ # criteria.assert_valid_keys(:mass, :velocity, :time)
7
7
  # end
8
8
  #
9
9
  # search(options.slice(:mass, :velocity, :time))
@@ -13,17 +13,17 @@ class Hash
13
13
  # valid_keys = [:mass, :velocity, :time]
14
14
  # search(options.slice(*valid_keys))
15
15
  def slice(*keys)
16
- keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
17
- hash = self.class.new
18
- keys.each { |k| hash[k] = self[k] if has_key?(k) }
19
- hash
16
+ keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
17
+ keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
20
18
  end
21
19
 
22
20
  # Replaces the hash with only the given keys.
23
- # Returns a hash contained the removed key/value pairs
24
- # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d => 4}
21
+ # Returns a hash containing the removed key/value pairs.
22
+ #
23
+ # { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)
24
+ # # => {:c=>3, :d=>4}
25
25
  def slice!(*keys)
26
- keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
26
+ keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
27
27
  omit = slice(*self.keys - keys)
28
28
  hash = slice(*keys)
29
29
  replace(hash)
@@ -31,10 +31,10 @@ class Hash
31
31
  end
32
32
 
33
33
  # Removes and returns the key/value pairs matching the given keys.
34
- # {:a => 1, :b => 2, :c => 3, :d => 4}.extract!(:a, :b) # => {:a => 1, :b => 2}
34
+ #
35
+ # { a: 1, b: 2, c: 3, d: 4 }.extract!(:a, :b) # => {:a=>1, :b=>2}
36
+ # { a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1}
35
37
  def extract!(*keys)
36
- result = {}
37
- keys.each {|key| result[key] = delete(key) }
38
- result
38
+ keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
39
39
  end
40
40
  end
@@ -0,0 +1,35 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/module/aliasing'
3
+ require 'active_support/core_ext/object/try'
4
+
5
+ module InfiniteComparable
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ alias_method_chain :<=>, :infinity
10
+ end
11
+
12
+ define_method :'<=>_with_infinity' do |other|
13
+ if other.class == self.class
14
+ public_send :'<=>_without_infinity', other
15
+ else
16
+ infinite = try(:infinite?)
17
+ other_infinite = other.try(:infinite?)
18
+
19
+ # inf <=> inf
20
+ if infinite && other_infinite
21
+ infinite <=> other_infinite
22
+ # not_inf <=> inf
23
+ elsif other_infinite
24
+ -other_infinite
25
+ # inf <=> not_inf
26
+ elsif infinite
27
+ infinite
28
+ else
29
+ conversion = "to_#{self.class.name.downcase}"
30
+ other = other.public_send(conversion) if other.respond_to?(conversion)
31
+ public_send :'<=>_without_infinity', other
32
+ end
33
+ end
34
+ end
35
+ end
@@ -10,8 +10,20 @@ class Integer
10
10
  # 1003.ordinalize # => "1003rd"
11
11
  # -11.ordinalize # => "-11th"
12
12
  # -1001.ordinalize # => "-1001st"
13
- #
14
13
  def ordinalize
15
14
  ActiveSupport::Inflector.ordinalize(self)
16
15
  end
16
+
17
+ # Ordinal returns the suffix used to denote the position
18
+ # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
19
+ #
20
+ # 1.ordinal # => "st"
21
+ # 2.ordinal # => "nd"
22
+ # 1002.ordinal # => "nd"
23
+ # 1003.ordinal # => "rd"
24
+ # -11.ordinal # => "th"
25
+ # -1001.ordinal # => "st"
26
+ def ordinal
27
+ ActiveSupport::Inflector.ordinal(self)
28
+ end
17
29
  end
@@ -1,21 +1,26 @@
1
+ require 'active_support/duration'
2
+ require 'active_support/core_ext/numeric/time'
3
+
1
4
  class Integer
2
- # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
5
+ # Enables the use of time calculations and declarations, like <tt>45.minutes +
6
+ # 2.hours + 4.years</tt>.
3
7
  #
4
- # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
5
- # as well as adding or subtracting their results from a Time object. For example:
8
+ # These methods use Time#advance for precise date calculations when using
9
+ # <tt>from_now</tt>, +ago+, etc. as well as adding or subtracting their
10
+ # results from a Time object.
6
11
  #
7
- # # equivalent to Time.now.advance(:months => 1)
12
+ # # equivalent to Time.now.advance(months: 1)
8
13
  # 1.month.from_now
9
14
  #
10
- # # equivalent to Time.now.advance(:years => 2)
15
+ # # equivalent to Time.now.advance(years: 2)
11
16
  # 2.years.from_now
12
17
  #
13
- # # equivalent to Time.now.advance(:months => 4, :years => 5)
18
+ # # equivalent to Time.now.advance(months: 4, years: 5)
14
19
  # (4.months + 5.years).from_now
15
20
  #
16
- # While these methods provide precise calculation when used as in the examples above, care
17
- # should be taken to note that this is not true if the result of `months', `years', etc is
18
- # converted before use:
21
+ # While these methods provide precise calculation when used as in the examples
22
+ # above, care should be taken to note that this is not true if the result of
23
+ # +months+, +years+, etc is converted before use:
19
24
  #
20
25
  # # equivalent to 30.days.to_i.from_now
21
26
  # 1.month.to_i.from_now
@@ -24,9 +29,9 @@ class Integer
24
29
  # 1.year.to_f.from_now
25
30
  #
26
31
  # In such cases, Ruby's core
27
- # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
28
- # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
29
- # date and time arithmetic
32
+ # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
33
+ # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
34
+ # date and time arithmetic.
30
35
  def months
31
36
  ActiveSupport::Duration.new(self * 30.days, [[:months, self]])
32
37
  end
@@ -1,8 +1,8 @@
1
1
  module Kernel
2
2
  unless respond_to?(:debugger)
3
- # Starts a debugging session if ruby-debug has been loaded (call rails server --debugger to do load it).
3
+ # Starts a debugging session if the +debugger+ gem has been loaded (call rails server --debugger to do load it).
4
4
  def debugger
5
- message = "\n***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****\n"
5
+ message = "\n***** Debugger requested, but was not available (ensure the debugger gem is listed in Gemfile/installed as gem): Start server with --debugger to enable *****\n"
6
6
  defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
7
7
  end
8
8
  alias breakpoint debugger unless respond_to?(:breakpoint)