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.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +364 -135
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -4
  5. data/lib/active_support/backtrace_cleaner.rb +33 -25
  6. data/lib/active_support/basic_object.rb +7 -17
  7. data/lib/active_support/benchmarkable.rb +19 -15
  8. data/lib/active_support/buffered_logger.rb +9 -113
  9. data/lib/active_support/cache/file_store.rb +14 -14
  10. data/lib/active_support/cache/mem_cache_store.rb +24 -30
  11. data/lib/active_support/cache/memory_store.rb +2 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +48 -37
  13. data/lib/active_support/cache.rb +228 -183
  14. data/lib/active_support/callbacks.rb +201 -253
  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/array/access.rb +17 -9
  19. data/lib/active_support/core_ext/array/conversions.rb +115 -55
  20. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  21. data/lib/active_support/core_ext/array/grouping.rb +21 -22
  22. data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
  23. data/lib/active_support/core_ext/array/wrap.rb +13 -16
  24. data/lib/active_support/core_ext/array.rb +0 -1
  25. data/lib/active_support/core_ext/benchmark.rb +7 -0
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -24
  27. data/lib/active_support/core_ext/class/attribute.rb +40 -32
  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/calculations.rb +44 -187
  32. data/lib/active_support/core_ext/date/conversions.rb +16 -38
  33. data/lib/active_support/core_ext/date/zones.rb +25 -2
  34. data/lib/active_support/core_ext/date.rb +5 -0
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
  36. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
  37. data/lib/active_support/core_ext/date_time/calculations.rb +77 -62
  38. data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
  39. data/lib/active_support/core_ext/date_time/zones.rb +11 -8
  40. data/lib/active_support/core_ext/date_time.rb +4 -0
  41. data/lib/active_support/core_ext/enumerable.rb +26 -73
  42. data/lib/active_support/core_ext/file/atomic.rb +27 -11
  43. data/lib/active_support/core_ext/file.rb +0 -1
  44. data/lib/active_support/core_ext/hash/conversions.rb +145 -79
  45. data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
  46. data/lib/active_support/core_ext/hash/diff.rb +5 -4
  47. data/lib/active_support/core_ext/hash/except.rb +1 -9
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
  49. data/lib/active_support/core_ext/hash/keys.rb +108 -24
  50. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  51. data/lib/active_support/core_ext/hash/slice.rb +12 -12
  52. data/lib/active_support/core_ext/hash.rb +0 -1
  53. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  54. data/lib/active_support/core_ext/integer/time.rb +17 -12
  55. data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
  56. data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  58. data/lib/active_support/core_ext/load_error.rb +7 -5
  59. data/lib/active_support/core_ext/logger.rb +7 -23
  60. data/lib/active_support/core_ext/marshal.rb +21 -0
  61. data/lib/active_support/core_ext/module/aliasing.rb +8 -9
  62. data/lib/active_support/core_ext/module/anonymous.rb +2 -7
  63. data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
  64. data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
  65. data/lib/active_support/core_ext/module/delegation.rb +92 -49
  66. data/lib/active_support/core_ext/module/deprecation.rb +19 -3
  67. data/lib/active_support/core_ext/module/introspection.rb +17 -27
  68. data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
  69. data/lib/active_support/core_ext/module/remove_method.rb +1 -5
  70. data/lib/active_support/core_ext/module.rb +1 -3
  71. data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
  72. data/lib/active_support/core_ext/numeric/time.rb +6 -6
  73. data/lib/active_support/core_ext/numeric.rb +1 -0
  74. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  75. data/lib/active_support/core_ext/object/blank.rb +7 -23
  76. data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
  77. data/lib/active_support/core_ext/object/duplicable.rb +1 -30
  78. data/lib/active_support/core_ext/object/inclusion.rb +8 -7
  79. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  80. data/lib/active_support/core_ext/object/to_json.rb +8 -0
  81. data/lib/active_support/core_ext/object/to_param.rb +5 -2
  82. data/lib/active_support/core_ext/object/try.rb +46 -25
  83. data/lib/active_support/core_ext/object/with_options.rb +7 -8
  84. data/lib/active_support/core_ext/object.rb +1 -0
  85. data/lib/active_support/core_ext/proc.rb +3 -0
  86. data/lib/active_support/core_ext/range/conversions.rb +0 -2
  87. data/lib/active_support/core_ext/range/include_range.rb +3 -1
  88. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  89. data/lib/active_support/core_ext/range.rb +0 -2
  90. data/lib/active_support/core_ext/string/access.rb +95 -90
  91. data/lib/active_support/core_ext/string/conversions.rb +27 -38
  92. data/lib/active_support/core_ext/string/encoding.rb +6 -9
  93. data/lib/active_support/core_ext/string/filters.rb +24 -18
  94. data/lib/active_support/core_ext/string/indent.rb +43 -0
  95. data/lib/active_support/core_ext/string/inflections.rb +70 -60
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  97. data/lib/active_support/core_ext/string/multibyte.rb +41 -64
  98. data/lib/active_support/core_ext/string/output_safety.rb +59 -51
  99. data/lib/active_support/core_ext/string/zones.rb +13 -0
  100. data/lib/active_support/core_ext/string.rb +2 -3
  101. data/lib/active_support/core_ext/struct.rb +6 -0
  102. data/lib/active_support/core_ext/thread.rb +74 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +108 -184
  104. data/lib/active_support/core_ext/time/conversions.rb +27 -51
  105. data/lib/active_support/core_ext/time/marshal.rb +0 -27
  106. data/lib/active_support/core_ext/time/zones.rb +27 -17
  107. data/lib/active_support/core_ext/time.rb +5 -0
  108. data/lib/active_support/core_ext/uri.rb +13 -17
  109. data/lib/active_support/core_ext.rb +3 -2
  110. data/lib/active_support/dependencies/autoload.rb +47 -20
  111. data/lib/active_support/dependencies.rb +160 -141
  112. data/lib/active_support/deprecation/behaviors.rb +44 -30
  113. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  114. data/lib/active_support/deprecation/method_wrappers.rb +33 -18
  115. data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
  116. data/lib/active_support/deprecation/reporting.rb +40 -11
  117. data/lib/active_support/deprecation.rb +39 -14
  118. data/lib/active_support/descendants_tracker.rb +34 -19
  119. data/lib/active_support/duration.rb +6 -8
  120. data/lib/active_support/file_update_checker.rb +63 -47
  121. data/lib/active_support/gzip.rb +11 -5
  122. data/lib/active_support/hash_with_indifferent_access.rb +127 -42
  123. data/lib/active_support/i18n.rb +4 -0
  124. data/lib/active_support/i18n_railtie.rb +5 -22
  125. data/lib/active_support/inflections.rb +14 -12
  126. data/lib/active_support/inflector/inflections.rb +108 -71
  127. data/lib/active_support/inflector/methods.rb +181 -160
  128. data/lib/active_support/inflector/transliterate.rb +16 -17
  129. data/lib/active_support/json/decoding.rb +18 -17
  130. data/lib/active_support/json/encoding.rb +93 -39
  131. data/lib/active_support/json/variable.rb +10 -1
  132. data/lib/active_support/key_generator.rb +75 -0
  133. data/lib/active_support/lazy_load_hooks.rb +21 -19
  134. data/lib/active_support/locale/en.yml +100 -3
  135. data/lib/active_support/log_subscriber/test_helper.rb +18 -15
  136. data/lib/active_support/log_subscriber.rb +35 -52
  137. data/lib/active_support/logger.rb +57 -0
  138. data/lib/active_support/logger_silence.rb +24 -0
  139. data/lib/active_support/message_encryptor.rb +38 -35
  140. data/lib/active_support/message_verifier.rb +9 -15
  141. data/lib/active_support/multibyte/chars.rb +80 -333
  142. data/lib/active_support/multibyte/unicode.rb +74 -64
  143. data/lib/active_support/multibyte.rb +5 -28
  144. data/lib/active_support/notifications/fanout.rb +112 -18
  145. data/lib/active_support/notifications/instrumenter.rb +33 -14
  146. data/lib/active_support/notifications.rb +79 -26
  147. data/lib/active_support/number_helper.rb +637 -0
  148. data/lib/active_support/ordered_hash.rb +8 -190
  149. data/lib/active_support/ordered_options.rb +21 -23
  150. data/lib/active_support/per_thread_registry.rb +52 -0
  151. data/lib/active_support/proxy_object.rb +13 -0
  152. data/lib/active_support/rails.rb +27 -0
  153. data/lib/active_support/railtie.rb +12 -32
  154. data/lib/active_support/rescuable.rb +9 -4
  155. data/lib/active_support/string_inquirer.rb +13 -8
  156. data/lib/active_support/subscriber.rb +93 -0
  157. data/lib/active_support/tagged_logging.rb +51 -73
  158. data/lib/active_support/test_case.rb +46 -17
  159. data/lib/active_support/testing/assertions.rb +56 -26
  160. data/lib/active_support/testing/autorun.rb +5 -0
  161. data/lib/active_support/testing/constant_lookup.rb +54 -0
  162. data/lib/active_support/testing/declarative.rb +1 -1
  163. data/lib/active_support/testing/deprecation.rb +0 -19
  164. data/lib/active_support/testing/isolation.rb +29 -58
  165. data/lib/active_support/testing/pending.rb +5 -43
  166. data/lib/active_support/testing/setup_and_teardown.rb +6 -92
  167. data/lib/active_support/testing/tagged_logging.rb +25 -0
  168. data/lib/active_support/time.rb +6 -21
  169. data/lib/active_support/time_with_zone.rb +80 -43
  170. data/lib/active_support/values/time_zone.rb +81 -60
  171. data/lib/active_support/values/unicode_tables.dat +0 -0
  172. data/lib/active_support/version.rb +7 -6
  173. data/lib/active_support/xml_mini/jdom.rb +9 -11
  174. data/lib/active_support/xml_mini/libxml.rb +1 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  176. data/lib/active_support/xml_mini/nokogiri.rb +1 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  178. data/lib/active_support/xml_mini/rexml.rb +6 -8
  179. data/lib/active_support/xml_mini.rb +35 -17
  180. data/lib/active_support.rb +8 -21
  181. metadata +104 -72
  182. data/lib/active_support/base64.rb +0 -54
  183. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  184. data/lib/active_support/core_ext/date/freeze.rb +0 -33
  185. data/lib/active_support/core_ext/exception.rb +0 -3
  186. data/lib/active_support/core_ext/file/path.rb +0 -5
  187. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  188. data/lib/active_support/core_ext/float.rb +0 -1
  189. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
  190. data/lib/active_support/core_ext/io.rb +0 -15
  191. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  192. data/lib/active_support/core_ext/module/synchronization.rb +0 -45
  193. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  194. data/lib/active_support/core_ext/process.rb +0 -1
  195. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  196. data/lib/active_support/core_ext/range/cover.rb +0 -3
  197. data/lib/active_support/core_ext/rexml.rb +0 -46
  198. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  199. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  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/jruby.rb +0 -115
  208. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  209. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  210. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  211. data/lib/active_support/testing/performance/ruby.rb +0 -152
  212. data/lib/active_support/testing/performance.rb +0 -317
  213. data/lib/active_support/time/autoload.rb +0 -5
  214. data/lib/active_support/whiny_nil.rb +0 -24
