activesupport 1.4.4 → 2.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 (126) hide show
  1. data/CHANGELOG +263 -7
  2. data/lib/active_support.rb +9 -4
  3. data/lib/active_support/basic_object.rb +5 -0
  4. data/lib/active_support/buffered_logger.rb +107 -0
  5. data/lib/active_support/clean_logger.rb +94 -5
  6. data/lib/active_support/core_ext.rb +4 -1
  7. data/lib/active_support/core_ext/array.rb +8 -2
  8. data/lib/active_support/core_ext/array/access.rb +28 -0
  9. data/lib/active_support/core_ext/array/conversions.rb +28 -15
  10. data/lib/active_support/core_ext/array/extract_options.rb +19 -0
  11. data/lib/active_support/core_ext/array/grouping.rb +20 -7
  12. data/lib/active_support/core_ext/array/random_access.rb +12 -0
  13. data/lib/active_support/core_ext/bigdecimal.rb +1 -2
  14. data/lib/active_support/core_ext/bigdecimal/{formatting.rb → conversions.rb} +1 -2
  15. data/lib/active_support/core_ext/blank.rb +2 -8
  16. data/lib/active_support/core_ext/cgi.rb +2 -2
  17. data/lib/active_support/core_ext/class.rb +4 -3
  18. data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
  19. data/lib/active_support/core_ext/class/delegating_attributes.rb +40 -0
  20. data/lib/active_support/core_ext/class/inheritable_attributes.rb +3 -3
  21. data/lib/active_support/core_ext/class/removal.rb +2 -2
  22. data/lib/active_support/core_ext/date.rb +5 -1
  23. data/lib/active_support/core_ext/date/behavior.rb +13 -0
  24. data/lib/active_support/core_ext/date/calculations.rb +188 -0
  25. data/lib/active_support/core_ext/date/conversions.rb +69 -13
  26. data/lib/active_support/core_ext/date_time.rb +10 -0
  27. data/lib/active_support/core_ext/date_time/calculations.rb +77 -0
  28. data/lib/active_support/core_ext/date_time/conversions.rb +54 -0
  29. data/lib/active_support/core_ext/duplicable.rb +37 -0
  30. data/lib/active_support/core_ext/enumerable.rb +1 -0
  31. data/lib/active_support/core_ext/exception.rb +2 -2
  32. data/lib/active_support/core_ext/file.rb +21 -0
  33. data/lib/active_support/core_ext/float.rb +5 -0
  34. data/lib/active_support/core_ext/float/rounding.rb +24 -0
  35. data/lib/active_support/core_ext/hash.rb +5 -5
  36. data/lib/active_support/core_ext/hash/conversions.rb +86 -34
  37. data/lib/active_support/core_ext/hash/diff.rb +8 -0
  38. data/lib/active_support/core_ext/hash/except.rb +24 -0
  39. data/lib/active_support/core_ext/hash/indifferent_access.rb +15 -2
  40. data/lib/active_support/core_ext/hash/keys.rb +10 -3
  41. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -2
  42. data/lib/active_support/core_ext/hash/slice.rb +28 -0
  43. data/lib/active_support/core_ext/integer.rb +2 -2
  44. data/lib/active_support/core_ext/kernel.rb +5 -4
  45. data/lib/active_support/core_ext/kernel/debugger.rb +13 -0
  46. data/lib/active_support/core_ext/module.rb +8 -7
  47. data/lib/active_support/core_ext/module/aliasing.rb +17 -5
  48. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  49. data/lib/active_support/core_ext/module/attribute_accessors.rb +1 -1
  50. data/lib/active_support/core_ext/module/delegation.rb +21 -0
  51. data/lib/active_support/core_ext/name_error.rb +2 -2
  52. data/lib/active_support/core_ext/numeric.rb +2 -2
  53. data/lib/active_support/core_ext/numeric/time.rb +30 -11
  54. data/lib/active_support/core_ext/object.rb +3 -2
  55. data/lib/active_support/core_ext/object/extending.rb +40 -29
  56. data/lib/active_support/core_ext/object/instance_variables.rb +22 -0
  57. data/lib/active_support/core_ext/object/misc.rb +29 -4
  58. data/lib/active_support/core_ext/pathname.rb +1 -1
  59. data/lib/active_support/core_ext/range.rb +7 -1
  60. data/lib/active_support/core_ext/range/blockless_step.rb +22 -0
  61. data/lib/active_support/core_ext/range/conversions.rb +8 -6
  62. data/lib/active_support/core_ext/range/include_range.rb +22 -0
  63. data/lib/active_support/core_ext/range/overlaps.rb +12 -0
  64. data/lib/active_support/core_ext/string.rb +10 -7
  65. data/lib/active_support/core_ext/string/conversions.rb +5 -1
  66. data/lib/active_support/core_ext/string/unicode.rb +2 -2
  67. data/lib/active_support/core_ext/string/xchar.rb +11 -0
  68. data/lib/active_support/core_ext/symbol.rb +12 -10
  69. data/lib/active_support/core_ext/test.rb +1 -0
  70. data/lib/active_support/core_ext/test/unit/assertions.rb +62 -0
  71. data/lib/active_support/core_ext/time.rb +4 -2
  72. data/lib/active_support/core_ext/time/behavior.rb +13 -0
  73. data/lib/active_support/core_ext/time/calculations.rb +87 -54
  74. data/lib/active_support/core_ext/time/conversions.rb +71 -10
  75. data/lib/active_support/dependencies.rb +25 -24
  76. data/lib/active_support/deprecation.rb +4 -2
  77. data/lib/active_support/duration.rb +86 -0
  78. data/lib/active_support/inflections.rb +2 -1
  79. data/lib/active_support/inflector.rb +13 -6
  80. data/lib/active_support/json.rb +22 -39
  81. data/lib/active_support/json/decoding.rb +60 -0
  82. data/lib/active_support/json/encoders/date.rb +5 -0
  83. data/lib/active_support/json/encoders/date_time.rb +5 -0
  84. data/lib/active_support/json/encoders/enumerable.rb +12 -0
  85. data/lib/active_support/json/encoders/false_class.rb +5 -0
  86. data/lib/active_support/json/encoders/hash.rb +50 -0
  87. data/lib/active_support/json/encoders/nil_class.rb +5 -0
  88. data/lib/active_support/json/encoders/numeric.rb +5 -0
  89. data/lib/active_support/json/encoders/object.rb +6 -0
  90. data/lib/active_support/json/encoders/regexp.rb +5 -0
  91. data/lib/active_support/json/encoders/string.rb +30 -0
  92. data/lib/active_support/json/encoders/symbol.rb +5 -0
  93. data/lib/active_support/json/encoders/time.rb +5 -0
  94. data/lib/active_support/json/encoders/true_class.rb +5 -0
  95. data/lib/active_support/json/encoding.rb +38 -0
  96. data/lib/active_support/json/variable.rb +10 -0
  97. data/lib/active_support/multibyte.rb +7 -5
  98. data/lib/active_support/multibyte/chars.rb +6 -0
  99. data/lib/active_support/multibyte/handlers/utf8_handler.rb +115 -5
  100. data/lib/active_support/option_merger.rb +7 -7
  101. data/lib/active_support/ordered_options.rb +22 -17
  102. data/lib/active_support/test_case.rb +5 -0
  103. data/lib/active_support/testing.rb +1 -0
  104. data/lib/active_support/testing/default.rb +12 -0
  105. data/lib/active_support/values/time_zone.rb +3 -3
  106. data/lib/active_support/vendor.rb +14 -0
  107. data/lib/active_support/vendor/builder-2.1.2/blankslate.rb +113 -0
  108. data/lib/active_support/vendor/{builder.rb → builder-2.1.2/builder.rb} +0 -0
  109. data/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +20 -0
  110. data/lib/active_support/vendor/builder-2.1.2/builder/css.rb +250 -0
  111. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xchar.rb +11 -8
  112. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlbase.rb +38 -44
  113. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlevents.rb +1 -1
  114. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlmarkup.rb +40 -39
  115. data/lib/active_support/vendor/{xml_simple.rb → xml-simple-1.0.11/xmlsimple.rb} +3 -3
  116. data/lib/active_support/version.rb +3 -3
  117. data/lib/active_support/whiny_nil.rb +12 -12
  118. data/lib/activesupport.rb +1 -0
  119. metadata +69 -17
  120. data/lib/active_support/binding_of_caller.rb +0 -84
  121. data/lib/active_support/breakpoint.rb +0 -528
  122. data/lib/active_support/caching_tools.rb +0 -62
  123. data/lib/active_support/json/encoders.rb +0 -25
  124. data/lib/active_support/json/encoders/core.rb +0 -70
  125. data/lib/active_support/reloadable.rb +0 -60
  126. data/lib/active_support/vendor/builder/blankslate.rb +0 -63
