activesupport 3.1.0 → 5.0.0

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 (276) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +798 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +13 -7
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +38 -34
  7. data/lib/active_support/benchmarkable.rb +17 -28
  8. data/lib/active_support/cache/file_store.rb +85 -70
  9. data/lib/active_support/cache/mem_cache_store.rb +75 -66
  10. data/lib/active_support/cache/memory_store.rb +31 -23
  11. data/lib/active_support/cache/null_store.rb +41 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +73 -70
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  14. data/lib/active_support/cache.rb +360 -294
  15. data/lib/active_support/callbacks.rb +563 -393
  16. data/lib/active_support/concern.rb +42 -34
  17. data/lib/active_support/concurrency/latch.rb +19 -0
  18. data/lib/active_support/concurrency/share_lock.rb +186 -0
  19. data/lib/active_support/configurable.rb +70 -12
  20. data/lib/active_support/core_ext/array/access.rb +53 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +109 -62
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +39 -32
  24. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  25. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  26. data/lib/active_support/core_ext/array/wrap.rb +16 -18
  27. data/lib/active_support/core_ext/array.rb +2 -2
  28. data/lib/active_support/core_ext/benchmark.rb +7 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
  30. data/lib/active_support/core_ext/class/attribute.rb +47 -34
  31. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
  32. data/lib/active_support/core_ext/class/subclasses.rb +12 -7
  33. data/lib/active_support/core_ext/class.rb +0 -3
  34. data/lib/active_support/core_ext/date/blank.rb +12 -0
  35. data/lib/active_support/core_ext/date/calculations.rb +57 -167
  36. data/lib/active_support/core_ext/date/conversions.rb +31 -42
  37. data/lib/active_support/core_ext/date/zones.rb +2 -10
  38. data/lib/active_support/core_ext/date.rb +5 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  42. data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
  43. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  44. data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
  45. data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
  46. data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
  47. data/lib/active_support/core_ext/date_time.rb +5 -0
  48. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  49. data/lib/active_support/core_ext/enumerable.rb +81 -74
  50. data/lib/active_support/core_ext/file/atomic.rb +53 -26
  51. data/lib/active_support/core_ext/file.rb +0 -1
  52. data/lib/active_support/core_ext/hash/compact.rb +20 -0
  53. data/lib/active_support/core_ext/hash/conversions.rb +175 -70
  54. data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
  55. data/lib/active_support/core_ext/hash/except.rb +11 -12
  56. data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
  57. data/lib/active_support/core_ext/hash/keys.rb +147 -24
  58. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  59. data/lib/active_support/core_ext/hash/slice.rb +22 -14
  60. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  61. data/lib/active_support/core_ext/hash.rb +2 -2
  62. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  63. data/lib/active_support/core_ext/integer/multiple.rb +4 -0
  64. data/lib/active_support/core_ext/integer/time.rb +12 -22
  65. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  66. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  67. data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
  68. data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
  69. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  70. data/lib/active_support/core_ext/kernel.rb +2 -3
  71. data/lib/active_support/core_ext/load_error.rb +14 -7
  72. data/lib/active_support/core_ext/marshal.rb +22 -0
  73. data/lib/active_support/core_ext/module/aliasing.rb +16 -12
  74. data/lib/active_support/core_ext/module/anonymous.rb +12 -8
  75. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  76. data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
  77. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  78. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  79. data/lib/active_support/core_ext/module/delegation.rb +141 -68
  80. data/lib/active_support/core_ext/module/deprecation.rb +17 -3
  81. data/lib/active_support/core_ext/module/introspection.rb +9 -31
  82. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  83. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  84. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  85. data/lib/active_support/core_ext/module/remove_method.rb +24 -5
  86. data/lib/active_support/core_ext/module.rb +3 -3
  87. data/lib/active_support/core_ext/name_error.rb +15 -2
  88. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  89. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  90. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  91. data/lib/active_support/core_ext/numeric/time.rb +31 -36
  92. data/lib/active_support/core_ext/numeric.rb +2 -0
  93. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  94. data/lib/active_support/core_ext/object/blank.rb +52 -18
  95. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  96. data/lib/active_support/core_ext/object/duplicable.rb +12 -20
  97. data/lib/active_support/core_ext/object/inclusion.rb +13 -1
  98. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  99. data/lib/active_support/core_ext/object/json.rb +205 -0
  100. data/lib/active_support/core_ext/object/to_param.rb +1 -55
  101. data/lib/active_support/core_ext/object/to_query.rb +66 -9
  102. data/lib/active_support/core_ext/object/try.rb +124 -33
  103. data/lib/active_support/core_ext/object/with_options.rb +37 -11
  104. data/lib/active_support/core_ext/object.rb +2 -1
  105. data/lib/active_support/core_ext/range/conversions.rb +17 -7
  106. data/lib/active_support/core_ext/range/each.rb +21 -0
  107. data/lib/active_support/core_ext/range/include_range.rb +20 -18
  108. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  109. data/lib/active_support/core_ext/range.rb +1 -2
  110. data/lib/active_support/core_ext/securerandom.rb +23 -0
  111. data/lib/active_support/core_ext/string/access.rb +95 -90
  112. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  113. data/lib/active_support/core_ext/string/conversions.rb +41 -38
  114. data/lib/active_support/core_ext/string/exclude.rb +6 -1
  115. data/lib/active_support/core_ext/string/filters.rb +70 -17
  116. data/lib/active_support/core_ext/string/indent.rb +43 -0
  117. data/lib/active_support/core_ext/string/inflections.rb +139 -59
  118. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  119. data/lib/active_support/core_ext/string/multibyte.rb +46 -65
  120. data/lib/active_support/core_ext/string/output_safety.rb +153 -56
  121. data/lib/active_support/core_ext/string/strip.rb +3 -6
  122. data/lib/active_support/core_ext/string/zones.rb +14 -0
  123. data/lib/active_support/core_ext/string.rb +2 -3
  124. data/lib/active_support/core_ext/struct.rb +3 -0
  125. data/lib/active_support/core_ext/time/calculations.rb +173 -173
  126. data/lib/active_support/core_ext/time/compatibility.rb +5 -0
  127. data/lib/active_support/core_ext/time/conversions.rb +33 -29
  128. data/lib/active_support/core_ext/time/marshal.rb +2 -56
  129. data/lib/active_support/core_ext/time/zones.rb +57 -32
  130. data/lib/active_support/core_ext/time.rb +5 -0
  131. data/lib/active_support/core_ext/uri.rb +13 -19
  132. data/lib/active_support/core_ext.rb +3 -2
  133. data/lib/active_support/dependencies/autoload.rb +47 -20
  134. data/lib/active_support/dependencies/interlock.rb +51 -0
  135. data/lib/active_support/dependencies.rb +315 -265
  136. data/lib/active_support/deprecation/behaviors.rb +71 -30
  137. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  138. data/lib/active_support/deprecation/method_wrappers.rb +59 -18
  139. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
  140. data/lib/active_support/deprecation/reporting.rb +61 -14
  141. data/lib/active_support/deprecation.rb +38 -13
  142. data/lib/active_support/descendants_tracker.rb +34 -19
  143. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  144. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  145. data/lib/active_support/duration.rb +85 -14
  146. data/lib/active_support/evented_file_update_checker.rb +194 -0
  147. data/lib/active_support/execution_wrapper.rb +117 -0
  148. data/lib/active_support/executor.rb +6 -0
  149. data/lib/active_support/file_update_checker.rb +138 -17
  150. data/lib/active_support/gem_version.rb +15 -0
  151. data/lib/active_support/gzip.rb +11 -5
  152. data/lib/active_support/hash_with_indifferent_access.rb +199 -49
  153. data/lib/active_support/i18n.rb +6 -2
  154. data/lib/active_support/i18n_railtie.rb +40 -21
  155. data/lib/active_support/inflections.rb +22 -13
  156. data/lib/active_support/inflector/inflections.rb +175 -144
  157. data/lib/active_support/inflector/methods.rb +328 -91
  158. data/lib/active_support/inflector/transliterate.rb +51 -37
  159. data/lib/active_support/json/decoding.rb +31 -22
  160. data/lib/active_support/json/encoding.rb +88 -248
  161. data/lib/active_support/key_generator.rb +71 -0
  162. data/lib/active_support/lazy_load_hooks.rb +27 -25
  163. data/lib/active_support/locale/en.yml +102 -3
  164. data/lib/active_support/log_subscriber/test_helper.rb +24 -21
  165. data/lib/active_support/log_subscriber.rb +36 -49
  166. data/lib/active_support/logger.rb +106 -0
  167. data/lib/active_support/logger_silence.rb +28 -0
  168. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  169. data/lib/active_support/message_encryptor.rb +72 -36
  170. data/lib/active_support/message_verifier.rb +96 -24
  171. data/lib/active_support/multibyte/chars.rb +88 -333
  172. data/lib/active_support/multibyte/unicode.rb +156 -136
  173. data/lib/active_support/multibyte.rb +5 -28
  174. data/lib/active_support/notifications/fanout.rb +115 -19
  175. data/lib/active_support/notifications/instrumenter.rb +52 -15
  176. data/lib/active_support/notifications.rb +168 -33
  177. data/lib/active_support/number_helper/number_converter.rb +182 -0
  178. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  179. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  180. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  181. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  182. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  183. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  184. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  185. data/lib/active_support/number_helper.rb +368 -0
  186. data/lib/active_support/option_merger.rb +1 -1
  187. data/lib/active_support/ordered_hash.rb +18 -183
  188. data/lib/active_support/ordered_options.rb +44 -24
  189. data/lib/active_support/per_thread_registry.rb +58 -0
  190. data/lib/active_support/proxy_object.rb +13 -0
  191. data/lib/active_support/rails.rb +27 -0
  192. data/lib/active_support/railtie.rb +25 -34
  193. data/lib/active_support/reloader.rb +129 -0
  194. data/lib/active_support/rescuable.rb +98 -48
  195. data/lib/active_support/security_utils.rb +27 -0
  196. data/lib/active_support/string_inquirer.rb +14 -9
  197. data/lib/active_support/subscriber.rb +120 -0
  198. data/lib/active_support/tagged_logging.rb +78 -0
  199. data/lib/active_support/test_case.rb +69 -17
  200. data/lib/active_support/testing/assertions.rb +43 -41
  201. data/lib/active_support/testing/autorun.rb +12 -0
  202. data/lib/active_support/testing/constant_lookup.rb +50 -0
  203. data/lib/active_support/testing/declarative.rb +7 -21
  204. data/lib/active_support/testing/deprecation.rb +14 -33
  205. data/lib/active_support/testing/file_fixtures.rb +34 -0
  206. data/lib/active_support/testing/isolation.rb +53 -95
  207. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  208. data/lib/active_support/testing/setup_and_teardown.rb +21 -82
  209. data/lib/active_support/testing/stream.rb +42 -0
  210. data/lib/active_support/testing/tagged_logging.rb +25 -0
  211. data/lib/active_support/testing/time_helpers.rb +134 -0
  212. data/lib/active_support/time.rb +6 -23
  213. data/lib/active_support/time_with_zone.rb +239 -92
  214. data/lib/active_support/values/time_zone.rb +236 -160
  215. data/lib/active_support/values/unicode_tables.dat +0 -0
  216. data/lib/active_support/version.rb +5 -7
  217. data/lib/active_support/xml_mini/jdom.rb +19 -13
  218. data/lib/active_support/xml_mini/libxml.rb +3 -4
  219. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  220. data/lib/active_support/xml_mini/nokogiri.rb +3 -4
  221. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  222. data/lib/active_support/xml_mini/rexml.rb +8 -10
  223. data/lib/active_support/xml_mini.rb +66 -34
  224. data/lib/active_support.rb +40 -23
  225. metadata +185 -134
  226. data/CHANGELOG +0 -1534
  227. data/lib/active_support/base64.rb +0 -42
  228. data/lib/active_support/basic_object.rb +0 -21
  229. data/lib/active_support/buffered_logger.rb +0 -137
  230. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  231. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  232. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  233. data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
  234. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
  235. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  236. data/lib/active_support/core_ext/date/freeze.rb +0 -31
  237. data/lib/active_support/core_ext/date_time/zones.rb +0 -21
  238. data/lib/active_support/core_ext/exception.rb +0 -3
  239. data/lib/active_support/core_ext/file/path.rb +0 -5
  240. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  241. data/lib/active_support/core_ext/float.rb +0 -1
  242. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
  243. data/lib/active_support/core_ext/hash/diff.rb +0 -13
  244. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  245. data/lib/active_support/core_ext/logger.rb +0 -81
  246. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  247. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  248. data/lib/active_support/core_ext/module/synchronization.rb +0 -43
  249. data/lib/active_support/core_ext/object/to_json.rb +0 -19
  250. data/lib/active_support/core_ext/proc.rb +0 -14
  251. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  252. data/lib/active_support/core_ext/process.rb +0 -1
  253. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  254. data/lib/active_support/core_ext/range/cover.rb +0 -3
  255. data/lib/active_support/core_ext/rexml.rb +0 -46
  256. data/lib/active_support/core_ext/string/encoding.rb +0 -11
  257. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  258. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  259. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  260. data/lib/active_support/file_watcher.rb +0 -36
  261. data/lib/active_support/json/variable.rb +0 -9
  262. data/lib/active_support/memoizable.rb +0 -105
  263. data/lib/active_support/multibyte/exceptions.rb +0 -8
  264. data/lib/active_support/multibyte/utils.rb +0 -60
  265. data/lib/active_support/ruby/shim.rb +0 -22
  266. data/lib/active_support/secure_random.rb +0 -6
  267. data/lib/active_support/testing/mochaing.rb +0 -7
  268. data/lib/active_support/testing/pending.rb +0 -52
  269. data/lib/active_support/testing/performance/jruby.rb +0 -115
  270. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  271. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  272. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  273. data/lib/active_support/testing/performance/ruby.rb +0 -152
  274. data/lib/active_support/testing/performance.rb +0 -317
  275. data/lib/active_support/time/autoload.rb +0 -5
  276. data/lib/active_support/whiny_nil.rb +0 -60