@@ -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)
@@ -1,8 +1,9 @@
1
1
  require 'rbconfig'
2
- require 'stringio'
2
+ require 'tempfile'
3
3
 
4
4
  module Kernel
5
- # Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
5
+ # Sets $VERBOSE to nil for the duration of the block and back to its original
6
+ # value afterwards.
6
7
  #
7
8
  # silence_warnings do
8
9
  # value = noisy_call # no warning voiced
@@ -13,12 +14,14 @@ module Kernel
13
14
  with_warnings(nil) { yield }
14
15
  end
15
16
 
16
- # Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.
17
+ # Sets $VERBOSE to +true+ for the duration of the block and back to its
18
+ # original value afterwards.
17
19
  def enable_warnings
18
20
  with_warnings(true) { yield }
19
21
  end
20
22
 
21
- # Sets $VERBOSE for the duration of the block and back to its original value afterwards.
23
+ # Sets $VERBOSE for the duration of the block and back to its original
24
+ # value afterwards.
22
25
  def with_warnings(flag)
23
26
  old_verbose, $VERBOSE = $VERBOSE, flag
24
27
  yield
@@ -51,40 +54,51 @@ module Kernel
51
54
  #
52
55
  # suppress(ZeroDivisionError) do
53
56
  # 1/0
54
- # puts "This code is NOT reached"
57
+ # puts 'This code is NOT reached'
55
58
  # end