@@ -4,29 +4,90 @@ module ActiveSupport #:nodoc:
4
4
  # Getting times in different convenient string representations and other objects
5
5
  module Conversions
6
6
  DATE_FORMATS = {
7
- :db => "%Y-%m-%d %H:%M:%S",
8
- :short => "%d %b %H:%M",
9
- :long => "%B %d, %Y %H:%M",
10
- :rfc822 => "%a, %d %b %Y %H:%M:%S %z"
7
+ :db => "%Y-%m-%d %H:%M:%S",
8
+ :time => "%H:%M",
9
+ :short => "%d %b %H:%M",
10
+ :long => "%B %d, %Y %H:%M",
11
+ :long_ordinal => lambda { |time| time.strftime("%B #{time.day.ordinalize}, %Y %H:%M") },
12
+ :rfc822 => "%a, %d %b %Y %H:%M:%S %z"
11
13
  }
12
14
 
13
- def self.included(klass)
14
- klass.send(:alias_method, :to_default_s, :to_s)
15
- klass.send(:alias_method, :to_s, :to_formatted_s)
15
+ def self.included(base)
16
+ base.class_eval do
17
+ alias_method :to_default_s, :to_s
18
+ alias_method :to_s, :to_formatted_s
19
+ end
16
20
  end
17
-
21
+
22
+ # Convert to a formatted string - see DATE_FORMATS for predefined formats.
23
+ # You can also add your own formats to the DATE_FORMATS constant and use them with this method.
24
+ #
25
+ # This method is also aliased as <tt>to_s</tt>.
26
+ #
27
+ # ==== Examples:
28
+ # time = Time.now # => Thu Jan 18 06:10:17 CST 2007
29
+ #
30
+ # time.to_formatted_s(:time) # => "06:10:17"
31
+ # time.to_s(:time) # => "06:10:17"
32
+ #
33
+ # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
34
+ # time.to_formatted_s(:short) # => "18 Jan 06:10"
35
+ # time.to_formatted_s(:long) # => "January 18, 2007 06:10"
36
+ # time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
37
+ # time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
18
38
  def to_formatted_s(format = :default)
