refactor #set

This commit is contained in:
Konstantin Haase 2011-06-05 09:33:00 +02:00
parent e47195a17a
commit e9e3c8500a
2 changed files with 60 additions and 16 deletions

View File

@ -822,20 +822,43 @@ module Sinatra
# Sets an option to the given value. If the value is a proc,
# the proc will be called every time the option is accessed.
def set(option, value = (not_set = true), &block)
def set(option, value = (not_set = true), ignore_setter = false, &block)
raise ArgumentError if block and !not_set
value = block if block
if value.kind_of?(Proc)
metadef(option, &value)
metadef("#{option}?") { !!__send__(option) }
metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) }
elsif not_set
value, not_set = block, false if block
if not_set
raise ArgumentError unless option.respond_to?(:each)
option.each { |k,v| set(k, v) }
elsif respond_to?("#{option}=")
__send__ "#{option}=", value
else
set option, Proc.new{value}
return self
end
if respond_to?("#{option}=") and not ignore_setter
return __send__("#{option}=", value)
end
setter = proc { |val| set option, val, true }
getter = proc { value }
case value
when Proc
getter = value
when Symbol, Fixnum, FalseClass, TrueClass, NilClass
# we have a lot of enable and disable calls, let's optimize those
class_eval "def self.#{option}() #{value.inspect} end"
getter = nil
when Hash
setter = proc do |val|
val = value.merge val if Hash === val
set option, val, true
end
end
(class << self; self; end).class_eval do
define_method("#{option}=", &setter) if setter
define_method(option, &getter) if getter
unless method_defined? "#{option}?"
class_eval "def #{option}?() !!#{option} end"
end
end
self
end
@ -1212,11 +1235,6 @@ module Sinatra
end
end
def metadef(message, &block)
(class << self; self; end).
send :define_method, message, &block
end
public
CALLERS_TO_IGNORE = [ # :nodoc:
/\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code

View File

@ -115,6 +115,32 @@ class SettingsTest < Test::Unit::TestCase
assert_equal 'oops', @base.foo
end
it 'merges values of multiple set calls if those are hashes' do
@base.set :foo, :a => 1
sub = Class.new(@base)
sub.set :foo, :b => 2
assert_equal({:a => 1, :b => 2}, sub.foo)
end
it 'merging does not affect the superclass' do
@base.set :foo, :a => 1
sub = Class.new(@base)
sub.set :foo, :b => 2
assert_equal({:a => 1}, @base.foo)
end
it 'is possible to change a value from a hash to something else' do
@base.set :foo, :a => 1
@base.set :foo, :bar
assert_equal(:bar, @base.foo)
end
it 'merges values with values of the superclass if those are hashes' do
@base.set :foo, :a => 1
@base.set :foo, :b => 2
assert_equal({:a => 1, :b => 2}, @base.foo)
end
it "sets multiple settings to true with #enable" do
@base.enable :sessions, :foo, :bar
assert @base.sessions