activesupport 3.0.20 → 3.1.0.beta1
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.
- data/CHANGELOG +14 -66
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/buffered_logger.rb +4 -11
- data/lib/active_support/cache.rb +12 -15
- data/lib/active_support/cache/file_store.rb +3 -2
- data/lib/active_support/cache/mem_cache_store.rb +11 -3
- data/lib/active_support/cache/strategy/local_cache.rb +28 -23
- data/lib/active_support/callbacks.rb +195 -175
- data/lib/active_support/concern.rb +105 -35
- data/lib/active_support/configurable.rb +41 -2
- data/lib/active_support/core_ext/array/access.rb +2 -2
- data/lib/active_support/core_ext/array/random_access.rb +10 -7
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/attribute.rb +27 -17
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +12 -86
- data/lib/active_support/core_ext/class/subclasses.rb +20 -34
- data/lib/active_support/core_ext/date/calculations.rb +14 -2
- data/lib/active_support/core_ext/date/conversions.rb +6 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
- data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
- data/lib/active_support/core_ext/date_time/zones.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +2 -5
- data/lib/active_support/core_ext/float/rounding.rb +1 -1
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/hash/conversions.rb +23 -36
- data/lib/active_support/core_ext/hash/deep_dup.rb +11 -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/kernel/reporting.rb +19 -0
- data/lib/active_support/core_ext/logger.rb +11 -38
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +11 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/object/blank.rb +42 -9
- data/lib/active_support/core_ext/object/duplicable.rb +48 -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 +27 -10
- data/lib/active_support/core_ext/object/with_options.rb +19 -5
- data/lib/active_support/core_ext/range.rb +1 -0
- data/lib/active_support/core_ext/range/cover.rb +3 -0
- data/lib/active_support/core_ext/string.rb +1 -0
- 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 +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +33 -89
- data/lib/active_support/core_ext/time/calculations.rb +14 -13
- data/lib/active_support/core_ext/time/conversions.rb +2 -24
- data/lib/active_support/core_ext/time/marshal.rb +0 -1
- 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 +93 -37
- data/lib/active_support/deprecation.rb +2 -2
- 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/duration.rb +4 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/file_watcher.rb +36 -0
- data/lib/active_support/gzip.rb +0 -1
- data/lib/active_support/hash_with_indifferent_access.rb +6 -4
- data/lib/active_support/i18n.rb +0 -1
- data/lib/active_support/i18n_railtie.rb +2 -2
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/json/decoding.rb +37 -23
- data/lib/active_support/json/encoding.rb +8 -3
- data/lib/active_support/lazy_load_hooks.rb +7 -7
- data/lib/active_support/log_subscriber.rb +3 -3
- data/lib/active_support/log_subscriber/test_helper.rb +4 -3
- 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 +4 -3
- data/lib/active_support/multibyte/unicode.rb +1 -1
- data/lib/active_support/notifications.rb +9 -8
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/ordered_hash.rb +19 -2
- data/lib/active_support/ordered_options.rb +33 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/rescuable.rb +1 -0
- data/lib/active_support/secure_random.rb +11 -5
- data/lib/active_support/test_case.rb +2 -10
- data/lib/active_support/testing/assertions.rb +17 -6
- data/lib/active_support/testing/mochaing.rb +7 -0
- data/lib/active_support/testing/pending.rb +27 -23
- 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/version.rb +3 -3
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini.rb +4 -2
- data/lib/active_support/xml_mini/jdom.rb +9 -16
- 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
- metadata +50 -32
- checksums.yaml +0 -7
- data/lib/active_support/core_ext/cgi.rb +0 -1
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
- 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", [])
|
@@ -4,12 +4,34 @@ require 'active_support/core_ext/kernel/singleton_class'
|
|
4
4
|
require 'active_support/core_ext/module/delegation'
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
|
+
# Configurable provides a <tt>config</tt> method to store and retrieve
|
8
|
+
# configuration options as an <tt>OrderedHash</tt>.
|
7
9
|
module Configurable
|
8
10
|
extend ActiveSupport::Concern
|
9
11
|
|
12
|
+
class Configuration < ActiveSupport::InheritableOptions
|
13
|
+
def compile_methods!
|
14
|
+
self.class.compile_methods!(keys.reject {|key| respond_to?(key)})
|
15
|
+
end
|
16
|
+
|
17
|
+
# compiles reader methods so we don't have to go through method_missing
|
18
|
+
def self.compile_methods!(keys)
|
19
|
+
keys.each do |key|
|
20
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
21
|
+
def #{key}; _get(#{key.inspect}); end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
10
27
|
module ClassMethods
|
11
28
|
def config
|
12
|
-
@_config ||=
|
29
|
+
@_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
|
30
|
+
superclass.config.inheritable_copy
|
31
|
+
else
|
32
|
+
# create a new "anonymous" class that will host the compiled reader methods
|
33
|
+
Class.new(Configuration).new
|
34
|
+
end
|
13
35
|
end
|
14
36
|
|
15
37
|
def configure
|
@@ -41,8 +63,25 @@ module ActiveSupport
|
|
41
63
|
end
|
42
64
|
end
|
43
65
|
|
66
|
+
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
|
67
|
+
#
|
68
|
+
# require 'active_support/configurable'
|
69
|
+
#
|
70
|
+
# class User
|
71
|
+
# include ActiveSupport::Configurable
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# user = User.new
|
75
|
+
#
|
76
|
+
# user.config.allowed_access = true
|
77
|
+
# user.config.level = 1
|
78
|
+
#
|
79
|
+
# user.config.allowed_access # => true
|
80
|
+
# user.config.level # => 1
|
81
|
+
#
|
44
82
|
def config
|
45
|
-
@_config ||=
|
83
|
+
@_config ||= self.class.config.inheritable_copy
|
46
84
|
end
|
47
85
|
end
|
48
86
|
end
|
87
|
+
|
@@ -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+.
|
@@ -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 sample number
|
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
|
@@ -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
|
#
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/kernel/singleton_class'
|
2
2
|
require 'active_support/core_ext/module/remove_method'
|
3
|
-
require 'active_support/core_ext/array/extract_options'
|
4
3
|
|
5
4
|
class Class
|
6
5
|
# Declare a class-level attribute whose value is inheritable by subclasses.
|
@@ -57,18 +56,11 @@ class Class
|
|
57
56
|
# object.setting # => false
|
58
57
|
# Base.setting # => true
|
59
58
|
#
|
60
|
-
# To opt out of the instance reader method, pass :instance_reader => false.
|
61
|
-
#
|
62
|
-
# object.setting # => NoMethodError
|
63
|
-
# object.setting? # => NoMethodError
|
64
|
-
#
|
65
59
|
# To opt out of the instance writer method, pass :instance_writer => false.
|
66
60
|
#
|
67
61
|
# object.setting = false # => NoMethodError
|
68
62
|
def class_attribute(*attrs)
|
69
|
-
|
70
|
-
instance_reader = options.fetch(:instance_reader, true)
|
71
|
-
instance_writer = options.fetch(:instance_writer, true)
|
63
|
+
instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
|
72
64
|
|
73
65
|
attrs.each do |name|
|
74
66
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -80,22 +72,40 @@ class Class
|
|
80
72
|
remove_possible_method(:#{name})
|
81
73
|
define_method(:#{name}) { val }
|
82
74
|
end
|
75
|
+
|
76
|
+
if singleton_class?
|
77
|
+
class_eval do
|
78
|
+
remove_possible_method(:#{name})
|
79
|
+
def #{name}
|
80
|
+
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
83
84
|
val
|
84
85
|
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
87
|
+
remove_possible_method :#{name}
|
88
|
+
def #{name}
|
89
|
+
defined?(@#{name}) ? @#{name} : self.class.#{name}
|
90
|
+
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
end
|
92
|
+
def #{name}?
|
93
|
+
!!#{name}
|
95
94
|
end
|
96
95
|
RUBY
|
97
96
|
|
98
97
|
attr_writer name if instance_writer
|
99
98
|
end
|
100
99
|
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def singleton_class?
|
103
|
+
# in case somebody is crazy enough to overwrite allocate
|
104
|
+
allocate = Class.instance_method(:allocate)
|
105
|
+
# object.class always points to a real (non-singleton) class
|
106
|
+
allocate.bind(self).call.class != self
|
107
|
+
rescue TypeError
|
108
|
+
# MRI/YARV/JRuby all disallow creating new instances of a singleton class
|
109
|
+
true
|
110
|
+
end
|
101
111
|
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)
|
@@ -124,6 +130,7 @@ class Class # :nodoc:
|
|
124
130
|
end
|
125
131
|
|
126
132
|
def write_inheritable_attribute(key, value)
|
133
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
127
134
|
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
128
135
|
@inheritable_attributes = {}
|
129
136
|
end
|
@@ -141,10 +148,12 @@ class Class # :nodoc:
|
|
141
148
|
end
|
142
149
|
|
143
150
|
def read_inheritable_attribute(key)
|
151
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
144
152
|
inheritable_attributes[key]
|
145
153
|
end
|
146
154
|
|
147
155
|
def reset_inheritable_attributes
|
156
|
+
ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
|
148
157
|
@inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
149
158
|
end
|
150
159
|
|
@@ -158,9 +167,9 @@ class Class # :nodoc:
|
|
158
167
|
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
159
168
|
new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
160
169
|
else
|
161
|
-
new_inheritable_attributes = inheritable_attributes.
|
162
|
-
|
163
|
-
end
|
170
|
+
new_inheritable_attributes = Hash[inheritable_attributes.map do |(key, value)|
|
171
|
+
[key, value.duplicable? ? value.dup : value]
|
172
|
+
end]
|
164
173
|
end
|
165
174
|
|
166
175
|
child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
|
@@ -169,86 +178,3 @@ class Class # :nodoc:
|
|
169
178
|
alias inherited_without_inheritable_attributes inherited
|
170
179
|
alias inherited inherited_with_inheritable_attributes
|
171
180
|
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
|