19
- DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s
39
+ if formatter = DATE_FORMATS[format]
40
+ if formatter.respond_to?(:call)
41
+ formatter.call(self).to_s
42
+ else
43
+ strftime(formatter)
44
+ end
45
+ else
46
+ to_default_s
47
+ end
20
48
  end
21
49
 
50
+ # Convert a Time object to a Date, dropping hour, minute, and second precision.
51
+ #
52
+ # ==== Examples
53
+ # my_time = Time.now
54
+ # # => Mon Nov 12 22:59:51 -0500 2007
55
+ #
56
+ # my_time.to_date
57
+ # #=> Mon, 12 Nov 2007
58
+ #
59
+ # your_time = Time.parse("1/13/2009 1:13:03 P.M.")
60
+ # # => Tue Jan 13 13:13:03 -0500 2009
61
+ #
62
+ # your_time.to_date
63
+ # # => Tue, 13 Jan 2009
22
64
  def to_date
23
65
  ::Date.new(year, month, day)
24
66
  end
25
67
 
26
- # To be able to keep Dates and Times interchangeable on conversions
68
+ # A method to keep Time, Date and DateTime instances interchangeable on conversions.
69
+ # In this case, it simply returns +self+.
27
70
  def to_time
28
71
  self
29
72
  end
73
+
74
+ # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
75
+ #
76
+ # ==== Examples
77
+ # my_time = Time.now
78
+ # # => Mon Nov 12 23:04:21 -0500 2007
79
+ #
80
+ # my_time.to_datetime
81
+ # # => Mon, 12 Nov 2007 23:04:21 -0500
82
+ #
83
+ # your_time = Time.parse("1/13/2009 1:13:03 P.M.")
84
+ # # => Tue Jan 13 13:13:03 -0500 2009
85
+ #
86
+ # your_time.to_datetime
87
+ # # => Tue, 13 Jan 2009 13:13:03 -0500
88
+ def to_datetime
89
+ ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
90
+ end
30
91
  end
31
92
  end
32
93
  end
@@ -1,7 +1,7 @@
1
1
  require 'set'
