activesupport 3.0.0.beta → 3.0.0.beta2

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 (73) hide show
  1. data/CHANGELOG +15 -1
  2. data/lib/active_support.rb +3 -0
  3. data/lib/active_support/all.rb +0 -1
  4. data/lib/active_support/cache/mem_cache_store.rb +1 -1
  5. data/lib/active_support/callbacks.rb +2 -2
  6. data/lib/active_support/core_ext/array/conversions.rb +0 -1
  7. data/lib/active_support/core_ext/array/extract_options.rb +16 -1
  8. data/lib/active_support/core_ext/class.rb +1 -0
  9. data/lib/active_support/core_ext/class/attribute.rb +30 -5
  10. data/lib/active_support/core_ext/class/attribute_accessors.rb +33 -27
  11. data/lib/active_support/core_ext/class/delegating_attributes.rb +10 -7
  12. data/lib/active_support/core_ext/class/subclasses.rb +55 -0
  13. data/lib/active_support/core_ext/date_time/conversions.rb +1 -0
  14. data/lib/active_support/core_ext/file/atomic.rb +3 -2
  15. data/lib/active_support/core_ext/file/path.rb +5 -0
  16. data/lib/active_support/core_ext/hash/conversions.rb +9 -0
  17. data/lib/active_support/core_ext/kernel.rb +0 -1
  18. data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
  19. data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
  20. data/lib/active_support/core_ext/module.rb +5 -3
  21. data/lib/active_support/core_ext/module/anonymous.rb +24 -0
  22. data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -21
  23. data/lib/active_support/core_ext/module/delegation.rb +20 -9
  24. data/lib/active_support/core_ext/module/introspection.rb +8 -8
  25. data/lib/active_support/core_ext/module/method_names.rb +14 -0
  26. data/lib/active_support/core_ext/module/reachable.rb +10 -0
  27. data/lib/active_support/core_ext/module/remove_method.rb +6 -0
  28. data/lib/active_support/core_ext/object.rb +7 -1
  29. data/lib/active_support/core_ext/object/extending.rb +11 -0
  30. data/lib/active_support/core_ext/object/singleton_class.rb +13 -0
  31. data/lib/active_support/core_ext/proc.rb +3 -3
  32. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  33. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  34. data/lib/active_support/core_ext/string/interpolation.rb +1 -91
  35. data/lib/active_support/core_ext/string/output_safety.rb +12 -8
  36. data/lib/active_support/core_ext/string/xchar.rb +1 -1
  37. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  38. data/lib/active_support/core_ext/time/marshal.rb +56 -0
  39. data/lib/active_support/dependencies.rb +146 -191
  40. data/lib/active_support/dependencies/autoload.rb +1 -0
  41. data/lib/active_support/deprecation/method_wrappers.rb +9 -9
  42. data/lib/active_support/deprecation/reporting.rb +2 -1
  43. data/lib/active_support/hash_with_indifferent_access.rb +4 -0
  44. data/lib/active_support/i18n.rb +2 -1
  45. data/lib/active_support/inflector/methods.rb +1 -1
  46. data/lib/active_support/inflector/transliterate.rb +3 -3
  47. data/lib/active_support/json/backends/yajl.rb +40 -0
  48. data/lib/active_support/json/decoding.rb +16 -1
  49. data/lib/active_support/lazy_load_hooks.rb +17 -0
  50. data/lib/active_support/memoizable.rb +1 -1
  51. data/lib/active_support/multibyte.rb +2 -2
  52. data/lib/active_support/multibyte/utils.rb +1 -1
  53. data/lib/active_support/notifications.rb +7 -3
  54. data/lib/active_support/notifications/fanout.rb +19 -5
  55. data/lib/active_support/ordered_options.rb +6 -0
  56. data/lib/active_support/railtie.rb +9 -9
  57. data/lib/active_support/ruby/shim.rb +2 -0
  58. data/lib/active_support/test_case.rb +2 -7
  59. data/lib/active_support/testing/assertions.rb +15 -0
  60. data/lib/active_support/testing/isolation.rb +2 -2
  61. data/lib/active_support/time.rb +1 -1
  62. data/lib/active_support/values/time_zone.rb +7 -4
  63. data/lib/active_support/version.rb +3 -2
  64. data/lib/active_support/whiny_nil.rb +4 -5
  65. data/lib/active_support/xml_mini/libxmlsax.rb +1 -0
  66. data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
  67. data/lib/active_support/xml_mini/rexml.rb +7 -1
  68. metadata +65 -31
  69. data/lib/active_support/core_ext/kernel/daemonizing.rb +0 -7
  70. data/lib/active_support/core_ext/module/inclusion.rb +0 -30
  71. data/lib/active_support/core_ext/module/loading.rb +0 -25
  72. data/lib/active_support/core_ext/object/metaclass.rb +0 -13
  73. data/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +0 -22
