提交 60bbf16b 编写于 作者: J Jeremy Kemper

class_attribute gets instance methods which delegate to but may override their...

class_attribute gets instance methods which delegate to but may override their class values as you'd expect. Disable instance writer methods with :instance_writer => false.
上级 47d252f9
......@@ -24,14 +24,35 @@ class Class
# For convenience, a query method is defined as well:
#
# Subclass.setting? # => false
#
# Instances may overwrite the class value in the same way:
#
# Base.setting = true
# object = Base.new
# object.setting # => true
# object.setting = false
# object.setting # => false
# Base.setting # => true
#
# To opt out of the instance writer method, pass :instance_writer => false.
#
# object.setting = false # => NoMethodError
def class_attribute(*attrs)
instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
s = singleton_class
attrs.each do |attr|
s.send(:define_method, attr) { }
s.send(:define_method, "#{attr}?") { !!send(attr) }
s.send(:define_method, "#{attr}=") do |value|
s.send(:define_method, :"#{attr}?") { !!send(attr) }
s.send(:define_method, :"#{attr}=") do |value|
singleton_class.send(:define_method, attr) { value }
end
define_method(attr) { self.class.send(attr) }
define_method(:"#{attr}?") { !!send(attr) }
define_method(:"#{attr}=") do |value|
singleton_class.send(:define_method, attr) { value }
end if instance_writer
end
end
end
......@@ -2,13 +2,6 @@
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)
......@@ -40,8 +33,30 @@ def setup
assert_equal true, @klass.setting?
end
test 'no instance delegates' do
assert_raise(NoMethodError) { @klass.new.setting }
assert_raise(NoMethodError) { @klass.new.setting? }
test 'instance reader delegates to class' do
assert_nil @klass.new.setting
@klass.setting = 1
assert_equal 1, @klass.new.setting
end
test 'instance override' do
object = @klass.new
object.setting = 1
assert_nil @klass.setting
@klass.setting = 2
assert_equal 1, object.setting
end
test 'instance query' do
object = @klass.new
assert_equal false, object.setting?
object.setting = 1
assert_equal true, object.setting?
end
test 'disabling instance writer' do
object = Class.new { class_attribute :setting, :instance_writer => false }.new
assert_raise(NoMethodError) { object.setting = 'boom' }
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册