56
59
  #
57
- # puts "This code gets executed and nothing related to ZeroDivisionError was seen"
60
+ # puts 'This code gets executed and nothing related to ZeroDivisionError was seen'
58
61
  def suppress(*exception_classes)
59
- begin yield
60
- rescue Exception => e
61
- raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
62
- end
62
+ yield
63
+ rescue Exception => e
64
+ raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
63
65
  end
64
66
 
65
67
  # Captures the given stream and returns it:
66
68
  #
67
- # stream = capture(:stdout) { puts "Cool" }
68
- # stream # => "Cool\n"
69
+ # stream = capture(:stdout) { puts 'notice' }
70
+ # stream # => "notice\n"
71
+ #
72
+ # stream = capture(:stderr) { warn 'error' }
73
+ # stream # => "error\n"
74
+ #
75
+ # even for subprocesses:
76
+ #
77
+ # stream = capture(:stdout) { system('echo notice') }
78
+ # stream # => "notice\n"
69
79
  #
80
+ # stream = capture(:stderr) { system('echo error 1>&2') }
81
+ # stream # => "error\n"
70
82
  def capture(stream)
71
- begin
72
- stream = stream.to_s
73
- eval "$#{stream} = StringIO.new"
74
- yield
75
- result = eval("$#{stream}").string
76
- ensure
77
- eval("$#{stream} = #{stream.upcase}")
78
- end
83
+ stream = stream.to_s
84
+ captured_stream = Tempfile.new(stream)
85
+ stream_io = eval("$#{stream}")
86
+ origin_stream = stream_io.dup
87
+ stream_io.reopen(captured_stream)
88
+
89
+ yield
79
90
 