data/CHANGELOG CHANGED
@@ -1,4 +1,18 @@
1
- *Rails 3.0 (pending)*
1
+ *Rails 3.0.0 [beta 2] (April 1st, 2010)*
2
+
3
+ * Reduced load time by deferring configuration of classes using
4
+ ActiveSupport::on_load(:component_name) [YK]
5
+
6
+ * Rename #metaclass to #singleton_class now that ruby-core has decided [JK]
7
+
8
+ * New assertions assert_blank and assert_present. #4299 [Juanjo Bazan]
9
+
10
+ * Use Object#singleton_class instead of #metaclass. Prefer Ruby's choice. [Jeremy Kemper]
11
+
12
+ * JSON backend for YAJL. Preferred if available. #2666 [Brian Lopez]
13
+
14
+
15
+ *Rails 3.0.0 [beta 1] (February 4, 2010)*
2
16
 
3
17
  * Introduce class_attribute to declare inheritable class attributes. Writing an attribute on a subclass behaves just like overriding the superclass reader method. Unifies and replaces most usage of cattr_accessor, class_inheritable_attribute, superclass_delegating_attribute, and extlib_inheritable_attribute. [Jeremy Kemper, Yehuda Katz]
4
18
 
@@ -53,6 +53,7 @@ module ActiveSupport
53
53
  autoload :Deprecation
54
54
  autoload :Gzip
55
55
  autoload :Inflector
56
+ autoload :JSON
56
57
  autoload :Memoizable
57
58
  autoload :MessageEncryptor
58
59
  autoload :MessageVerifier
@@ -70,3 +71,5 @@ module ActiveSupport
70
71
  autoload :SafeBuffer, "active_support/core_ext/string/output_safety"
71
72
  autoload :TestCase
72
73
  end
74
+
75
+ autoload :I18n, "active_support/i18n"
@@ -1,4 +1,3 @@
1
1
  require 'active_support'
2
- require 'active_support/i18n'
3
2
  require 'active_support/time'
4
3
  require 'active_support/core_ext'
@@ -91,7 +91,7 @@ module ActiveSupport
91
91
 
92
92
  def delete(key, options = nil) # :nodoc:
93
93
  super do
94
- response = @data.delete(key, expires_in(options))
94
+ response = @data.delete(key)
95
95
  response == Response::DELETED
96
96
  end
97
97
  rescue MemCache::MemCacheError => e
@@ -1,7 +1,7 @@
1
1
  require 'active_support/core_ext/array/wrap'
2
2
  require 'active_support/core_ext/class/inheritable_attributes'
3
3
  require 'active_support/core_ext/kernel/reporting'
4
- require 'active_support/core_ext/object/metaclass'
4
+ require 'active_support/core_ext/object/singleton_class'
5
5
 
6
6
  module ActiveSupport
7
7
  # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
@@ -312,7 +312,7 @@ module ActiveSupport
312
312
 