@@ -0,0 +1,205 @@
1
+ # Hack to load json gem first so we can overwrite its to_json.
2
+ require 'json'
3
+ require 'bigdecimal'
4
+ require 'active_support/core_ext/big_decimal/conversions' # for #to_s
5
+ require 'active_support/core_ext/hash/except'
6
+ require 'active_support/core_ext/hash/slice'
7
+ require 'active_support/core_ext/object/instance_variables'
8
+ require 'time'
9
+ require 'active_support/core_ext/time/conversions'
10
+ require 'active_support/core_ext/date_time/conversions'
11
+ require 'active_support/core_ext/date/conversions'
12
+
13
+ # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
14
+ # their default behavior. That said, we need to define the basic to_json method in all of them,
15
+ # otherwise they will always use to_json gem implementation, which is backwards incompatible in
16
+ # several cases (for instance, the JSON implementation for Hash does not work) with inheritance
17
+ # and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
18
+ #
19
+ # On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
20
+ # JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
21
+ # passes a ::JSON::State object as the only argument to to_json, we can detect that and forward the
22
+ # calls to the original to_json method.
23
+ #
24
+ # It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
25
+ # bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
26
+ # ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
27
+ # should give exactly the same results with or without active support.
28
+
29
+ module ActiveSupport
30
+ module ToJsonWithActiveSupportEncoder # :nodoc:
31
+ def to_json(options = nil)
32
+ if options.is_a?(::JSON::State)
33
+ # Called from JSON.{generate,dump}, forward it to JSON gem's to_json
34
+ super(options)
35
+ else
36
+ # to_json is being invoked directly, use ActiveSupport's encoder
37
+ ActiveSupport::JSON.encode(self, options)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass, Enumerable].reverse_each do |klass|
44
+ klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
45
+ end
46
+
47
+ class Object
48
+ def as_json(options = nil) #:nodoc:
49
+ if respond_to?(:to_hash)
50
+ to_hash.as_json(options)
51
+ else
52
+ instance_values.as_json(options)
53
+ end
54
+ end
55
+ end
56
+
57
+ class Struct #:nodoc:
58
+ def as_json(options = nil)
59
+ Hash[members.zip(values)].as_json(options)
60
+ end
61
+ end
62
+
63
+ class TrueClass
64
+ def as_json(options = nil) #:nodoc:
65
+ self
66
+ end
67
+ end
68
+
69
+ class FalseClass
70
+ def as_json(options = nil) #:nodoc:
71
+ self
72
+ end
73
+ end
74
+
75
+ class NilClass
76
+ def as_json(options = nil) #:nodoc:
77
+ self
78
+ end
79
+ end
80
+
81
+ class String
82
+ def as_json(options = nil) #:nodoc:
83
+ self
84
+ end
85
+ end
86
+
87
+ class Symbol
88
+ def as_json(options = nil) #:nodoc:
89
+ to_s
90
+ end
91
+ end
92
+
93
+ class Numeric
94
+ def as_json(options = nil) #:nodoc:
95
+ self
96
+ end
97
+ end
98
+
99
+ class Float
100
+ # Encoding Infinity or NaN to JSON should return "null". The default returns
101
+ # "Infinity" or "NaN" which are not valid JSON.
102
+ def as_json(options = nil) #:nodoc:
103
+ finite? ? self : nil
104
+ end
105
+ end
106
+
107
+ class BigDecimal
108
+ # A BigDecimal would be naturally represented as a JSON number. Most libraries,
109
+ # however, parse non-integer JSON numbers directly as floats. Clients using
110
+ # those libraries would get in general a wrong number and no way to recover
111
+ # other than manually inspecting the string with the JSON code itself.
112
+ #
113
+ # That's why a JSON string is returned. The JSON literal is not numeric, but
114
+ # if the other end knows by contract that the data is supposed to be a
115
+ # BigDecimal, it still has the chance to post-process the string and get the
116
+ # real value.
117
+ def as_json(options = nil) #:nodoc:
118
+ finite? ? to_s : nil
119
+ end
120
+ end
121
+
122
+ class Regexp
123
+ def as_json(options = nil) #:nodoc:
124
+ to_s
125
+ end
126
+ end
127
+
128
+ module Enumerable
129
+ def as_json(options = nil) #:nodoc:
130
+ to_a.as_json(options)
131
+ end
132
+ end
133
+
134
+ class Range
135
+ def as_json(options = nil) #:nodoc:
136
+ to_s
137
+ end
138
+ end
139
+
140
+ class Array
141
+ def as_json(options = nil) #:nodoc:
142
+ map { |v| options ? v.as_json(options.dup) : v.as_json }
143
+ end
144
+ end
145
+
146
+ class Hash
147
+ def as_json(options = nil) #:nodoc:
148
+ # create a subset of the hash by applying :only or :except
149
+ subset = if options
150
+ if attrs = options[:only]
151
+ slice(*Array(attrs))
152
+ elsif attrs = options[:except]
153
+ except(*Array(attrs))
154
+ else
155
+ self
156
+ end
157
+ else
158
+ self
159
+ end
160
+
161
+ Hash[subset.map { |k, v| [k.to_s, options ? v.as_json(options.dup) : v.as_json] }]
162
+ end
163
+ end
164
+
165
+ class Time
166
+ def as_json(options = nil) #:nodoc:
167
+ if ActiveSupport::JSON::Encoding.use_standard_json_time_format
168
+ xmlschema(ActiveSupport::JSON::Encoding.time_precision)
169
+ else
170
+ %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
171
+ end
172
+ end
173
+ end
174
+
175
+ class Date
176
+ def as_json(options = nil) #:nodoc:
177
+ if ActiveSupport::JSON::Encoding.use_standard_json_time_format
178
+ strftime("%Y-%m-%d")
179
+ else
180
+ strftime("%Y/%m/%d")
181
+ end
182
+ end
183
+ end
184
+
185
+ class DateTime
186
+ def as_json(options = nil) #:nodoc:
187
+ if ActiveSupport::JSON::Encoding.use_standard_json_time_format
188
+ xmlschema(ActiveSupport::JSON::Encoding.time_precision)
189
+ else
190
+ strftime('%Y/%m/%d %H:%M:%S %z')
191
+ end
192
+ end
193
+ end
194
+
195
+ class Process::Status #:nodoc:
196
+ def as_json(options = nil)
197
+ { :exitstatus => exitstatus, :pid => pid }
198
+ end
199
+ end
200
+
201
+ class Exception
202
+ def as_json(options = nil)
203
+ to_s
204
+ end
205
+ end
@@ -1,55 +1 @@
1
- class Object
2
- # Alias of <tt>to_s</tt>.
3
- def to_param
4
- to_s
5
- end
6
- end
7
-
8
- class NilClass
9
- def to_param
10
- self
11
- end
12
- end
13
-
14
- class TrueClass
15
- def to_param
16
- self
17
- end
18
- end
19
-
20
- class FalseClass
21
- def to_param
22
- self
23
- end
24
- end
25
-
26
- class Array
27
- # Calls <tt>to_param</tt> on all its elements and joins the result with
28
- # slashes. This is used by <tt>url_for</tt> in Action Pack.
29
- def to_param
30
- collect { |e| e.to_param }.join '/'
31
- end
32
- end
33
-
34
- class Hash
35
- # Returns a string representation of the receiver suitable for use as a URL
36
- # query string:
37
- #
38
- # {:name => 'David', :nationality => 'Danish'}.to_param
39
- # # => "name=David&nationality=Danish"
40
- #
41
- # An optional namespace can be passed to enclose the param names:
42
- #
43
- # {:name => 'David', :nationality => 'Danish'}.to_param('user')
44
- # # => "user[name]=David&user[nationality]=Danish"
45
- #
46
- # The string pairs "key=value" that conform the query string
47
- # are sorted lexicographically in ascending order.
48
- #
49
- # This method is also aliased as +to_query+.
50
- def to_param(namespace = nil)
51
- collect do |key, value|
52
- value.to_query(namespace ? "#{namespace}[#{key}]" : key)
53
- end.sort * '&'
54
- end
55
- end
1
+ require 'active_support/core_ext/object/to_query'
@@ -1,27 +1,84 @@
1
- require 'active_support/core_ext/object/to_param'
1
+ require 'cgi'
2
2
 