80
- result
91
+ stream_io.rewind
92
+ return captured_stream.read
93
+ ensure
94
+ captured_stream.unlink
95
+ stream_io.reopen(origin_stream)
81
96
  end
82
97
  alias :silence :capture
83
98
 
84
99
  # Silences both STDOUT and STDERR, even for subprocesses.
85
100
  #
86
101
  # quietly { system 'bundle install' }
87
- #
88
102
  def quietly
89
103
  silence_stream(STDOUT) do
90
104
  silence_stream(STDERR) do
@@ -1,11 +1,4 @@
1
1
  module Kernel
2
- # Returns the object's singleton class.
3
- def singleton_class
4
- class << self
5
- self
6
- end
7
- end unless respond_to?(:singleton_class) # exists in 1.9.2
8
-
9
2
  # class_eval on an object acts like singleton_class.class_eval.
10
3
  def class_eval(*args, &block)
11
4
  singleton_class.class_eval(*args, &block)
@@ -6,12 +6,14 @@ class LoadError
6
6
  /^cannot load such file -- (.+)$/i,
7
7
  ]
8
8
 
9
- def path
10
- @path ||= begin
11
- REGEXPS.find do |regex|
12
- message =~ regex
9
+ unless method_defined?(:path)
10
+ def path
11
+ @path ||= begin
12
+ REGEXPS.find do |regex|
13
+ message =~ regex
14
+ end
15
+ $1
13
16
  end
14
- $1
15
17
  end
16
18
  end
17
19
 
@@ -1,5 +1,8 @@
1
1
  require 'active_support/core_ext/class/attribute_accessors'
2
2
  require 'active_support/deprecation'
3
+ require 'active_support/logger_silence'
4
+
5
+ ActiveSupport::Deprecation.warn 'this file is deprecated and will be removed'
3
6
 
4
7
  # Adds the 'around_level' method to Logger.
5
8
  class Logger #:nodoc:
@@ -29,34 +32,15 @@ require 'logger'
29
32
  #
