1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activesupport/lib/active_support/configurable.rb
Francesco Rodriguez 5e1d40f773 add instance_accessor option to ActiveSupport::Configurable#config_accessor
Changes:

* Add `instance_accessor` option to opt out of the instance writer and
  instance reader methods.
* Raises a NameError if the name of the attribute is not valid.
* Update documentation and tests.
* Add CHANGELOG entry in activesupport.
2012-06-05 10:50:48 -05:00

135 lines
4.3 KiB
Ruby
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'active_support/concern'
require 'active_support/ordered_options'
require 'active_support/core_ext/array/extract_options'
module ActiveSupport
# Configurable provides a <tt>config</tt> method to store and retrieve
# configuration options as an <tt>OrderedHash</tt>.
module Configurable
extend ActiveSupport::Concern
class Configuration < ActiveSupport::InheritableOptions
def compile_methods!
self.class.compile_methods!(keys)
end
# compiles reader methods so we don't have to go through method_missing
def self.compile_methods!(keys)
keys.reject { |m| method_defined?(m) }.each do |key|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{key}; _get(#{key.inspect}); end
RUBY
end
end
end
module ClassMethods
def config
@_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
superclass.config.inheritable_copy
else
# create a new "anonymous" class that will host the compiled reader methods
Class.new(Configuration).new
end
end
def configure
yield config
end
# Allows you to add shortcut so that you don't have to refer to attribute
# through config. Also look at the example for config to contrast.
#
# Defines both class and instance config accessors.
#
# class User
# include ActiveSupport::Configurable
# config_accessor :allowed_access
# end
#
# User.allowed_access # => nil
# User.allowed_access = false
# User.allowed_access # => false
#
# user = User.new
# user.allowed_access # => false
# 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)
options = names.extract_options!
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__
writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
singleton_class.class_eval reader, __FILE__, line
singleton_class.class_eval writer, __FILE__, line
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
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
#
# require 'active_support/configurable'
#
# class User
# include ActiveSupport::Configurable
# end
#
# user = User.new
#
# user.config.allowed_access = true
# user.config.level = 1
#
# user.config.allowed_access # => true
# user.config.level # => 1
def config
@_config ||= self.class.config.inheritable_copy
end
end
end