313
313
  def _normalize_legacy_filter(kind, filter)
314
314
  if !filter.respond_to?(kind) && filter.respond_to?(:filter)
315
- filter.metaclass.class_eval(
315
+ filter.singleton_class.class_eval(
316
316
  "def #{kind}(context, &block) filter(context, &block) end",
317
317
  __FILE__, __LINE__ - 1)
318
318
  elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around
@@ -1,7 +1,6 @@
1
1
  require 'active_support/core_ext/hash/keys'
2
2
  require 'active_support/core_ext/hash/reverse_merge'
3
3
  require 'active_support/inflector'
4
- require 'active_support/i18n'
5
4
 
6
5
  class Array
7
6
  # Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
@@ -1,3 +1,14 @@
1
+ class Hash
2
+ # By default, only instances of Hash itself are extractable.
3
+ # Subclasses of Hash may implement this method and return
4
+ # true to declare themselves as extractable. If a Hash
5
+ # is extractable, Array#extract_options! pops it from
6
+ # the Array when it is the last element of the Array.
7
+ def extractable_options?
8
+ instance_of?(Hash)
9
+ end
10
+ end
11
+
1
12
  class Array
2
13
  # Extracts options from a set of arguments. Removes and returns the last
3
14
  # element in the array if it's a hash, otherwise returns a blank hash.
@@ -9,6 +20,10 @@ class Array
9
20
  # options(1, 2) # => {}
10
21
  # options(1, 2, :a => :b) # => {:a=>:b}
11
22
  def extract_options!
12
- last.is_a?(::Hash) ? pop : {}
23
+ if last.is_a?(Hash) && last.extractable_options?
24
+ pop
25
+ else
26
+ {}
27
+ end
13
28
  end
14
29
  end
@@ -1,3 +1,4 @@
1
1
  require 'active_support/core_ext/class/attribute_accessors'
2
2
  require 'active_support/core_ext/class/inheritable_attributes'
3
3
  require 'active_support/core_ext/class/delegating_attributes'
4
+ require 'active_support/core_ext/class/subclasses'
@@ -1,5 +1,6 @@
1
- require 'active_support/core_ext/object/metaclass'
1
+ require 'active_support/core_ext/object/singleton_class'
2
2
  require 'active_support/core_ext/module/delegation'
3
+ require 'active_support/core_ext/module/remove_method'
3
4
 
4
5
  class Class
5
6
  # Declare a class-level attribute whose value is inheritable and
@@ -24,13 +25,37 @@ class Class
24
25
  # For convenience, a query method is defined as well:
25
26
  #
26
27
  # Subclass.setting? # => false
28
+ #
29
+ # Instances may overwrite the class value in the same way:
30
+ #
31
+ # Base.setting = true
32
+ # object = Base.new
33
+ # object.setting # => true
34
+ # object.setting = false
35
+ # object.setting # => false
36
+ # Base.setting # => true
37
+ #
38
+ # To opt out of the instance writer method, pass :instance_writer => false.
39
+ #
40
+ # object.setting = false # => NoMethodError
27
41
  def class_attribute(*attrs)
42
+ instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
43
+
44
+ s = singleton_class
28
45
  attrs.each do |attr|
29
- metaclass.send(:define_method, attr) { }
30
- metaclass.send(:define_method, "#{attr}?") { !!send(attr) }
31
- metaclass.send(:define_method, "#{attr}=") do |value|
32
- metaclass.send(:define_method, attr) { value }
46
+ s.send(:define_method, attr) { }
47
+ s.send(:define_method, :"#{attr}?") { !!send(attr) }
48
+ s.send(:define_method, :"#{attr}=") do |value|
49
+ singleton_class.remove_possible_method(attr)
50
+ singleton_class.send(:define_method, attr) { value }
33
51
  end
52
+
53
+ define_method(attr) { self.class.send(attr) }
54
+ define_method(:"#{attr}?") { !!send(attr) }
55
+ define_method(:"#{attr}=") do |value|
56
+ singleton_class.remove_possible_method(attr)
57
+ singleton_class.send(:define_method, attr) { value }
58
+ end if instance_writer
34
59
  end
35
60
  end
36
61
  end
@@ -10,42 +10,48 @@ require 'active_support/core_ext/array/extract_options'
10
10
  # Person.hair_colors = [:brown, :black, :blonde, :red]
11
11
  class Class
12
12
  def cattr_reader(*syms)
13
- syms.flatten.each do |sym|
14
- next if sym.is_a?(Hash)
13
+ options = syms.extract_options!
14
+ syms.each do |sym|
15
15
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
16
- unless defined? @@#{sym} # unless defined? @@hair_colors
17
- @@#{sym} = nil # @@hair_colors = nil
18
- end # end
19
- #
20
- def self.#{sym} # def self.hair_colors
21
- @@#{sym} # @@hair_colors
22
- end # end
23
- #
24
- def #{sym} # def hair_colors
25
- @@#{sym} # @@hair_colors
26
- end # end
16
+ unless defined? @@#{sym}
17
+ @@#{sym} = nil
18
+ end
19
+
20
+ def self.#{sym}
21
+ @@#{sym}
22
+ end
27
23
  EOS
24
+
25
+ unless options[:instance_reader] == false
26
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
27
+ def #{sym}
28
+ @@#{sym}
29
+ end
30
+ EOS
31
+ end
28
32
  end
29
33
  end
30
34
 
31
35
  def cattr_writer(*syms)
32
36
  options = syms.extract_options!
33
- syms.flatten.each do |sym|
37
+ syms.each do |sym|
34
38
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
35
- unless defined? @@#{sym} # unless defined? @@hair_colors
36
- @@#{sym} = nil # @@hair_colors = nil
37
- end # end
38
- #
39
- def self.#{sym}=(obj) # def self.hair_colors=(obj)
40
- @@#{sym} = obj # @@hair_colors = obj
41
- end # end
42
- #
43
- #{" #
44
- def #{sym}=(obj) # def hair_colors=(obj)
45
- @@#{sym} = obj # @@hair_colors = obj
46
- end # end
47
- " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false
39
+ unless defined? @@#{sym}
40
+ @@#{sym} = nil
41
+ end
42
+
43
+ def self.#{sym}=(obj)
44
+ @@#{sym} = obj
45
+ end
48
46
  EOS
47
+
48
+ unless options[:instance_writer] == false
49
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
50
+ def #{sym}=(obj)
51
+ @@#{sym} = obj
52
+ end
53
+ EOS
54
+ end
49
55
  self.send("#{sym}=", yield) if block_given?
50
56
  end
51
57
  end
@@ -1,6 +1,7 @@
1
1
  require 'active_support/core_ext/object/blank'
2
2
  require 'active_support/core_ext/array/extract_options'
3
- require 'active_support/core_ext/object/metaclass'
3
+ require 'active_support/core_ext/object/singleton_class'
4
+ require 'active_support/core_ext/module/remove_method'
4
5
 
5
6
  class Class
6
7
  def superclass_delegating_accessor(name, options = {})
@@ -11,9 +12,9 @@ class Class
11
12
  # Generate the public methods name, name=, and name?
12
13
  # These methods dispatch to the private _name, and _name= methods, making them
13
14
  # overridable
14
- metaclass.send(:define_method, name) { send("_#{name}") }
15
- metaclass.send(:define_method, "#{name}?") { !!send("_#{name}") }
16
- metaclass.send(:define_method, "#{name}=") { |value| send("_#{name}=", value) }
15
+ singleton_class.send(:define_method, name) { send("_#{name}") }
16
+ singleton_class.send(:define_method, "#{name}?") { !!send("_#{name}") }
17
+ singleton_class.send(:define_method, "#{name}=") { |value| send("_#{name}=", value) }
17
18
 
18
19
  # If an instance_reader is needed, generate methods for name and name= on the
19
20
  # class itself, so instances will be able to see them
@@ -27,15 +28,17 @@ private
27
28
  # inheritance behavior, without having to store the object in an instance
28
29
  # variable and look up the superclass chain manually.
29
30
  def _stash_object_in_method(object, method, instance_reader = true)
30
- metaclass.send(:define_method, method) { object }
31
+ singleton_class.remove_possible_method(method)
32
+ singleton_class.send(:define_method, method) { object }
33
+ remove_possible_method(method)
31
34
  define_method(method) { object } if instance_reader
32
35
  end
33
36
 
34
37
  def _superclass_delegating_accessor(name, options = {})
35
- metaclass.send(:define_method, "#{name}=") do |value|
38
+ singleton_class.send(:define_method, "#{name}=") do |value|
36
39
  _stash_object_in_method(value, name, options[:instance_reader] != false)
37
40
  end
38
- self.send("#{name}=", nil)
41
+ send("#{name}=", nil)
39
42
  end
40
43
 
41
44
  end
@@ -0,0 +1,55 @@
1
+ require 'active_support/core_ext/module/anonymous'
2
+ require 'active_support/core_ext/module/reachable'
3
+
4
+ class Class #:nodoc:
5
+ # Returns an array with the names of the subclasses of +self+ as strings.
6
+ #
7
+ # Integer.subclasses # => ["Bignum", "Fixnum"]
8
+ def subclasses
9
+ Class.subclasses_of(self).map { |o| o.to_s }
10
+ end
11
+
12
+ # Rubinius
13
+ if defined?(Class.__subclasses__)
14
+ def descendents
15
+ subclasses = []
16
+ __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendents }
17
+ subclasses
18
+ end
19
+ else
20
+ # MRI
21
+ begin
22
+ ObjectSpace.each_object(Class.new) {}
23
+
24
+ def descendents
25
+ subclasses = []
26
+ ObjectSpace.each_object(class << self; self; end) do |k|
27
+ subclasses << k unless k == self
28
+ end
29
+ subclasses
30
+ end
31
+ # JRuby
32
+ rescue StandardError
33
+ def descendents
34
+ subclasses = []
35
+ ObjectSpace.each_object(Class) do |k|
36
+ subclasses << k if k < self
37
+ end
38
+ subclasses.uniq!
39
+ subclasses
40
+ end
41
+ end
42
+ end
43
+
44
+ # Exclude this class unless it's a subclass of our supers and is defined.
45
+ # We check defined? in case we find a removed class that has yet to be
46
+ # garbage collected. This also fails for anonymous classes -- please
47
+ # submit a patch if you have a workaround.
48
+ def self.subclasses_of(*superclasses) #:nodoc:
49
+ subclasses = []
50
+ superclasses.each do |klass|
51
+ subclasses.concat klass.descendents.select {|k| k.anonymous? || k.reachable?}
52
+ end
53
+ subclasses
54
+ end
55
+ end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/inflector'
2
+ require 'active_support/core_ext/time/conversions'
2
3
 