30
33
  # logger.datetime_format = "%Y-%m-%d"
31
34
  #
32
- # Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
35
+ # Note: This logger is deprecated in favor of ActiveSupport::Logger
33
36
  class Logger
34
- ##
35
- # :singleton-method:
36
- # Set to false to disable the silencer
37
- cattr_accessor :silencer
38
- self.silencer = true
39
-
40
- # Silences the logger for the duration of the block.
41
- def silence(temporary_level = Logger::ERROR)
42
- if silencer
43
- begin
44
- old_logger_level, self.level = level, temporary_level
45
- yield self
46
- ensure
47
- self.level = old_logger_level
48
- end
49
- else
50
- yield self
51
- end
52
- end
53
- deprecate :silence
37
+ include LoggerSilence
54
38
 
55
39
  alias :old_datetime_format= :datetime_format=
56
40
  # Logging date-time format (string passed to +strftime+). Ignored if the formatter
57
41
  # does not respond to datetime_format=.
58
- def datetime_format=(datetime_format)
59
- formatter.datetime_format = datetime_format if formatter.respond_to?(:datetime_format=)
42
+ def datetime_format=(format)
43
+ formatter.datetime_format = format if formatter.respond_to?(:datetime_format=)
60
44
  end
61
45
 
62
46
  alias :old_datetime_format :datetime_format
@@ -0,0 +1,21 @@
1
+ require 'active_support/core_ext/module/aliasing'
2
+
3
+ module Marshal
4
+ class << self
5
+ def load_with_autoloading(source)
6
+ load_without_autoloading(source)
7
+ rescue ArgumentError, NameError => exc
8
+ if exc.message.match(%r|undefined class/module (.+)|)
9
+ # try loading the class/module
10
+ $1.constantize
11
+ # if it is a IO we need to go back to read the object
12
+ source.rewind if source.respond_to?(:rewind)
13
+ retry
14
+ else
15
+ raise exc
16
+ end
17
+ end
18
+
19
+ alias_method_chain :load, :autoloading
20
+ end
21
+ end
@@ -26,26 +26,25 @@ class Module
26
26
  aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
27
27
  yield(aliased_target, punctuation) if block_given?
28
28
 
29
- with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
29
+ with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
30
+ without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
30
31
 
31
32
  alias_method without_method, target
32
33
  alias_method target, with_method
33
34
 
34
35
  case
35
- when public_method_defined?(without_method)
36
- public target
37
- when protected_method_defined?(without_method)
38
- protected target
39
- when private_method_defined?(without_method)
40
- private target
36
+ when public_method_defined?(without_method)
37
+ public target
38
+ when protected_method_defined?(without_method)
39
+ protected target
40
+ when private_method_defined?(without_method)
41
+ private target
41
42
  end
42
43
  end
43
44
 
44
45
  # Allows you to make aliases for attributes, which includes
45
46
  # getter, setter, and query methods.
46
47
  #
47
- # Example:
48
- #
49
48
  # class Content < ActiveRecord::Base
50
49
  # # has a title attribute
51
50
  # end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/object/blank'
2
-
3
1
  class Module
4
2
  # A module may or may not have a name.
5
3
  #
@@ -7,7 +5,7 @@ class Module
7
5
  # M.name # => "M"
8
6
  #
9
7
  # m = Module.new
10
- # m.name # => ""
8
+ # m.name # => nil
11
9
  #
12
10
  # A module gets a name when it is first assigned to a constant. Either
13
11
  # via the +module+ or +class+ keyword or by an explicit assignment:
@@ -15,10 +13,7 @@ class Module
15
13
  # m = Module.new # creates an anonymous module
16
14
  # M = m # => m gets a name here as a side-effect
17
15
  # m.name # => "M"
18
- #
19
16
  def anonymous?
20
- # Uses blank? because the name of an anonymous class is an empty
21
- # string in 1.8, and nil in 1.9.
22
- name.blank?
17
+ name.nil?
23
18
  end
24
19
  end
@@ -15,7 +15,6 @@ class Module
15
15
  attr_internal_reader(*attrs)
16
16
  attr_internal_writer(*attrs)
17
17
  end
