Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #6638 from frodsan/config_accessor
Browse files Browse the repository at this point in the history
add instance_accessor option to config_accessor
  • Loading branch information
rafaelfranca committed Jun 5, 2012
2 parents 8359a2f + 5e1d40f commit 5b3d140
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 9 deletions.
12 changes: 12 additions & 0 deletions activesupport/CHANGELOG.md
@@ -1,5 +1,17 @@
## Rails 4.0.0 (unreleased) ## ## Rails 4.0.0 (unreleased) ##


* Add `:instance_accessor` option for `config_accessor`.

class User
include ActiveSupport::Configurable
config_accessor :allowed_access, instance_accessor: false
end

User.new.allowed_access = true # => NoMethodError
User.new.allowed_access # => NoMethodError

*Francesco Rodriguez*

* ActionView::Helpers::NumberHelper methods have been moved to ActiveSupport::NumberHelper and are now available via * ActionView::Helpers::NumberHelper methods have been moved to ActiveSupport::NumberHelper and are now available via
Numeric#to_s. Numeric#to_s now accepts the formatting options :phone, :currency, :percentage, :delimited, Numeric#to_s. Numeric#to_s now accepts the formatting options :phone, :currency, :percentage, :delimited,
:rounded, :human, and :human_size. *Andrew Mutz* :rounded, :human, and :human_size. *Andrew Mutz*
Expand Down
57 changes: 52 additions & 5 deletions activesupport/lib/active_support/configurable.rb
Expand Up @@ -37,29 +37,77 @@ def configure
yield config yield config
end end


# Allows you to add shortcut so that you don't have to refer to attribute through config. # Allows you to add shortcut so that you don't have to refer to attribute
# Also look at the example for config to contrast. # through config. Also look at the example for config to contrast.
#
# Defines both class and instance config accessors.
# #
# class User # class User
# include ActiveSupport::Configurable # include ActiveSupport::Configurable
# config_accessor :allowed_access # config_accessor :allowed_access
# end # end
# #
# User.allowed_access # => nil
# User.allowed_access = false
# User.allowed_access # => false
#
# user = User.new # user = User.new
# user.allowed_access # => false
# user.allowed_access = true # user.allowed_access = true
# user.allowed_access # => true # user.allowed_access # => true
# #
# User.allowed_access # => false
#
# The attribute name must be a valid method name in Ruby.
#
# class User
# include ActiveSupport::Configurable
# config_accessor :"1_Badname"
# end
# # => NameError: invalid config attribute name
#
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
#
# class User
# include ActiveSupport::Configurable
# config_accessor :allowed_access, instance_reader: false, instance_writer: false
# end
#
# User.allowed_access = false
#  User.allowed_access # => false
#
# User.new.allowed_access = true # => NoMethodError
# User.new.allowed_access # => NoMethodError
#
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
#
# class User
# include ActiveSupport::Configurable
# config_accessor :allowed_access, instance_accessor: false
# end
#
# User.allowed_access = false
#  User.allowed_access # => false
#
# User.new.allowed_access = true # => NoMethodError
# User.new.allowed_access # => NoMethodError
def config_accessor(*names) def config_accessor(*names)
options = names.extract_options! options = names.extract_options!


names.each do |name| names.each do |name|
raise NameError.new('invalid config attribute name') unless name =~ /^[_A-Za-z]\w*$/

reader, line = "def #{name}; config.#{name}; end", __LINE__ reader, line = "def #{name}; config.#{name}; end", __LINE__
writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__ writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__


singleton_class.class_eval reader, __FILE__, line singleton_class.class_eval reader, __FILE__, line
singleton_class.class_eval writer, __FILE__, line singleton_class.class_eval writer, __FILE__, line
class_eval reader, __FILE__, line unless options[:instance_reader] == false
class_eval writer, __FILE__, line unless options[:instance_writer] == false unless options[:instance_accessor] == false
class_eval reader, __FILE__, line unless options[:instance_reader] == false
class_eval writer, __FILE__, line unless options[:instance_writer] == false
end
end end
end end
end end
Expand All @@ -79,7 +127,6 @@ def config_accessor(*names)
# #
# user.config.allowed_access # => true # user.config.allowed_access # => true
# user.config.level # => 1 # user.config.level # => 1
#
def config def config
@_config ||= self.class.config.inheritable_copy @_config ||= self.class.config.inheritable_copy
end end
Expand Down
22 changes: 18 additions & 4 deletions activesupport/test/configurable_test.rb
Expand Up @@ -5,7 +5,8 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase
class Parent class Parent
include ActiveSupport::Configurable include ActiveSupport::Configurable
config_accessor :foo config_accessor :foo
config_accessor :bar, :instance_reader => false, :instance_writer => false config_accessor :bar, instance_reader: false, instance_writer: false
config_accessor :baz, instance_accessor: false
end end


class Child < Parent class Child < Parent
Expand All @@ -19,13 +20,13 @@ class Child < Parent
end end


test "adds a configuration hash" do test "adds a configuration hash" do
assert_equal({ :foo => :bar }, Parent.config) assert_equal({ foo: :bar }, Parent.config)
end end


test "adds a configuration hash to a module as well" do test "adds a configuration hash to a module as well" do
mixin = Module.new { include ActiveSupport::Configurable } mixin = Module.new { include ActiveSupport::Configurable }
mixin.config.foo = :bar mixin.config.foo = :bar
assert_equal({ :foo => :bar }, mixin.config) assert_equal({ foo: :bar }, mixin.config)
end end


test "configuration hash is inheritable" do test "configuration hash is inheritable" do
Expand All @@ -39,8 +40,12 @@ class Child < Parent


test "configuration accessors is not available on instance" do test "configuration accessors is not available on instance" do
instance = Parent.new instance = Parent.new

assert !instance.respond_to?(:bar) assert !instance.respond_to?(:bar)
assert !instance.respond_to?(:bar=) assert !instance.respond_to?(:bar=)

assert !instance.respond_to?(:baz)
assert !instance.respond_to?(:baz=)
end end


test "configuration hash is available on instance" do test "configuration hash is available on instance" do
Expand Down Expand Up @@ -71,6 +76,15 @@ class Child < Parent
assert_method_defined child.new.config, :bar assert_method_defined child.new.config, :bar
end end


test "should raise name error if attribute name is invalid" do
assert_raises NameError do
Class.new do
include ActiveSupport::Configurable
config_accessor "invalid attribute name"
end
end
end

def assert_method_defined(object, method) def assert_method_defined(object, method)
methods = object.public_methods.map(&:to_s) methods = object.public_methods.map(&:to_s)
assert methods.include?(method.to_s), "Expected #{methods.inspect} to include #{method.to_s.inspect}" assert methods.include?(method.to_s), "Expected #{methods.inspect} to include #{method.to_s.inspect}"
Expand All @@ -80,4 +94,4 @@ def assert_method_not_defined(object, method)
methods = object.public_methods.map(&:to_s) methods = object.public_methods.map(&:to_s)
assert !methods.include?(method.to_s), "Expected #{methods.inspect} to not include #{method.to_s.inspect}" assert !methods.include?(method.to_s), "Expected #{methods.inspect} to not include #{method.to_s.inspect}"
end end
end end

0 comments on commit 5b3d140

Please sign in to comment.