3
4
  class DateTime
4
5
  # Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows
@@ -9,11 +9,12 @@ class File
9
9
  # If your temp directory is not on the same filesystem as the file you're
10
10
  # trying to write, you can provide a different temporary directory.
11
11
  #
12
- # File.atomic_write("/data/something.important", "/data/tmp") do |f|
12
+ # File.atomic_write("/data/something.important", "/data/tmp") do |file|
13
13
  # file.write("hello")
14
14
  # end
15
15
  def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
16
16
  require 'tempfile' unless defined?(Tempfile)
17
+ require 'fileutils' unless defined?(FileUtils)
17
18
 
18
19
  temp_file = Tempfile.new(basename(file_name), temp_dir)
19
20
  yield temp_file
@@ -31,7 +32,7 @@ class File
31
32
  end
32
33
 
33
34
  # Overwrite original file with temp file
34
- rename(temp_file.path, file_name)
35
+ FileUtils.mv(temp_file.path, file_name)
35
36
 
36
37
  # Set correct permissions on new file
37
38
  chown(old_stat.uid, old_stat.gid, file_name)
@@ -0,0 +1,5 @@
1
+ class File
2
+ unless File.allocate.respond_to?(:to_path)
3
+ alias to_path path
4
+ end
5
+ end
@@ -54,6 +54,15 @@ class Hash
54
54
  "string" => Proc.new { |string| string.to_s },