18
-
19
18
  alias_method :attr_internal, :attr_internal_accessor
20
19
 
21
20
  class << self; attr_accessor :attr_internal_naming_format end
@@ -4,6 +4,7 @@ class Module
4
4
  def mattr_reader(*syms)
5
5
  options = syms.extract_options!
6
6
  syms.each do |sym|
7
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
7
8
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
8
9
  @@#{sym} = nil unless defined? @@#{sym}
9
10
 
@@ -25,6 +26,7 @@ class Module
25
26
  def mattr_writer(*syms)
26
27
  options = syms.extract_options!
27
28
  syms.each do |sym|
29
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
28
30
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
29
31
  def self.#{sym}=(obj)
30
32
  @@#{sym} = obj
@@ -44,19 +46,19 @@ class Module
44
46
  # Extends the module object with module and instance accessors for class attributes,
45
47
  # just like the native attr* accessors for instance attributes.
46
48
  #
47
- # module AppConfiguration
48
- # mattr_accessor :google_api_key
49
- # self.google_api_key = "123456789"
49
+ # module AppConfiguration
50
+ # mattr_accessor :google_api_key
50
51
  #
51
- # mattr_accessor :paypal_url
52
- # self.paypal_url = "www.sandbox.paypal.com"
53
- # end
52
+ # self.google_api_key = "123456789"
53
+ # end
54
54
  #
55
- # AppConfiguration.google_api_key = "overriding the api key!"
55
+ # AppConfiguration.google_api_key # => "123456789"
56
+ # AppConfiguration.google_api_key = "overriding the api key!"
57
+ # AppConfiguration.google_api_key # => "overriding the api key!"
56
58
  #
57
- # To opt out of the instance writer method, pass :instance_writer => false.
58
- # To opt out of the instance reader method, pass :instance_reader => false.
59
- # To opt out of both instance methods, pass :instance_accessor => false.
59
+ # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
60
+ # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
61
+ # To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
60
62
  def mattr_accessor(*syms)
61
63
  mattr_reader(*syms)
62
64
  mattr_writer(*syms)
@@ -1,24 +1,26 @@
1
1
  class Module
2
- # Provides a delegate class method to easily expose contained objects' methods
3
- # as your own. Pass one or more methods (specified as symbols or strings)
4
- # and the name of the target object via the <tt>:to</tt> option (also a symbol
5
- # or string). At least one method and the <tt>:to</tt> option are required.
2
+ # Provides a +delegate+ class method to easily expose contained objects'
3
+ # public methods as your own.
4
+ #
5
+ # The macro receives one or more method names (specified as symbols or
6
+ # strings) and the name of the target object via the <tt>:to</tt> option
7
+ # (also a symbol or string).
6
8
  #
7
9
  # Delegation is particularly useful with Active Record associations:
8
10
  #
9
11
  # class Greeter < ActiveRecord::Base
10
12
  # def hello
11
- # "hello"
13
+ # 'hello'
12
14
  # end
13
15
  #
14
16
  # def goodbye
15
- # "goodbye"
17
+ # 'goodbye'
16
18
  # end
17
19
  # end
18
20
  #
19
21
  # class Foo < ActiveRecord::Base
20
22
  # belongs_to :greeter
21
- # delegate :hello, :to => :greeter
23
+ # delegate :hello, to: :greeter
22
24
  # end
23
25
  #
24
26
  # Foo.new.hello # => "hello"
@@ -28,7 +30,7 @@ class Module
28
30
  #
29
31
  # class Foo < ActiveRecord::Base
30
32
  # belongs_to :greeter
31
- # delegate :hello, :goodbye, :to => :greeter
33
+ # delegate :hello, :goodbye, to: :greeter
32
34
  # end
33
35
  #
34
36
  # Foo.new.goodbye # => "goodbye"
@@ -43,15 +45,27 @@ class Module
43
45
  # def initialize
44
46
  # @instance_array = [8,9,10,11]
45
47
  # end
46
- # delegate :sum, :to => :CONSTANT_ARRAY
47
- # delegate :min, :to => :@@class_array
48
- # delegate :max, :to => :@instance_array
48
+ # delegate :sum, to: :CONSTANT_ARRAY
49
+ # delegate :min, to: :@@class_array
50
+ # delegate :max, to: :@instance_array
49
51
  # end