3
3
  class Object
4
- # Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the
5
- # param name.
6
- #
7
- # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
4
+ # Alias of <tt>to_s</tt>.
5
+ def to_param
6
+ to_s
7
+ end
8
+
9
+ # Converts an object into a string suitable for use as a URL query string,
10
+ # using the given <tt>key</tt> as the param name.
8
11
  def to_query(key)
9
- require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
10
- "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
12
+ "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
13
+ end
14
+ end
15
+
16
+ class NilClass
17
+ # Returns +self+.
18
+ def to_param
19
+ self
20
+ end
21
+ end
22
+
23
+ class TrueClass
24
+ # Returns +self+.
25
+ def to_param
26
+ self
27
+ end
28
+ end
29
+
30
+ class FalseClass
31
+ # Returns +self+.
32
+ def to_param
33
+ self
11
34
  end
12
35
  end
13
36
 
14
37
  class Array
38
+ # Calls <tt>to_param</tt> on all its elements and joins the result with
39
+ # slashes. This is used by <tt>url_for</tt> in Action Pack.
40
+ def to_param
41
+ collect(&:to_param).join '/'
42
+ end
43
+
15
44
  # Converts an array into a string suitable for use as a URL query string,
16
45
  # using the given +key+ as the param name.
17
46
  #
18
47
  # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