55
55
  "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
56
56
  "base64Binary" => Proc.new { |bin| ActiveSupport::Base64.decode64(bin) },
57
+ "binary" => Proc.new do |bin, entity|
58
+ case entity['encoding']
59
+ when 'base64'
60
+ ActiveSupport::Base64.decode64(bin)
61
+ # TODO: Add support for other encodings
62
+ else
63
+ bin
64
+ end
65
+ end,
57
66
  "file" => Proc.new do |file, entity|
58
67
  f = StringIO.new(ActiveSupport::Base64.decode64(file))
59
68
  f.extend(FileLike)
@@ -1,4 +1,3 @@
1
- require 'active_support/core_ext/kernel/daemonizing'
2
1
  require 'active_support/core_ext/kernel/reporting'
3
2
  require 'active_support/core_ext/kernel/agnostics'
4
3
  require 'active_support/core_ext/kernel/requires'
@@ -1,6 +1,6 @@
1
1
  module Kernel
2
2
  unless respond_to?(:debugger)
3
- # Starts a debugging session if ruby-debug has been loaded (call script/server --debugger to do load it).
3
+ # Starts a debugging session if ruby-debug has been loaded (call rails server --debugger to do load it).
4
4
  def debugger
5
5
  message = "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n"
6
6
  defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