2
- require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors'
3
- require File.dirname(__FILE__) + '/core_ext/load_error'
4
- require File.dirname(__FILE__) + '/core_ext/kernel'
2
+ require 'active_support/core_ext/module/attribute_accessors'
3
+ require 'active_support/core_ext/load_error'
4
+ require 'active_support/core_ext/kernel'
5
5
 
6
6
  module Dependencies #:nodoc:
7
7
  extend self
@@ -114,7 +114,7 @@ module Dependencies #:nodoc:
114
114
  raise NameError, "#{path.inspect} is not a valid constant name!" unless
115
115
  /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ path
116
116
 
117
- names = path.split('::')
117
+ names = path.to_s.split('::')
118
118
  names.shift if names.first.empty?
119
119
 
120
120
  # We can't use defined? because it will invoke const_missing for the parent
@@ -229,10 +229,10 @@ module Dependencies #:nodoc:
229
229
  from_mod = Object
230
230
  end
231
231
  end
232
-
232
+
233
233
  # If we have an anonymous module, all we can do is attempt to load from Object.
234
- from_mod = Object if from_mod.name.empty?
235
-
234
+ from_mod = Object if from_mod.name.blank?
235
+
236
236
  unless qualified_const_defined?(from_mod.name) && from_mod.name.constantize.object_id == from_mod.object_id
237
237
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
238
238
  end
@@ -383,7 +383,7 @@ module Dependencies #:nodoc:
383
383
 
384
384
  class LoadingModule #:nodoc:
385
385
  # Old style environment.rb referenced this method directly. Please note, it doesn't
386
- # actualy *do* anything any more.
386
+ # actually *do* anything any more.
387
387
  def self.root(*args)
388
388
  if defined?(RAILS_DEFAULT_LOGGER)
389
389
  RAILS_DEFAULT_LOGGER.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
@@ -392,11 +392,9 @@ module Dependencies #:nodoc:
392
392
  end
393
393
  end
394
394
 
395
- protected
396
-
397
395
  # Convert the provided const desc to a qualified constant name (as a string).
398
396
  # A module, class, symbol, or string may be provided.
399
- def to_constant_name(desc)
397
+ def to_constant_name(desc) #:nodoc:
400
398
  name = case desc
401
399
  when String then desc.starts_with?('::') ? desc[2..-1] : desc
402
400
  when Symbol then desc.to_s
@@ -406,23 +404,24 @@ protected
406
404
  else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
407
405
  end
408
406
  end
409
-
410
- def remove_constant(const)
407
+
408
+ def remove_constant(const) #:nodoc:
411
409
  return false unless qualified_const_defined? const
412
-
410
+
413
411
  const = $1 if /\A::(.*)\Z/ =~ const.to_s
414
- names = const.split('::')
412
+ names = const.to_s.split('::')
415
413
  if names.size == 1 # It's under Object
416
414
  parent = Object
417
415
  else
418
416
  parent = (names[0..-2] * '::').constantize
419
417
  end
420
-
418
+
421
419
  log "removing constant #{const}"
422
- parent.send :remove_const, names.last
420
+ parent.instance_eval { remove_const names.last }
423
421
  return true
424
422
  end
425
-
423
+
424
+ protected
426
425
  def log_call(*args)
427
426
  arg_str = args.collect(&:inspect) * ', '