50
52
  #
51
53
  # Foo.new.sum # => 6
52
54
  # Foo.new.min # => 4
53
55
  # Foo.new.max # => 11
54
56
  #
57
+ # It's also possible to delegate a method to the class by using +:class+:
58
+ #
59
+ # class Foo
60
+ # def self.hello
61
+ # "world"
62
+ # end
63
+ #
64
+ # delegate :hello, to: :class
65
+ # end
66
+ #
67
+ # Foo.new.hello # => "world"
68
+ #
55
69
  # Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value
56
70
  # is <tt>true</tt>, the delegate methods are prefixed with the name of the object being
57
71
  # delegated to.
@@ -59,10 +73,10 @@ class Module
59
73
  # Person = Struct.new(:name, :address)
60
74
  #
61
75
  # class Invoice < Struct.new(:client)
62
- # delegate :name, :address, :to => :client, :prefix => true
76
+ # delegate :name, :address, to: :client, prefix: true
63
77
  # end
64
78
  #
65
- # john_doe = Person.new("John Doe", "Vimmersvej 13")
79
+ # john_doe = Person.new('John Doe', 'Vimmersvej 13')
66
80
  # invoice = Invoice.new(john_doe)
67
81
  # invoice.client_name # => "John Doe"
68
82
  # invoice.client_address # => "Vimmersvej 13"
@@ -70,49 +84,64 @@ class Module
70
84
  # It is also possible to supply a custom prefix.
71
85
  #
72
86
  # class Invoice < Struct.new(:client)
73
- # delegate :name, :address, :to => :client, :prefix => :customer
87
+ # delegate :name, :address, to: :client, prefix: :customer
74
88
  # end
75
89
  #
76
90
  # invoice = Invoice.new(john_doe)
77
- # invoice.customer_name # => "John Doe"
78
- # invoice.customer_address # => "Vimmersvej 13"
91
+ # invoice.customer_name # => 'John Doe'
92
+ # invoice.customer_address # => 'Vimmersvej 13'
93
+ #
94
+ # If the target is +nil+ and does not respond to the delegated method a
95
+ # +NoMethodError+ is raised, as with any other value. Sometimes, however, it
96
+ # makes sense to be robust to that situation and that is the purpose of the
97
+ # <tt>:allow_nil</tt> option: If the target is not +nil+, or it is and
98
+ # responds to the method, everything works as usual. But if it is +nil+ and
99
+ # does not respond to the delegated method, +nil+ is returned.
100
+ #
101
+ # class User < ActiveRecord::Base
102
+ # has_one :profile
103
+ # delegate :age, to: :profile
104
+ # end
105
+ #
106
+ # User.new.age # raises NoMethodError: undefined method `age'
79
107
  #
80
- # If the delegate object is +nil+ an exception is raised, and that happens
81
- # no matter whether +nil+ responds to the delegated method. You can get a
82
- # +nil+ instead with the +:allow_nil+ option.
108
+ # But if not having a profile yet is fine and should not be an error
109
+ # condition:
83
110
  #
84
- # class Foo
85
- # attr_accessor :bar
86
- # def initialize(bar = nil)
87
- # @bar = bar
88
- # end
89
- # delegate :zoo, :to => :bar
90
- # end
111
+ # class User < ActiveRecord::Base
112
+ # has_one :profile
113
+ # delegate :age, to: :profile, allow_nil: true
114
+ # end
115
+ #
116
+ # User.new.age # nil
117
+ #
118
+ # Note that if the target is not +nil+ then the call is attempted regardless of the
119
+ # <tt>:allow_nil</tt> option, and thus an exception is still raised if said object
120
+ # does not respond to the method:
91
121
  #
92
- # Foo.new.zoo # raises NoMethodError exception (you called nil.zoo)
122
+ # class Foo
123
+ # def initialize(bar)
124
+ # @bar = bar
125
+ # end
93
126
  #