@@ -37,7 +37,7 @@ module Kernel
37
37
  # puts 'But this will'
38
38
  def silence_stream(stream)
39
39
  old_stream = stream.dup
40
- stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
40
+ stream.reopen(RUBY_PLATFORM =~ /mswin|mingw/ ? 'NUL:' : '/dev/null')
41
41
  stream.sync = true
42
42
  yield
43
43
  ensure
@@ -1,10 +1,12 @@
1
1
  require 'active_support/core_ext/module/aliasing'
2
2
  require 'active_support/core_ext/module/introspection'
3
-
4
- require 'active_support/core_ext/module/inclusion'
3
+ require 'active_support/core_ext/module/anonymous'
4
+ require 'active_support/core_ext/module/reachable'
5
5
  require 'active_support/core_ext/module/attribute_accessors'
6
6
  require 'active_support/core_ext/module/attr_internal'
7
7
  require 'active_support/core_ext/module/attr_accessor_with_default'
8
8
  require 'active_support/core_ext/module/delegation'
9
- require 'active_support/core_ext/module/loading'
10
9
  require 'active_support/core_ext/module/synchronization'
10
+ require 'active_support/core_ext/module/deprecation'
11
+ require 'active_support/core_ext/module/remove_method'
12
+ require 'active_support/core_ext/module/method_names'
@@ -0,0 +1,24 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
3
+ class Module
4
+ # A module may or may not have a name.
5
+ #
6
+ # module M; end
7
+ # M.name # => "M"
8
+ #
9
+ # m = Module.new
10
+ # m.name # => ""
11
+ #
12
+ # A module gets a name when it is first assigned to a constant. Either
13
+ # via the +module+ or +class+ keyword or by an explicit assignment:
14
+ #
15
+ # m = Module.new # creates an anonymous module
16
+ # M = m # => m gets a name here as a side-effect
17
+ # m.name # => "M"
18
+ #
19
+ 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?
23
+ end
24
+ end