提交 8ae25a8e 编写于 作者: J Jeremy Kemper

Introduce class_attribute to declare inheritable class attributes. Writing an...

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.
上级 20923516
*Rails 3.0 (pending)*
* 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]
* Time#- with a DateTime argument behaves the same as with a Time argument, i.e. returns the difference between self and arg as a Float #3476 [Geoff Buesing]
* YAML serialization for OrderedHash. #3608 [Gregor Schmidt]
......
require 'active_support/core_ext/object/metaclass'
require 'active_support/core_ext/module/delegation'
class Class
# Declare a class-level attribute whose value is inheritable and
# overwritable by subclasses:
#
# class Base
# class_attribute :setting
# end
#
# class Subclass < Base
# end
#
# Base.setting = true
# Subclass.setting # => true
# Subclass.setting = false
# Subclass.setting # => false
# Base.setting # => true
#
# This matches normal Ruby method inheritance: think of writing an attribute
# on a subclass as overriding the reader method.
#
# For convenience, a query method is defined as well:
#
# Subclass.setting? # => false
def class_attribute(*attrs)
attrs.each do |attr|
metaclass.send(:define_method, attr) { }
metaclass.send(:define_method, "#{attr}?") { !!send(attr) }
metaclass.send(:define_method, "#{attr}=") do |value|
metaclass.send(:define_method, attr) { value }
end
end
end
end
require 'abstract_unit'
require 'active_support/core_ext/class/attribute'
class ClassAttributeTest < ActiveSupport::TestCase
class Base
class_attribute :setting
end
class Subclass < Base
end
def setup
@klass = Class.new { class_attribute :setting }
@sub = Class.new(@klass)
end
test 'defaults to nil' do
assert_nil @klass.setting
assert_nil @sub.setting
end
test 'inheritable' do
@klass.setting = 1
assert_equal 1, @sub.setting
end
test 'overridable' do
@sub.setting = 1
assert_nil @klass.setting
@klass.setting = 2
assert_equal 1, @sub.setting
assert_equal 1, Class.new(@sub).setting
end
test 'query method' do
assert_equal false, @klass.setting?
@klass.setting = 1
assert_equal true, @klass.setting?
end
test 'no instance delegates' do
assert_raise(NoMethodError) { @klass.new.setting }
assert_raise(NoMethodError) { @klass.new.setting? }
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册