94
- # class Foo
95
- # attr_accessor :bar
96
- # def initialize(bar = nil)
97
- # @bar = bar
98
- # end
99
- # delegate :zoo, :to => :bar, :allow_nil => true
100
- # end
127
+ # delegate :name, to: :@bar, allow_nil: true
128
+ # end
101
129
  #
102
- # Foo.new.zoo # returns nil
130
+ # Foo.new("Bar").name # raises NoMethodError: undefined method `name'
103
131
  #
104
132
  def delegate(*methods)
105
133
  options = methods.pop
106
134
  unless options.is_a?(Hash) && to = options[:to]
107
- raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
135
+ raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
108
136
  end
109
- prefix, to, allow_nil = options[:prefix], options[:to], options[:allow_nil]
110
137
 
111
- if prefix == true && to.to_s =~ /^[^a-z_]/
112
- raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
138
+ prefix, allow_nil = options.values_at(:prefix, :allow_nil)
139
+
140
+ if prefix == true && to =~ /^[^a-z_]/
141
+ raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
113
142
  end
114
143
 
115
- method_prefix =
144
+ method_prefix = \
116
145
  if prefix
117
146
  "#{prefix == true ? to : prefix}_"
118
147
  else
@@ -122,25 +151,39 @@ class Module
122
151
  file, line = caller.first.split(':', 2)
123
152
  line = line.to_i
124
153
 
154
+ to = to.to_s
155
+ to = 'self.class' if to == 'class'
156
+
125
157
  methods.each do |method|
126
- method = method.to_s
158
+ # Attribute writer methods only accept one argument. Makes sure []=
159
+ # methods still accept two arguments.
160
+ definition = (method =~ /[^\]]=$/) ? 'arg' : '*args, &block'
127
161
 
162
+ # The following generated methods call the target exactly once, storing
163
+ # the returned value in a dummy variable.
164
+ #
165
+ # Reason is twofold: On one hand doing less calls is in general better.
166
+ # On the other hand it could be that the target has side-effects,
167
+ # whereas conceptualy, from the user point of view, the delegator should
168
+ # be doing one call.
128
169
  if allow_nil
129
- module_eval(<<-EOS, file, line - 2)
130
- def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
131
- if #{to} || #{to}.respond_to?(:#{method}) # if client || client.respond_to?(:name)
132
- #{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
170
+ module_eval(<<-EOS, file, line - 3)
171
+ def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
172
+ _ = #{to} # _ = client
173
+ if !_.nil? || nil.respond_to?(:#{method}) # if !_.nil? || nil.respond_to?(:name)
174
+ _.#{method}(#{definition}) # _.name(*args, &block)
133
175
  end # end
134
176
  end # end
135
177
  EOS
136
178
  else
137
179
  exception = %(raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
138
180
 
139
- module_eval(<<-EOS, file, line - 1)
140
- def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
141
- #{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
181
+ module_eval(<<-EOS, file, line - 2)
182
+ def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
183
+ _ = #{to} # _ = client
184
+ _.#{method}(#{definition}) # _.name(*args, &block)
142
185
  rescue NoMethodError # rescue NoMethodError
143
- if #{to}.nil? # if client.nil?
186
+ if _.nil? # if _.nil?
144
187
  #{exception} # # add helpful message to the exception
145
188
  else # else
146
189
  raise # raise
@@ -1,8 +1,24 @@
1
+ require 'active_support/deprecation/method_wrappers'
2
+
1
3
  class Module
2
- # Declare that a method has been deprecated.
3
4
  # deprecate :foo
4
- # deprecate :bar => 'message'
5
- # deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
5
+ # deprecate bar: 'message'
6
+ # deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'
7
+ #
8
+ # You can also use custom deprecator instance:
9
+ #
10
+ # deprecate :foo, deprecator: MyLib::Deprecator.new
11
+ # deprecate :foo, bar: "warning!", deprecator: MyLib::Deprecator.new
12
+ #
13
+ # \Custom deprecators must respond to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt>
14
+ # method where you can implement your custom warning behavior.
15
+ #
16
+ # class MyLib::Deprecator
17
+ # def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
18
+ # message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
19
+ # Kernel.warn message
20
+ # end
21
+ # end
6
22
  def deprecate(*method_names)
7
23
  ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
8
24
  end