428
427
  /in `([a-z_\?\!]+)'/ =~ caller(1).first
@@ -438,9 +437,11 @@ protected
438
437
 
439
438
  end
440
439
 
441
- Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
442
- Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
443
- Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
440
+ Object.instance_eval do
441
+ define_method(:require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
442
+ define_method(:require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
443
+ define_method(:require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
444
+ end
444
445
 
445
446
  class Module #:nodoc:
446
447
  # Rename the original handler so we can chain it to the new one
@@ -480,18 +481,18 @@ class Class
480
481
  end
481
482
  end
482
483
 
483
- class Object #:nodoc:
484
+ class Object
484
485
 
485
486
  alias_method :load_without_new_constant_marking, :load
486
487
 
487
- def load(file, *extras)
488
+ def load(file, *extras) #:nodoc:
488
489
  Dependencies.new_constants_in(Object) { super(file, *extras) }
489
490
  rescue Exception => exception # errors from loading file
490
491
  exception.blame_file! file
491
492
  raise
492
493
  end
493
494
 
494
- def require(file, *extras)
495
+ def require(file, *extras) #:nodoc:
495
496
  Dependencies.new_constants_in(Object) { super(file, *extras) }
496
497
  rescue Exception => exception # errors from required file
497
498
  exception.blame_file! file
@@ -85,7 +85,7 @@ module ActiveSupport
85
85
  module ClassMethods #:nodoc:
86
86
  # Declare that a method has been deprecated.
87
87
  def deprecate(*method_names)
88
- options = method_names.last.is_a?(Hash) ? method_names.pop : {}
88
+ options = method_names.extract_options!
89
89
  method_names = method_names + options.keys
90
90
  method_names.each do |method_name|
91
91
  alias_method_chain(method_name, :deprecation) do |target, punctuation|
@@ -147,7 +147,9 @@ module ActiveSupport
147
147
  # Stand-in for @request, @attributes, @params, etc which emits deprecation
148
148
  # warnings on any method call (except #inspect).
149
149
  class DeprecatedInstanceVariableProxy #:nodoc:
150
- instance_methods.each { |m| undef_method m unless m =~ /^__/ }
150
+ silence_warnings do
151
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
152
+ end
151
153
 
152
154
  def initialize(instance, method, var = "@#{method}")
153
155
  @instance, @method, @var = instance, method, var
@@ -0,0 +1,86 @@
1
+ module ActiveSupport
2
+ # Provides accurate date and time measurements using Date#advance and
3
+ # Time#advance, respectively. It mainly supports the methods on Numeric,
4
+ # such as in this example:
5
+ #
6
+ # 1.month.ago # equivalent to Time.now.advance(:months => -1)
7
+ class Duration < BasicObject
8
+ attr_accessor :value, :parts
9
+
10
+ def initialize(value, parts) #:nodoc:
11
+ @value, @parts = value, parts
12
+ end
13
+
14
+ # Adds another Duration or a Numeric to this Duration. Numeric values
15
+ # are treated as seconds.
16
+ def +(other)
17
+ if Duration === other
18
+ Duration.new(value + other.value, @parts + other.parts)
19
+ else
20
+ Duration.new(value + other, @parts + [[:seconds, other]])
21
+ end
22
+ end
23
+
24
+ # Subtracts another Duration or a Numeric from this Duration. Numeric
25
+ # values are treated as seconds.
26
+ def -(other)
27
+ self + (-other)
28
+ end
29
+
30
+ def -@ #:nodoc:
31
+ Duration.new(-value, parts.map { |type,number| [type, -number] })
32
+ end
33
+
34
+ def is_a?(klass) #:nodoc:
35
+ klass == Duration || super
36
+ end
37
+
38
+ def self.===(other) #:nodoc:
39
+ other.is_a?(Duration) rescue super
40
+ end
41
+
42
+ # Calculates a new Time or Date that is as far in the future
43
+ # as this Duration represents.
44
+ def since(time = ::Time.now)
45
+ sum(1, time)
46
+ end
47
+ alias :from_now :since
48
+
49
+ # Calculates a new Time or Date that is as far in the past
50
+ # as this Duration represents.
51
+ def ago(time = ::Time.now)
52
+ sum(-1, time)
53
+ end
54
+ alias :until :ago
55
+
56
+ def inspect #:nodoc:
57
+ consolidated = parts.inject(Hash.new(0)) { |h,part| h[part.first] += part.last; h }
58
+ [:years, :months, :days, :minutes, :seconds].map do |length|
59
+ n = consolidated[length]
60
+ "#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero?
61
+ end.compact.to_sentence
62
+ end
63
+
64
+ protected
65
+
66
+ def sum(sign, time = ::Time.now) #:nodoc:
67
+ parts.inject(time) do |t,(type,number)|
68
+ if t.acts_like?(:time) || t.acts_like?(:date)
69
+ if type == :seconds
70
+ t.since(sign * number)
71
+ else
72
+ t.advance(type => sign * number)
73
+ end
74
+ else
75
+ raise ArgumentError, "expected a time or date, got #{time.inspect}"
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def method_missing(method, *args, &block) #:nodoc:
83
+ value.send(method, *args)
84
+ end
85
+ end
86
+ end
@@ -12,7 +12,7 @@ Inflector.inflections do |inflect|
12
12
  inflect.plural(/(hive)$/i, '\1s')
13
13
  inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
14
14
  inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
15
- inflect.plural(/(matr|vert|ind)ix|ex$/i, '\1ices')
15
+ inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
16
16
  inflect.plural(/([m|l])ouse$/i, '\1ice')
17
17
  inflect.plural(/^(ox)$/i, '\1en')
18
18
  inflect.plural(/(quiz)$/i, '\1zes')
@@ -47,6 +47,7 @@ Inflector.inflections do |inflect|
47
47
  inflect.irregular('child', 'children')
48
48
  inflect.irregular('sex', 'sexes')
49
49
  inflect.irregular('move', 'moves')
50
+ inflect.irregular('cow', 'kine')
50
51
 
51
52
  inflect.uncountable(%w(equipment information rice money species series fish sheep))
52
53
  end
@@ -47,8 +47,15 @@ module Inflector
47
47
  # irregular 'octopus', 'octopi'
48
48
  # irregular 'person', 'people'
49
49
  def irregular(singular, plural)
50
- plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
51
- singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
50
+ if singular[0,1].upcase == plural[0,1].upcase
51
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
52
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
53
+ else
54
+ plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
55
+ plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
56
+ singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
57
+ singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
58
+ end
52
59
  end
53
60
 
54
61
  # Add uncountable words that shouldn't be attempted inflected.
@@ -99,7 +106,7 @@ module Inflector
99
106
  def pluralize(word)
100
107
  result = word.to_s.dup
101
108
 
102
- if inflections.uncountables.include?(result.downcase)
109
+ if word.empty? || inflections.uncountables.include?(result.downcase)
103
110
  result
104
111
  else
105
112
  inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
@@ -263,9 +270,9 @@ module Inflector
263
270
  "#{number}th"
264
271
  else
265
272
  case number.to_i % 10
266
- when 1: "#{number}st"
267
- when 2: "#{number}nd"
268
- when 3: "#{number}rd"
273
+ when 1; "#{number}st"
274
+ when 2; "#{number}nd"
275
+ when 3; "#{number}rd"
269
276
  else "#{number}th"
270
277
  end
271
278
  end
@@ -1,48 +1,31 @@
1
- require 'active_support/json/encoders'
1
+ require 'active_support/json/encoding'
2
+ require 'active_support/json/decoding'
2
3
 
3
4
  module ActiveSupport
4
- module JSON #:nodoc:
5
- class CircularReferenceError < StandardError #:nodoc:
6
- end
7
-
8
- # A string that returns itself as as its JSON-encoded form.
9
- class Variable < String #:nodoc:
10
- def to_json
11
- self
12
- end
13
- end
14
-
15
- # When +true+, Hash#to_json will omit quoting string or symbol keys
16
- # if the keys are valid JavaScript identifiers. Note that this is
17
- # technically improper JSON (all object keys must be quoted), so if
18
- # you need strict JSON compliance, set this option to +false+.
19
- mattr_accessor :unquote_hash_key_identifiers
20
- @@unquote_hash_key_identifiers = true
5
+ module JSON
6
+ RESERVED_WORDS = %w(
7
+ abstract delete goto private transient
8
+ boolean do if protected try
9
+ break double implements public typeof
10
+ byte else import return var
11
+ case enum in short void
12
+ catch export instanceof static volatile
13
+ char extends int super while
14
+ class final interface switch with
15
+ const finally long synchronized
16
+ continue float native this
17
+ debugger for new throw
18
+ default function package throws
19
+ ) #:nodoc:
21
20
 
22
21
  class << self
23
- REFERENCE_STACK_VARIABLE = :json_reference_stack
24
-
25
- def encode(value)
26
- raise_on_circular_reference(value) do
27
- Encoders[value.class].call(value)
28
- end
22
+ def valid_identifier?(key) #:nodoc:
23
+ key.to_s =~ /^[[:alpha:]_$][[:alnum:]_$]*$/ && !reserved_word?(key)
29
24
  end
30
-
31
- def can_unquote_identifier?(key)
32
- return false unless unquote_hash_key_identifiers
33
- key.to_s =~ /^[[:alpha:]_$][[:alnum:]_$]*$/
25
+
26
+ def reserved_word?(key) #:nodoc:
27
+ RESERVED_WORDS.include?(key.to_s)
34
28
  end
35
-
36
- protected
37
- def raise_on_circular_reference(value)
38
- stack = Thread.current[REFERENCE_STACK_VARIABLE] ||= []
39
- raise CircularReferenceError, 'object references itself' if
40
- stack.include? value
41
- stack << value
42
- yield
43
- ensure
44
- stack.pop
45
- end
46
29
  end
47
30
  end
48
31
  end