diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index 7baba75ad3..0d4033329e 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -56,11 +56,22 @@ class Class # object.setting # => false # Base.setting # => true # + # To opt out of the instance reader method, pass :instance_reader => false. + # + # object.setting # => NoMethodError + # object.setting? # => NoMethodError + # # 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] + instance_reader = true + instance_writer = true + if attrs.last.is_a?(Hash) + instance_accessors = attrs.pop + instance_reader = instance_accessors[:instance_reader] + instance_writer = instance_accessors[:instance_writer] + end attrs.each do |name| class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -84,13 +95,15 @@ class Class val end - remove_possible_method :#{name} - def #{name} - defined?(@#{name}) ? @#{name} : self.class.#{name} - end + if instance_reader + remove_possible_method :#{name} + def #{name} + defined?(@#{name}) ? @#{name} : self.class.#{name} + end - def #{name}? - !!#{name} + def #{name}? + !!#{name} + end end RUBY diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb index d58b60482b..e290a6e012 100644 --- a/activesupport/test/core_ext/class/attribute_test.rb +++ b/activesupport/test/core_ext/class/attribute_test.rb @@ -60,6 +60,12 @@ class ClassAttributeTest < ActiveSupport::TestCase assert_raise(NoMethodError) { object.setting = 'boom' } end + test 'disabling instance reader' do + object = Class.new { class_attribute :setting, :instance_reader => false }.new + assert_raise(NoMethodError) { object.setting } + assert_raise(NoMethodError) { object.setting? } + end + test 'works well with singleton classes' do object = @klass.new object.singleton_class.setting = 'foo'