19
48
  def to_query(key)
20
49
  prefix = "#{key}[]"
21
- collect { |value| value.to_query(prefix) }.join '&'
50
+
51
+ if empty?
52
+ nil.to_query(prefix)
53
+ else
54
+ collect { |value| value.to_query(prefix) }.join '&'
55
+ end
22
56
  end
23
57
  end
24
58
 
25
59
  class Hash
26
- alias_method :to_query, :to_param
60
+ # Returns a string representation of the receiver suitable for use as a URL
61
+ # query string:
62
+ #
63
+ # {name: 'David', nationality: 'Danish'}.to_query
64
+ # # => "name=David&nationality=Danish"
65
+ #
66
+ # An optional namespace can be passed to enclose key names:
67
+ #
68
+ # {name: 'David', nationality: 'Danish'}.to_query('user')
69
+ # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
70
+ #
71
+ # The string pairs "key=value" that conform the query string
72
+ # are sorted lexicographically in ascending order.
73
+ #
74
+ # This method is also aliased as +to_param+.
75
+ def to_query(namespace = nil)
76
+ collect do |key, value|
77
+ unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
78
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
79
+ end
80
+ end.compact.sort! * '&'
81
+ end
82
+
83
+ alias_method :to_param, :to_query
27
84
  end
@@ -1,55 +1,146 @@
1
+ require 'delegate'
2
+
3
+ module ActiveSupport
4
+ module Tryable #:nodoc:
5
+ def try(*a, &b)
6
+ try!(*a, &b) if a.empty? || respond_to?(a.first)
7
+ end
8
+
9
+ def try!(*a, &b)
10
+ if a.empty? && block_given?
11
+ if b.arity == 0
12
+ instance_eval(&b)
13
+ else
14
+ yield self
15
+ end
16
+ else
17
+ public_send(*a, &b)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
1
23
  class Object
