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.

Files changed (110) hide show
  1. data/CHANGELOG +14 -66
  2. data/README.rdoc +1 -1
  3. data/lib/active_support/backtrace_cleaner.rb +1 -1
  4. data/lib/active_support/buffered_logger.rb +4 -11
  5. data/lib/active_support/cache.rb +12 -15
  6. data/lib/active_support/cache/file_store.rb +3 -2
  7. data/lib/active_support/cache/mem_cache_store.rb +11 -3
  8. data/lib/active_support/cache/strategy/local_cache.rb +28 -23
  9. data/lib/active_support/callbacks.rb +195 -175
  10. data/lib/active_support/concern.rb +105 -35
  11. data/lib/active_support/configurable.rb +41 -2
  12. data/lib/active_support/core_ext/array/access.rb +2 -2
  13. data/lib/active_support/core_ext/array/random_access.rb +10 -7
  14. data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
  15. data/lib/active_support/core_ext/class/attribute.rb +27 -17
  16. data/lib/active_support/core_ext/class/inheritable_attributes.rb +12 -86
  17. data/lib/active_support/core_ext/class/subclasses.rb +20 -34
  18. data/lib/active_support/core_ext/date/calculations.rb +14 -2
  19. data/lib/active_support/core_ext/date/conversions.rb +6 -0
  20. data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
  21. data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
  22. data/lib/active_support/core_ext/date_time/zones.rb +1 -1
  23. data/lib/active_support/core_ext/enumerable.rb +2 -5
  24. data/lib/active_support/core_ext/float/rounding.rb +1 -1
  25. data/lib/active_support/core_ext/hash.rb +1 -0
  26. data/lib/active_support/core_ext/hash/conversions.rb +23 -36
  27. data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
  28. data/lib/active_support/core_ext/hash/keys.rb +6 -4
  29. data/lib/active_support/core_ext/hash/reverse_merge.rb +9 -14
  30. data/lib/active_support/core_ext/kernel/reporting.rb +19 -0
  31. data/lib/active_support/core_ext/logger.rb +11 -38
  32. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +11 -12
  33. data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
  34. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  35. data/lib/active_support/core_ext/object.rb +1 -1
  36. data/lib/active_support/core_ext/object/blank.rb +42 -9
  37. data/lib/active_support/core_ext/object/duplicable.rb +48 -9
  38. data/lib/active_support/core_ext/object/inclusion.rb +15 -0
  39. data/lib/active_support/core_ext/object/instance_variables.rb +1 -35
  40. data/lib/active_support/core_ext/object/to_param.rb +13 -8
  41. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  42. data/lib/active_support/core_ext/object/try.rb +27 -10
  43. data/lib/active_support/core_ext/object/with_options.rb +19 -5
  44. data/lib/active_support/core_ext/range.rb +1 -0
  45. data/lib/active_support/core_ext/range/cover.rb +3 -0
  46. data/lib/active_support/core_ext/string.rb +1 -0
  47. data/lib/active_support/core_ext/string/filters.rb +3 -3
  48. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  49. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  50. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  51. data/lib/active_support/core_ext/string/output_safety.rb +33 -89
  52. data/lib/active_support/core_ext/time/calculations.rb +14 -13
  53. data/lib/active_support/core_ext/time/conversions.rb +2 -24
  54. data/lib/active_support/core_ext/time/marshal.rb +0 -1
  55. data/lib/active_support/core_ext/time/zones.rb +32 -21
  56. data/lib/active_support/core_ext/uri.rb +8 -0
  57. data/lib/active_support/dependencies.rb +93 -37
  58. data/lib/active_support/deprecation.rb +2 -2
  59. data/lib/active_support/deprecation/behaviors.rb +7 -0
  60. data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
  61. data/lib/active_support/deprecation/reporting.rb +4 -0
  62. data/lib/active_support/duration.rb +4 -0
  63. data/lib/active_support/file_update_checker.rb +1 -1
  64. data/lib/active_support/file_watcher.rb +36 -0
  65. data/lib/active_support/gzip.rb +0 -1
  66. data/lib/active_support/hash_with_indifferent_access.rb +6 -4
  67. data/lib/active_support/i18n.rb +0 -1
  68. data/lib/active_support/i18n_railtie.rb +2 -2
  69. data/lib/active_support/inflector/inflections.rb +1 -1
  70. data/lib/active_support/json/decoding.rb +37 -23
  71. data/lib/active_support/json/encoding.rb +8 -3
  72. data/lib/active_support/lazy_load_hooks.rb +7 -7
  73. data/lib/active_support/log_subscriber.rb +3 -3
  74. data/lib/active_support/log_subscriber/test_helper.rb +4 -3
  75. data/lib/active_support/message_encryptor.rb +1 -1
  76. data/lib/active_support/message_verifier.rb +1 -1
  77. data/lib/active_support/multibyte/chars.rb +4 -3
  78. data/lib/active_support/multibyte/unicode.rb +1 -1
  79. data/lib/active_support/notifications.rb +9 -8
  80. data/lib/active_support/notifications/fanout.rb +3 -3
  81. data/lib/active_support/ordered_hash.rb +19 -2
  82. data/lib/active_support/ordered_options.rb +33 -3
  83. data/lib/active_support/railtie.rb +1 -1
  84. data/lib/active_support/rescuable.rb +1 -0
  85. data/lib/active_support/secure_random.rb +11 -5
  86. data/lib/active_support/test_case.rb +2 -10
  87. data/lib/active_support/testing/assertions.rb +17 -6
  88. data/lib/active_support/testing/mochaing.rb +7 -0
  89. data/lib/active_support/testing/pending.rb +27 -23
  90. data/lib/active_support/testing/setup_and_teardown.rb +8 -11
  91. data/lib/active_support/time_with_zone.rb +6 -3
  92. data/lib/active_support/version.rb +3 -3
  93. data/lib/active_support/whiny_nil.rb +1 -1
  94. data/lib/active_support/xml_mini.rb +4 -2
  95. data/lib/active_support/xml_mini/jdom.rb +9 -16
  96. data/lib/active_support/xml_mini/libxml.rb +1 -0
  97. data/lib/active_support/xml_mini/libxmlsax.rb +2 -1
  98. data/lib/active_support/xml_mini/nokogiri.rb +1 -0
  99. data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
  100. data/lib/active_support/xml_mini/rexml.rb +1 -0
  101. metadata +50 -32
  102. checksums.yaml +0 -7
  103. data/lib/active_support/core_ext/cgi.rb +0 -1
  104. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
  105. data/lib/active_support/core_ext/object/returning.rb +0 -43
  106. data/lib/active_support/json/backends/jsongem.rb +0 -47
  107. data/lib/active_support/json/backends/okjson.rb +0 -644
  108. data/lib/active_support/json/backends/yajl.rb +0 -44
  109. data/lib/active_support/json/backends/yaml.rb +0 -19
  110. 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 ||= ActiveSupport::InheritableOptions.new(superclass.respond_to?(:config) ? superclass.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 ||= ActiveSupport::InheritableOptions.new(self.class.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) # => nil
6
+ # %w( a b c d ).from(10) # => %w()
7
7
  # %w().from(0) # => %w()
8
8
  def from(position)
9
- self[position..-1]
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 http://github.com/marcandre/backports/
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>. if +n+ is passed, returns <tt>[]</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 # => 4
7
- # [1,2,3,4,5,6].sample(3) # => [2, 4, 5]
8
- # [].sample # => nil
9
- # [].sample(3) # => []
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
- options = attrs.extract_options!
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
- if instance_reader
87
- remove_possible_method :#{name}
88
- def #{name}
89
- defined?(@#{name}) ? @#{name} : singleton_class.#{name}
90
- end
87
+ remove_possible_method :#{name}
88
+ def #{name}
89
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
90
+ end
91
91
 
92
- def #{name}?
93
- !!#{name}
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.inject({}) do |memo, (key, value)|
162
- memo.update(key => value.duplicable? ? value.dup : value)
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