activesupport 3.0.20 → 3.1.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.
- data/CHANGELOG +24 -28
- data/README.rdoc +2 -2
- data/lib/active_support/backtrace_cleaner.rb +17 -12
- data/lib/active_support/buffered_logger.rb +7 -9
- data/lib/active_support/cache/file_store.rb +4 -3
- data/lib/active_support/cache/mem_cache_store.rb +10 -2
- data/lib/active_support/cache/strategy/local_cache.rb +28 -23
- data/lib/active_support/cache.rb +11 -14
- data/lib/active_support/callbacks.rb +195 -175
- data/lib/active_support/concern.rb +105 -35
- data/lib/active_support/configurable.rb +50 -8
- data/lib/active_support/core_ext/array/access.rb +2 -2
- data/lib/active_support/core_ext/array/conversions.rb +2 -2
- data/lib/active_support/core_ext/array/random_access.rb +10 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +2 -3
- data/lib/active_support/core_ext/array/wrap.rb +1 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/attribute.rb +15 -1
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +10 -86
- data/lib/active_support/core_ext/class/subclasses.rb +20 -34
- data/lib/active_support/core_ext/date/calculations.rb +17 -5
- data/lib/active_support/core_ext/date/conversions.rb +9 -2
- data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
- data/lib/active_support/core_ext/date_time/conversions.rb +9 -9
- data/lib/active_support/core_ext/date_time/zones.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +3 -6
- data/lib/active_support/core_ext/float/rounding.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +22 -34
- data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +12 -0
- data/lib/active_support/core_ext/hash/keys.rb +6 -4
- data/lib/active_support/core_ext/hash/reverse_merge.rb +9 -14
- data/lib/active_support/core_ext/hash/slice.rb +3 -1
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/integer/inflections.rb +7 -4
- data/lib/active_support/core_ext/kernel/reporting.rb +31 -0
- data/lib/active_support/core_ext/kernel/requires.rb +2 -0
- data/lib/active_support/core_ext/logger.rb +11 -38
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +12 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
- data/lib/active_support/core_ext/module/delegation.rb +1 -5
- data/lib/active_support/core_ext/module/remove_method.rb +7 -2
- data/lib/active_support/core_ext/numeric/time.rb +2 -0
- data/lib/active_support/core_ext/object/blank.rb +45 -12
- data/lib/active_support/core_ext/object/duplicable.rb +50 -9
- data/lib/active_support/core_ext/object/inclusion.rb +15 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -35
- data/lib/active_support/core_ext/object/to_param.rb +13 -8
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +29 -10
- data/lib/active_support/core_ext/object/with_options.rb +25 -8
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/range/cover.rb +3 -0
- data/lib/active_support/core_ext/range.rb +1 -0
- data/lib/active_support/core_ext/string/behavior.rb +1 -2
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/exclude.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/inquiry.rb +13 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +45 -62
- data/lib/active_support/core_ext/string.rb +1 -0
- data/lib/active_support/core_ext/time/calculations.rb +19 -16
- data/lib/active_support/core_ext/time/conversions.rb +2 -24
- data/lib/active_support/core_ext/time/zones.rb +32 -21
- data/lib/active_support/core_ext/uri.rb +8 -0
- data/lib/active_support/dependencies.rb +74 -28
- data/lib/active_support/deprecation/behaviors.rb +7 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
- data/lib/active_support/deprecation/reporting.rb +4 -0
- data/lib/active_support/deprecation.rb +2 -2
- data/lib/active_support/descendants_tracker.rb +9 -7
- data/lib/active_support/duration.rb +5 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/file_watcher.rb +36 -0
- data/lib/active_support/hash_with_indifferent_access.rb +20 -8
- data/lib/active_support/i18n.rb +0 -1
- data/lib/active_support/i18n_railtie.rb +2 -2
- data/lib/active_support/inflections.rb +1 -0
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/inflector/methods.rb +5 -3
- data/lib/active_support/json/decoding.rb +37 -23
- data/lib/active_support/json/encoding.rb +12 -4
- data/lib/active_support/lazy_load_hooks.rb +7 -7
- data/lib/active_support/log_subscriber/test_helper.rb +5 -3
- data/lib/active_support/log_subscriber.rb +6 -6
- data/lib/active_support/message_encryptor.rb +1 -1
- data/lib/active_support/message_verifier.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +5 -5
- data/lib/active_support/multibyte/unicode.rb +2 -1
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +1 -1
- data/lib/active_support/notifications.rb +9 -10
- data/lib/active_support/ordered_hash.rb +23 -2
- data/lib/active_support/ordered_options.rb +37 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/rescuable.rb +1 -0
- data/lib/active_support/secure_random.rb +3 -196
- data/lib/active_support/test_case.rb +2 -10
- data/lib/active_support/testing/assertions.rb +20 -7
- data/lib/active_support/testing/mochaing.rb +7 -0
- data/lib/active_support/testing/pending.rb +27 -23
- data/lib/active_support/testing/performance/jruby.rb +115 -0
- data/lib/active_support/testing/performance/rubinius.rb +113 -0
- data/lib/active_support/testing/performance/ruby/mri.rb +57 -0
- data/lib/active_support/testing/performance/ruby/yarv.rb +57 -0
- data/lib/active_support/testing/performance/ruby.rb +152 -0
- data/lib/active_support/testing/performance.rb +214 -322
- data/lib/active_support/testing/setup_and_teardown.rb +8 -11
- data/lib/active_support/time_with_zone.rb +6 -3
- data/lib/active_support/values/time_zone.rb +26 -8
- data/lib/active_support/version.rb +2 -2
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +1 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -1
- data/lib/active_support/xml_mini/nokogiri.rb +1 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
- data/lib/active_support/xml_mini/rexml.rb +1 -0
- data/lib/active_support/xml_mini.rb +8 -3
- data/lib/active_support.rb +4 -2
- metadata +70 -32
- checksums.yaml +0 -7
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
- data/lib/active_support/core_ext/cgi.rb +0 -1
- data/lib/active_support/core_ext/object/returning.rb +0 -43
- data/lib/active_support/json/backends/jsongem.rb +0 -47
- data/lib/active_support/json/backends/okjson.rb +0 -644
- data/lib/active_support/json/backends/yajl.rb +0 -44
- data/lib/active_support/json/backends/yaml.rb +0 -19
- data/lib/active_support/testing/default.rb +0 -9
|
@@ -1,39 +1,109 @@
|
|
|
1
|
-
# A typical module looks like this
|
|
2
|
-
#
|
|
3
|
-
# module M
|
|
4
|
-
# def self.included(base)
|
|
5
|
-
# base.send(:extend, ClassMethods)
|
|
6
|
-
# base.send(:include, InstanceMethods)
|
|
7
|
-
# scope :foo, :conditions => { :created_at => nil }
|
|
8
|
-
# end
|
|
9
|
-
#
|
|
10
|
-
# module ClassMethods
|
|
11
|
-
# def cm; puts 'I am a class method'; end
|
|
12
|
-
# end
|
|
13
|
-
#
|
|
14
|
-
# module InstanceMethods
|
|
15
|
-
# def im; puts 'I am an instance method'; end
|
|
16
|
-
# end
|
|
17
|
-
# end
|
|
18
|
-
#
|
|
19
|
-
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
|
|
20
|
-
#
|
|
21
|
-
# module M
|
|
22
|
-
# extend ActiveSupport::Concern
|
|
23
|
-
#
|
|
24
|
-
# included do
|
|
25
|
-
# scope :foo, :conditions => { :created_at => nil }
|
|
26
|
-
# end
|
|
27
|
-
#
|
|
28
|
-
# module ClassMethods
|
|
29
|
-
# def cm; puts 'I am a class method'; end
|
|
30
|
-
# end
|
|
31
|
-
#
|
|
32
|
-
# module InstanceMethods
|
|
33
|
-
# def im; puts 'I am an instance method'; end
|
|
34
|
-
# end
|
|
35
|
-
# end
|
|
36
1
|
module ActiveSupport
|
|
2
|
+
# A typical module looks like this:
|
|
3
|
+
#
|
|
4
|
+
# module M
|
|
5
|
+
# def self.included(base)
|
|
6
|
+
# base.extend ClassMethods
|
|
7
|
+
# base.send(:include, InstanceMethods)
|
|
8
|
+
# scope :disabled, where(:disabled => true)
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# module ClassMethods
|
|
12
|
+
# ...
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# module InstanceMethods
|
|
16
|
+
# ...
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
|
|
21
|
+
#
|
|
22
|
+
# require 'active_support/concern'
|
|
23
|
+
#
|
|
24
|
+
# module M
|
|
25
|
+
# extend ActiveSupport::Concern
|
|
26
|
+
#
|
|
27
|
+
# included do
|
|
28
|
+
# scope :disabled, where(:disabled => true)
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# module ClassMethods
|
|
32
|
+
# ...
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# module InstanceMethods
|
|
36
|
+
# ...
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module and a +Bar+
|
|
41
|
+
# module which depends on the former, we would typically write the following:
|
|
42
|
+
#
|
|
43
|
+
# module Foo
|
|
44
|
+
# def self.included(base)
|
|
45
|
+
# base.class_eval do
|
|
46
|
+
# def self.method_injected_by_foo
|
|
47
|
+
# ...
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# module Bar
|
|
54
|
+
# def self.included(base)
|
|
55
|
+
# base.method_injected_by_foo
|
|
56
|
+
# end
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# class Host
|
|
60
|
+
# include Foo # We need to include this dependency for Bar
|
|
61
|
+
# include Bar # Bar is the module that Host really needs
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We could try to hide
|
|
65
|
+
# these from +Host+ directly including +Foo+ in +Bar+:
|
|
66
|
+
#
|
|
67
|
+
# module Bar
|
|
68
|
+
# include Foo
|
|
69
|
+
# def self.included(base)
|
|
70
|
+
# base.method_injected_by_foo
|
|
71
|
+
# end
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# class Host
|
|
75
|
+
# include Bar
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt> is the +Bar+ module,
|
|
79
|
+
# not the +Host+ class. With <tt>ActiveSupport::Concern</tt>, module dependencies are properly resolved:
|
|
80
|
+
#
|
|
81
|
+
# require 'active_support/concern'
|
|
82
|
+
#
|
|
83
|
+
# module Foo
|
|
84
|
+
# extend ActiveSupport::Concern
|
|
85
|
+
# included do
|
|
86
|
+
# class_eval do
|
|
87
|
+
# def self.method_injected_by_foo
|
|
88
|
+
# ...
|
|
89
|
+
# end
|
|
90
|
+
# end
|
|
91
|
+
# end
|
|
92
|
+
# end
|
|
93
|
+
#
|
|
94
|
+
# module Bar
|
|
95
|
+
# extend ActiveSupport::Concern
|
|
96
|
+
# include Foo
|
|
97
|
+
#
|
|
98
|
+
# included do
|
|
99
|
+
# self.method_injected_by_foo
|
|
100
|
+
# end
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
# class Host
|
|
104
|
+
# include Bar # works, Bar takes care now of its dependencies
|
|
105
|
+
# end
|
|
106
|
+
#
|
|
37
107
|
module Concern
|
|
38
108
|
def self.extended(base)
|
|
39
109
|
base.instance_variable_set("@_dependencies", [])
|
|
@@ -2,14 +2,37 @@ require 'active_support/concern'
|
|
|
2
2
|
require 'active_support/ordered_options'
|
|
3
3
|
require 'active_support/core_ext/kernel/singleton_class'
|
|
4
4
|
require 'active_support/core_ext/module/delegation'
|
|
5
|
+
require 'active_support/core_ext/array/extract_options'
|
|
5
6
|
|
|
6
7
|
module ActiveSupport
|
|
8
|
+
# Configurable provides a <tt>config</tt> method to store and retrieve
|
|
9
|
+
# configuration options as an <tt>OrderedHash</tt>.
|
|
7
10
|
module Configurable
|
|
8
11
|
extend ActiveSupport::Concern
|
|
9
12
|
|
|
13
|
+
class Configuration < ActiveSupport::InheritableOptions
|
|
14
|
+
def compile_methods!
|
|
15
|
+
self.class.compile_methods!(keys)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# compiles reader methods so we don't have to go through method_missing
|
|
19
|
+
def self.compile_methods!(keys)
|
|
20
|
+
keys.reject { |m| method_defined?(m) }.each do |key|
|
|
21
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
22
|
+
def #{key}; _get(#{key.inspect}); end
|
|
23
|
+
RUBY
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
10
28
|
module ClassMethods
|
|
11
29
|
def config
|
|
12
|
-
@_config ||=
|
|
30
|
+
@_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
|
|
31
|
+
superclass.config.inheritable_copy
|
|
32
|
+
else
|
|
33
|
+
# create a new "anonymous" class that will host the compiled reader methods
|
|
34
|
+
Class.new(Configuration).new
|
|
35
|
+
end
|
|
13
36
|
end
|
|
14
37
|
|
|
15
38
|
def configure
|
|
@@ -29,20 +52,39 @@ module ActiveSupport
|
|
|
29
52
|
# user.allowed_access # => true
|
|
30
53
|
#
|
|
31
54
|
def config_accessor(*names)
|
|
55
|
+
options = names.extract_options!
|
|
56
|
+
|
|
32
57
|
names.each do |name|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def #{name}=(value); config.#{name} = value; end
|
|
36
|
-
RUBY
|
|
58
|
+
reader, line = "def #{name}; config.#{name}; end", __LINE__
|
|
59
|
+
writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
|
37
60
|
|
|
38
|
-
singleton_class.class_eval
|
|
39
|
-
class_eval
|
|
61
|
+
singleton_class.class_eval reader, __FILE__, line
|
|
62
|
+
singleton_class.class_eval writer, __FILE__, line
|
|
63
|
+
class_eval reader, __FILE__, line unless options[:instance_reader] == false
|
|
64
|
+
class_eval writer, __FILE__, line unless options[:instance_writer] == false
|
|
40
65
|
end
|
|
41
66
|
end
|
|
42
67
|
end
|
|
43
68
|
|
|
69
|
+
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
|
|
70
|
+
#
|
|
71
|
+
# require 'active_support/configurable'
|
|
72
|
+
#
|
|
73
|
+
# class User
|
|
74
|
+
# include ActiveSupport::Configurable
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# user = User.new
|
|
78
|
+
#
|
|
79
|
+
# user.config.allowed_access = true
|
|
80
|
+
# user.config.level = 1
|
|
81
|
+
#
|
|
82
|
+
# user.config.allowed_access # => true
|
|
83
|
+
# user.config.level # => 1
|
|
84
|
+
#
|
|
44
85
|
def config
|
|
45
|
-
@_config ||=
|
|
86
|
+
@_config ||= self.class.config.inheritable_copy
|
|
46
87
|
end
|
|
47
88
|
end
|
|
48
89
|
end
|
|
90
|
+
|
|
@@ -3,10 +3,10 @@ class Array
|
|
|
3
3
|
#
|
|
4
4
|
# %w( a b c d ).from(0) # => %w( a b c d )
|
|
5
5
|
# %w( a b c d ).from(2) # => %w( c d )
|
|
6
|
-
# %w( a b c d ).from(10) # =>
|
|
6
|
+
# %w( a b c d ).from(10) # => %w()
|
|
7
7
|
# %w().from(0) # => %w()
|
|
8
8
|
def from(position)
|
|
9
|
-
self[position
|
|
9
|
+
self[position, length] || []
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# Returns the beginning of the array up to +position+.
|
|
@@ -37,12 +37,12 @@ class Array
|
|
|
37
37
|
# Converts a collection of elements into a formatted string by calling
|
|
38
38
|
# <tt>to_s</tt> on all elements and joining them:
|
|
39
39
|
#
|
|
40
|
-
# Blog.
|
|
40
|
+
# Blog.all.to_formatted_s # => "First PostSecond PostThird Post"
|
|
41
41
|
#
|
|
42
42
|
# Adding in the <tt>:db</tt> argument as the format yields a prettier
|
|
43
43
|
# output:
|
|
44
44
|
#
|
|
45
|
-
# Blog.
|
|
45
|
+
# Blog.all.to_formatted_s(:db) # => "First Post,Second Post,Third Post"
|
|
46
46
|
def to_formatted_s(format = :default)
|
|
47
47
|
case format
|
|
48
48
|
when :db
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
class Array
|
|
2
|
-
# Backport of Array#sample based on Marc-Andre Lafortune's
|
|
2
|
+
# Backport of Array#sample based on Marc-Andre Lafortune's https://github.com/marcandre/backports/
|
|
3
3
|
# Returns a random element or +n+ random elements from the array.
|
|
4
|
-
# If the array is empty and +n+ is nil, returns <tt>nil</tt>.
|
|
4
|
+
# If the array is empty and +n+ is nil, returns <tt>nil</tt>.
|
|
5
|
+
# If +n+ is passed and its value is less than 0, it raises an +ArgumentError+ exception.
|
|
6
|
+
# If the value of +n+ is equal or greater than 0 it returns <tt>[]</tt>.
|
|
5
7
|
#
|
|
6
|
-
# [1,2,3,4,5,6].sample
|
|
7
|
-
# [1,2,3,4,5,6].sample(3)
|
|
8
|
-
#
|
|
9
|
-
# [].sample
|
|
8
|
+
# [1,2,3,4,5,6].sample # => 4
|
|
9
|
+
# [1,2,3,4,5,6].sample(3) # => [2, 4, 5]
|
|
10
|
+
# [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative array size
|
|
11
|
+
# [].sample # => nil
|
|
12
|
+
# [].sample(3) # => []
|
|
10
13
|
def sample(n=nil)
|
|
11
14
|
return self[Kernel.rand(size)] if n.nil?
|
|
12
15
|
n = n.to_int
|
|
@@ -24,4 +27,4 @@ class Array
|
|
|
24
27
|
result[n..size] = []
|
|
25
28
|
result
|
|
26
29
|
end unless method_defined? :sample
|
|
27
|
-
end
|
|
30
|
+
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
class Array
|
|
2
|
-
#
|
|
2
|
+
# Returns an unique array based on the criteria given as a +Proc+.
|
|
3
3
|
#
|
|
4
|
-
# [1, 2, 3, 4].uniq_by { |i| i.odd? }
|
|
5
|
-
# # => [1, 2]
|
|
4
|
+
# [1, 2, 3, 4].uniq_by { |i| i.odd? } # => [1, 2]
|
|
6
5
|
#
|
|
7
6
|
def uniq_by
|
|
8
7
|
hash, array = {}, []
|
|
@@ -14,7 +14,7 @@ class Array
|
|
|
14
14
|
# This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
|
|
15
15
|
#
|
|
16
16
|
# * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
|
|
17
|
-
# moves on to try +to_a+ if the returned value is +nil+, but <tt>
|
|
17
|
+
# moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
|
|
18
18
|
# such a +nil+ right away.
|
|
19
19
|
# * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
|
|
20
20
|
# raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
|
|
@@ -11,8 +11,6 @@ class BigDecimal
|
|
|
11
11
|
YAML_TAG = 'tag:yaml.org,2002:float'
|
|
12
12
|
YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
|
|
13
13
|
|
|
14
|
-
yaml_as YAML_TAG
|
|
15
|
-
|
|
16
14
|
# This emits the number without any scientific notation.
|
|
17
15
|
# This is better than self.to_f.to_s since it doesn't lose precision.
|
|
18
16
|
#
|
|
@@ -80,13 +80,22 @@ class Class
|
|
|
80
80
|
remove_possible_method(:#{name})
|
|
81
81
|
define_method(:#{name}) { val }
|
|
82
82
|
end
|
|
83
|
+
|
|
84
|
+
if singleton_class?
|
|
85
|
+
class_eval do
|
|
86
|
+
remove_possible_method(:#{name})
|
|
87
|
+
def #{name}
|
|
88
|
+
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
83
92
|
val
|
|
84
93
|
end
|
|
85
94
|
|
|
86
95
|
if instance_reader
|
|
87
96
|
remove_possible_method :#{name}
|
|
88
97
|
def #{name}
|
|
89
|
-
defined?(@#{name}) ? @#{name} :
|
|
98
|
+
defined?(@#{name}) ? @#{name} : self.class.#{name}
|
|
90
99
|
end
|
|
91
100
|
|
|
92
101
|
def #{name}?
|
|
@@ -98,4 +107,9 @@ class Class
|
|
|
98
107
|
attr_writer name if instance_writer
|
|
99
108
|
end
|
|
100
109
|
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
def singleton_class?
|
|
113
|
+
!name || '' == name
|
|
114
|
+
end
|
|
101
115
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
require 'active_support/core_ext/object/duplicable'
|
|
2
2
|
require 'active_support/core_ext/array/extract_options'
|
|
3
|
+
require 'active_support/deprecation'
|
|
3
4
|
|
|
4
5
|
# Retained for backward compatibility. Methods are now included in Class.
|
|
5
6
|
module ClassInheritableAttributes # :nodoc:
|
|
7
|
+
DEPRECATION_WARNING_MESSAGE = "class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first"
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
# It is recommended to use <tt>class_attribute</tt> over methods defined in this file. Please
|
|
@@ -36,6 +38,7 @@ end
|
|
|
36
38
|
# Person.new.hair_colors # => NoMethodError
|
|
37
39
|
class Class # :nodoc:
|
|
38
40
|
def class_inheritable_reader(*syms)
|
|
41
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
|
39
42
|
options = syms.extract_options!
|
|
40
43
|
syms.each do |sym|
|
|
41
44
|
next if sym.is_a?(Hash)
|
|
@@ -54,6 +57,7 @@ class Class # :nodoc:
|
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
def class_inheritable_writer(*syms)
|
|
60
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
|
57
61
|
options = syms.extract_options!
|
|
58
62
|
syms.each do |sym|
|
|
59
63
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
@@ -71,6 +75,7 @@ class Class # :nodoc:
|
|
|
71
75
|
end
|
|
72
76
|
|
|
73
77
|
def class_inheritable_array_writer(*syms)
|
|
78
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
|
74
79
|
options = syms.extract_options!
|
|
75
80
|
syms.each do |sym|
|
|
76
81
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
@@ -88,6 +93,7 @@ class Class # :nodoc:
|
|
|
88
93
|
end
|
|
89
94
|
|
|
90
95
|
def class_inheritable_hash_writer(*syms)
|
|
96
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
|
91
97
|
options = syms.extract_options!
|
|
92
98
|
syms.each do |sym|
|
|
93
99
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
@@ -145,6 +151,7 @@ class Class # :nodoc:
|
|
|
145
151
|
end
|
|
146
152
|
|
|
147
153
|
def reset_inheritable_attributes
|
|
154
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
|
148
155
|
@inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
|
149
156
|
end
|
|
150
157
|
|
|
@@ -158,9 +165,9 @@ class Class # :nodoc:
|
|
|
158
165
|
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
|
159
166
|
new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
|
160
167
|
else
|
|
161
|
-
new_inheritable_attributes = inheritable_attributes.
|
|
162
|
-
|
|
163
|
-
end
|
|
168
|
+
new_inheritable_attributes = Hash[inheritable_attributes.map do |(key, value)|
|
|
169
|
+
[key, value.duplicable? ? value.dup : value]
|
|
170
|
+
end]
|
|
164
171
|
end
|
|
165
172
|
|
|
166
173
|
child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
|
|
@@ -169,86 +176,3 @@ class Class # :nodoc:
|
|
|
169
176
|
alias inherited_without_inheritable_attributes inherited
|
|
170
177
|
alias inherited inherited_with_inheritable_attributes
|
|
171
178
|
end
|
|
172
|
-
|
|
173
|
-
class Class
|
|
174
|
-
# Defines class-level inheritable attribute reader. Attributes are available to subclasses,
|
|
175
|
-
# each subclass has a copy of parent's attribute.
|
|
176
|
-
#
|
|
177
|
-
# @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
|
|
178
|
-
# @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
|
|
179
|
-
#
|
|
180
|
-
# @api public
|
|
181
|
-
#
|
|
182
|
-
# @todo Do we want to block instance_reader via :instance_reader => false
|
|
183
|
-
# @todo It would be preferable that we do something with a Hash passed in
|
|
184
|
-
# (error out or do the same as other methods above) instead of silently
|
|
185
|
-
# moving on). In particular, this makes the return value of this function
|
|
186
|
-
# less useful.
|
|
187
|
-
def extlib_inheritable_reader(*ivars, &block)
|
|
188
|
-
options = ivars.extract_options!
|
|
189
|
-
|
|
190
|
-
ivars.each do |ivar|
|
|
191
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
192
|
-
def self.#{ivar}
|
|
193
|
-
return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
|
|
194
|
-
ivar = superclass.#{ivar}
|
|
195
|
-
return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
|
|
196
|
-
@#{ivar} = ivar.duplicable? ? ivar.dup : ivar
|
|
197
|
-
end
|
|
198
|
-
RUBY
|
|
199
|
-
unless options[:instance_reader] == false
|
|
200
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
201
|
-
def #{ivar}
|
|
202
|
-
self.class.#{ivar}
|
|
203
|
-
end
|
|
204
|
-
RUBY
|
|
205
|
-
end
|
|
206
|
-
instance_variable_set(:"@#{ivar}", yield) if block_given?
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Defines class-level inheritable attribute writer. Attributes are available to subclasses,
|
|
211
|
-
# each subclass has a copy of parent's attribute.
|
|
212
|
-
#
|
|
213
|
-
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
214
|
-
# define inheritable writer for.
|
|
215
|
-
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
216
|
-
# @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
|
|
217
|
-
#
|
|
218
|
-
# @api public
|
|
219
|
-
#
|
|
220
|
-
# @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
|
|
221
|
-
# class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
|
|
222
|
-
def extlib_inheritable_writer(*ivars)
|
|
223
|
-
options = ivars.extract_options!
|
|
224
|
-
|
|
225
|
-
ivars.each do |ivar|
|
|
226
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
227
|
-
def self.#{ivar}=(obj)
|
|
228
|
-
@#{ivar} = obj
|
|
229
|
-
end
|
|
230
|
-
RUBY
|
|
231
|
-
unless options[:instance_writer] == false
|
|
232
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
233
|
-
def #{ivar}=(obj) self.class.#{ivar} = obj end
|
|
234
|
-
RUBY
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
self.send("#{ivar}=", yield) if block_given?
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
|
|
242
|
-
# each subclass has a copy of parent's attribute.
|
|
243
|
-
#
|
|
244
|
-
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
245
|
-
# define inheritable accessor for.
|
|
246
|
-
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
247
|
-
# @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
|
|
248
|
-
#
|
|
249
|
-
# @api public
|
|
250
|
-
def extlib_inheritable_accessor(*syms, &block)
|
|
251
|
-
extlib_inheritable_reader(*syms)
|
|
252
|
-
extlib_inheritable_writer(*syms, &block)
|
|
253
|
-
end
|
|
254
|
-
end
|
|
@@ -2,49 +2,35 @@ require 'active_support/core_ext/module/anonymous'
|
|
|
2
2
|
require 'active_support/core_ext/module/reachable'
|
|
3
3
|
|
|
4
4
|
class Class #:nodoc:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
alias :subclasses :__subclasses__
|
|
5
|
+
begin
|
|
6
|
+
ObjectSpace.each_object(Class.new) {}
|
|
8
7
|
|
|
9
8
|
def descendants
|
|
10
9
|
descendants = []
|
|
11
|
-
|
|
12
|
-
descendants
|
|
13
|
-
descendants.concat k.descendants
|
|
10
|
+
ObjectSpace.each_object(class << self; self; end) do |k|
|
|
11
|
+
descendants.unshift k unless k == self
|
|
14
12
|
end
|
|
15
13
|
descendants
|
|
16
14
|
end
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
descendants = []
|
|
23
|
-
ObjectSpace.each_object(class << self; self; end) do |k|
|
|
24
|
-
descendants.unshift k unless k == self
|
|
25
|
-
end
|
|
26
|
-
descendants
|
|
27
|
-
end
|
|
28
|
-
rescue StandardError # JRuby
|
|
29
|
-
def descendants
|
|
30
|
-
descendants = []
|
|
31
|
-
ObjectSpace.each_object(Class) do |k|
|
|
32
|
-
descendants.unshift k if k < self
|
|
33
|
-
end
|
|
34
|
-
descendants.uniq!
|
|
35
|
-
descendants
|
|
15
|
+
rescue StandardError # JRuby
|
|
16
|
+
def descendants
|
|
17
|
+
descendants = []
|
|
18
|
+
ObjectSpace.each_object(Class) do |k|
|
|
19
|
+
descendants.unshift k if k < self
|
|
36
20
|
end
|
|
21
|
+
descendants.uniq!
|
|
22
|
+
descendants
|
|
37
23
|
end
|
|
24
|
+
end
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
subclasses
|
|
26
|
+
# Returns an array with the direct children of +self+.
|
|
27
|
+
#
|
|
28
|
+
# Integer.subclasses # => [Bignum, Fixnum]
|
|
29
|
+
def subclasses
|
|
30
|
+
subclasses, chain = [], descendants
|
|
31
|
+
chain.each do |k|
|
|
32
|
+
subclasses << k unless chain.any? { |c| c > k }
|
|
48
33
|
end
|
|
34
|
+
subclasses
|
|
49
35
|
end
|
|
50
36
|
end
|
|
@@ -5,6 +5,8 @@ require 'active_support/core_ext/date/zones'
|
|
|
5
5
|
require 'active_support/core_ext/time/zones'
|
|
6
6
|
|
|
7
7
|
class Date
|
|
8
|
+
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
|
|
9
|
+
|
|
8
10
|
if RUBY_VERSION < '1.9'
|
|
9
11
|
undef :>>
|
|
10
12
|
|
|
@@ -127,6 +129,11 @@ class Date
|
|
|
127
129
|
)
|
|
128
130
|
end
|
|
129
131
|
|
|
132
|
+
# Returns a new Date/DateTime representing the time a number of specified weeks ago.
|
|
133
|
+
def weeks_ago(weeks)
|
|
134
|
+
advance(:weeks => -weeks)
|
|
135
|
+
end
|
|
136
|
+
|
|
130
137
|
# Returns a new Date/DateTime representing the time a number of specified months ago.
|
|
131
138
|
def months_ago(months)
|
|
132
139
|
advance(:months => -months)
|
|
@@ -185,16 +192,21 @@ class Date
|
|
|
185
192
|
alias :sunday :end_of_week
|
|
186
193
|
alias :at_end_of_week :end_of_week
|
|
187
194
|
|
|
195
|
+
# Returns a new Date/DateTime representing the start of the given day in the previous week (default is Monday).
|
|
196
|
+
def prev_week(day = :monday)
|
|
197
|
+
result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
|
|
198
|
+
self.acts_like?(:time) ? result.change(:hour => 0) : result
|
|
199
|
+
end
|
|
200
|
+
|
|
188
201
|
# Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
|
|
189
202
|
def next_week(day = :monday)
|
|
190
|
-
|
|
191
|
-
result = (self + 7).beginning_of_week + days_into_week[day]
|
|
203
|
+
result = (self + 7).beginning_of_week + DAYS_INTO_WEEK[day]
|
|
192
204
|
self.acts_like?(:time) ? result.change(:hour => 0) : result
|
|
193
205
|
end
|
|
194
206
|
|
|
195
207
|
# Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00)
|
|
196
208
|
def beginning_of_month
|
|
197
|
-
self.acts_like?(:time) ? change(:day => 1
|
|
209
|
+
self.acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1)
|
|
198
210
|
end
|
|
199
211
|
alias :at_beginning_of_month :beginning_of_month
|
|
200
212
|
|
|
@@ -219,13 +231,13 @@ class Date
|
|
|
219
231
|
|
|
220
232
|
# Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
|
|
221
233
|
def beginning_of_year
|
|
222
|
-
self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0
|
|
234
|
+
self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0) : change(:month => 1, :day => 1)
|
|
223
235
|
end
|
|
224
236
|
alias :at_beginning_of_year :beginning_of_year
|
|
225
237
|
|
|
226
238
|
# Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59)
|
|
227
239
|
def end_of_year
|
|
228
|
-
self.acts_like?(:time) ? change(:month => 12
|
|
240
|
+
self.acts_like?(:time) ? change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31)
|
|
229
241
|
end
|
|
230
242
|
alias :at_end_of_year :end_of_year
|
|
231
243
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'date'
|
|
2
2
|
require 'active_support/inflector/methods'
|
|
3
3
|
require 'active_support/core_ext/date/zones'
|
|
4
|
+
require 'active_support/core_ext/module/remove_method'
|
|
4
5
|
|
|
5
6
|
class Date
|
|
6
7
|
DATE_FORMATS = {
|
|
@@ -13,10 +14,10 @@ class Date
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
# Ruby 1.9 has Date#to_time which converts to localtime only.
|
|
16
|
-
|
|
17
|
+
remove_possible_method :to_time
|
|
17
18
|
|
|
18
19
|
# Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
|
|
19
|
-
|
|
20
|
+
remove_possible_method :xmlschema
|
|
20
21
|
|
|
21
22
|
# Convert to a formatted string. See DATE_FORMATS for predefined formats.
|
|
22
23
|
#
|
|
@@ -93,6 +94,12 @@ class Date
|
|
|
93
94
|
::DateTime.civil(year, month, day, 0, 0, 0, 0)
|
|
94
95
|
end if RUBY_VERSION < '1.9'
|
|
95
96
|
|
|
97
|
+
def iso8601
|
|
98
|
+
strftime('%F')
|
|
99
|
+
end if RUBY_VERSION < '1.9'
|
|
100
|
+
|
|
101
|
+
alias_method :rfc3339, :iso8601 if RUBY_VERSION < '1.9'
|
|
102
|
+
|
|
96
103
|
def xmlschema
|
|
97
104
|
to_time_in_current_zone.xmlschema
|
|
98
105
|
end
|