2
- # Invokes the method identified by the symbol +method+, passing it any arguments
3
- # and/or the block specified, just like the regular Ruby <tt>Object#send</tt> does.
4
- #
5
- # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
6
- # and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
24
+ include ActiveSupport::Tryable
25
+
26
+ ##
27
+ # :method: try
7
28
  #
8
- # If try is called without a method to call, it will yield any given block with the object.
29
+ # :call-seq:
30
+ # try(*a, &b)
9
31
  #
10
- # ==== Examples
32
+ # Invokes the public method whose name goes as first argument just like
33
+ # +public_send+ does, except that if the receiver does not respond to it the
34
+ # call returns +nil+ rather than raising an exception.
11
35
  #
12
- # Without +try+
13
- # @person && @person.name
14
- # or
15
- # @person ? @person.name : nil
36
+ # This method is defined to be able to write
16
37
  #
17
- # With +try+
18
38
  # @person.try(:name)
19
39
  #
20
- # +try+ also accepts arguments and/or a block, for the method it is trying
21
- # Person.try(:find, 1)
22
- # @people.try(:collect) {|p| p.name}
23
- #
24
- # Without a method argument try will yield to the block unless the receiver is nil.
25
- # @person.try { |p| "#{p.first_name} #{p.last_name}" }
26
- #--
27
- # +try+ behaves like +Object#send+, unless called on +NilClass+.
28
- def try(*a, &b)
29
- if a.empty? && block_given?
30
- yield self
31
- elsif !a.empty? && !respond_to?(a.first)
32
- nil
33
- else
34
- __send__(*a, &b)
35
- end
36
- end
40
+ # instead of
41
+ #
42
+ # @person.name if @person
43
+ #
44
+ # +try+ calls can be chained:
45
+ #
46
+ # @person.try(:spouse).try(:name)
47
+ #
48
+ # instead of
49
+ #
50
+ # @person.spouse.name if @person && @person.spouse
51
+ #
52
+ # +try+ will also return +nil+ if the receiver does not respond to the method:
53
+ #
54
+ # @person.try(:non_existing_method) # => nil
55
+ #
56
+ # instead of
57
+ #
58
+ # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
59
+ #
60
+ # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
61
+ # to the method:
62
+ #
63
+ # nil.try(:to_i) # => nil, rather than 0
64
+ #
65
+ # Arguments and blocks are forwarded to the method if invoked:
66
+ #
67
+ # @posts.try(:each_slice, 2) do |a, b|
68
+ # ...
69
+ # end
70
+ #
71
+ # The number of arguments in the signature must match. If the object responds
72
+ # to the method the call is attempted and +ArgumentError+ is still raised
73
+ # in case of argument mismatch.
74
+ #
75
+ # If +try+ is called without arguments it yields the receiver to a given
76
+ # block unless it is +nil+:
77
+ #
78
+ # @person.try do |p|
79
+ # ...
80
+ # end
81
+ #
82
+ # You can also call try with a block without accepting an argument, and the block
83
+ # will be instance_eval'ed instead:
84
+ #
85
+ # @person.try { upcase.truncate(50) }
86
+ #
87
+ # Please also note that +try+ is defined on +Object+. Therefore, it won't work
88
+ # with instances of classes that do not have +Object+ among their ancestors,
89
+ # like direct subclasses of +BasicObject+.
90
+
91
+ ##
92
+ # :method: try!
93
+ #
94
+ # :call-seq:
95
+ # try!(*a, &b)
96
+ #
97
+ # Same as #try, but raises a +NoMethodError+ exception if the receiver is
98
+ # not +nil+ and does not implement the tried method.
99
+ #
100
+ # "a".try!(:upcase) # => "A"
101
+ # nil.try!(:upcase) # => nil
102
+ # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
103
+ end
104
+
105
+ class Delegator
106
+ include ActiveSupport::Tryable
107
+
108
+ ##
109
+ # :method: try
110
+ #
111
+ # :call-seq:
112
+ # try(a*, &b)
113
+ #
114
+ # See Object#try
115
+
116
+ ##
117
+ # :method: try!
118
+ #
119
+ # :call-seq:
120
+ # try!(a*, &b)
121
+ #
122
+ # See Object#try!
37
123
  end
38
124
 
39
125
  class NilClass
40
126
  # Calling +try+ on +nil+ always returns +nil+.
41
- # It becomes specially helpful when navigating through associations that may return +nil+.
42
- #
43
- # === Examples
127
+ # It becomes especially helpful when navigating through associations that may return +nil+.
44
128
  #
45
129
  # nil.try(:name) # => nil
46
130
  #
47
131
  # Without +try+
48
- # @person && !@person.children.blank? && @person.children.first.name
132
+ # @person && @person.children.any? && @person.children.first.name
49
133
  #
50
134
  # With +try+
51
135
  # @person.try(:children).try(:first).try(:name)
52
136
  def try(*args)
53
137
  nil
54
138
  end
139
+
140
+ # Calling +try!+ on +nil+ always returns +nil+.
141
+ #
142
+ # nil.try!(:name) # => nil
143
+ def try!(*args)
144
+ nil
145
+ end
55
146
  end
@@ -7,19 +7,19 @@ class Object
7
7
  # provided. Each method called on the block variable must take an options
8
8
  # hash as its final argument.
9
9
  #
10
- # Without <tt>with_options></tt>, this code contains duplication:
10
+ # Without <tt>with_options</tt>, this code contains duplication:
11
11
  #
12
12
  # class Account < ActiveRecord::Base
13
- # has_many :customers, :dependent => :destroy
14
- # has_many :products, :dependent => :destroy
15
- # has_many :invoices, :dependent => :destroy
16
- # has_many :expenses, :dependent => :destroy
13
+ # has_many :customers, dependent: :destroy
14
+ # has_many :products, dependent: :destroy
15
+ # has_many :invoices, dependent: :destroy
16
+ # has_many :expenses, dependent: :destroy
17
17
  # end
18
18
  #
19
19
  # Using <tt>with_options</tt>, we can remove the duplication:
20
20
  #
21
21
  # class Account < ActiveRecord::Base
22
- # with_options :dependent => :destroy do |assoc|
22
+ # with_options dependent: :destroy do |assoc|
23
23
  # assoc.has_many :customers
24
24
  # assoc.has_many :products
25
25
  # assoc.has_many :invoices
@@ -29,15 +29,41 @@ class Object
29
29
  #
30
30
  # It can also be used with an explicit receiver:
31
31
  #
32
- # I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
32
+ # I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
33
33
  # subject i18n.t :subject
34
- # body i18n.t :body, :user_name => user.name
34
+ # body i18n.t :body, user_name: user.name
35
+ # end
36
+ #
37
+ # When you don't pass an explicit receiver, it executes the whole block
38
+ # in merging options context:
39
+ #
40
+ # class Account < ActiveRecord::Base
41
+ # with_options dependent: :destroy do
42
+ # has_many :customers
43
+ # has_many :products
44
+ # has_many :invoices
45
+ # has_many :expenses
46
+ # end
35
47
  # end
36
48
  #
37
49
  # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
38
- # Each nesting level will merge inherited defaults in addition to their own.
39
50
  #
40
- def with_options(options)
41
- yield ActiveSupport::OptionMerger.new(self, options)
51
+ # NOTE: Each nesting level will merge inherited defaults in addition to their own.
52
+ #
53
+ # class Post < ActiveRecord::Base
54
+ # with_options if: :persisted?, length: { minimum: 50 } do
55
+ # validates :content, if: -> { content.present? }
56
+ # end
57
+ # end
58
+ #
59
+ # The code is equivalent to:
60
+ #
61
+ # validates :content, length: { minimum: 50 }, if: -> { content.present? }
62
+ #
63
+ # Hence the inherited default for `if` key is ignored.
64
+ #
65
+ def with_options(options, &block)
66
+ option_merger = ActiveSupport::OptionMerger.new(self, options)
67
+ block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
42
68
  end
43
69
  end
@@ -1,13 +1,14 @@
1
1
  require 'active_support/core_ext/object/acts_like'
2
2
  require 'active_support/core_ext/object/blank'
3
3
  require 'active_support/core_ext/object/duplicable'
4
+ require 'active_support/core_ext/object/deep_dup'
4
5
  require 'active_support/core_ext/object/try'
5
6
  require 'active_support/core_ext/object/inclusion'
6
7
 
7
8
  require 'active_support/core_ext/object/conversions'
8
9
  require 'active_support/core_ext/object/instance_variables'
9
10
 
10
- require 'active_support/core_ext/object/to_json'
11
+ require 'active_support/core_ext/object/json'
11
12
  require 'active_support/core_ext/object/to_param'
12
13
  require 'active_support/core_ext/object/to_query'
13
14
  require 'active_support/core_ext/object/with_options'
@@ -1,21 +1,31 @@
1
- class Range
1
+ module ActiveSupport::RangeWithFormat
2
2
  RANGE_FORMATS = {
3
3
  :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
4
4
  }
5
5
 
6
- # Gives a human readable format of the range.
6
+ # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
7
7
  #
8
- # ==== Example
8
+ # range = (1..100) # => 1..100
9
9
  #
10
- # [1..100].to_formatted_s # => "1..100"
11
- def to_formatted_s(format = :default)
10
+ # range.to_s # => "1..100"
11
+ # range.to_s(:db) # => "BETWEEN '1' AND '100'"
12
+ #
13
+ # == Adding your own range formats to to_s
14
+ # You can add your own formats to the Range::RANGE_FORMATS hash.
15
+ # Use the format name as the hash key and a Proc instance.
16
+ #
17
+ # # config/initializers/range_formats.rb
18
+ # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
19
+ def to_s(format = :default)
12
20
  if formatter = RANGE_FORMATS[format]
13
21
  formatter.call(first, last)
14
22
  else
15
- to_default_s
23
+ super()
16
24
  end
17
25
  end
18
26
 
19
27
  alias_method :to_default_s, :to_s
20
- alias_method :to_s, :to_formatted_s
28
+ alias_method :to_formatted_s, :to_s
21
29
  end
30
+
31
+ Range.prepend(ActiveSupport::RangeWithFormat)
@@ -0,0 +1,21 @@
1
+ module ActiveSupport
2
+ module EachTimeWithZone #:nodoc:
3
+ def each(&block)
4
+ ensure_iteration_allowed
5
+ super
6
+ end
7
+
8
+ def step(n = 1, &block)
9
+ ensure_iteration_allowed
10
+ super
11
+ end
12
+
13
+ private
14
+
15
+ def ensure_iteration_allowed
16
+ raise TypeError, "can't iterate from #{first.class}" if first.is_a?(Time)
17
+ end
18
+ end
19
+ end
20
+
21
+ Range.prepend(ActiveSupport::EachTimeWithZone)