diff options
-rw-r--r-- | activesupport/CHANGELOG | 11 | ||||
-rw-r--r-- | activesupport/lib/active_support.rb | 1 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/object_and_class.rb | 4 | ||||
-rw-r--r-- | activesupport/lib/active_support/option_merger.rb | 25 | ||||
-rw-r--r-- | activesupport/test/option_merger_test.rb | 32 |
5 files changed, 73 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index b5673f8a71..0f2d0abfd1 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,16 @@ *SVN* +* Add Object#with_options for DRYing up multiple calls to methods having shared options. [Sam Stephenson] Example: + + ActionController::Routing::Routes.draw do |map| + # Account routes + map.with_options(:controller => 'account') do |account| + account.home '', :action => 'dashboard' + account.signup 'signup', :action => 'new' + account.logout 'logout', :action => 'logout' + end + end + * Introduce Dependencies.warnings_on_first_load setting. If true, enables warnings on first load of a require_dependency. Otherwise, loads without warnings. Disabled (set to false) by default. [Jeremy Kemper] * Active Support is warnings-safe. #1792 [Eric Hodel] diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 7d5440f2a8..1cace11e9b 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -32,5 +32,6 @@ require 'active_support/clean_logger' require 'active_support/dependencies' require 'active_support/ordered_options' +require 'active_support/option_merger' require 'active_support/values/time_zone'
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/object_and_class.rb b/activesupport/lib/active_support/core_ext/object_and_class.rb index 7864c1a9dc..aef1f22c6f 100644 --- a/activesupport/lib/active_support/core_ext/object_and_class.rb +++ b/activesupport/lib/active_support/core_ext/object_and_class.rb @@ -50,6 +50,10 @@ class Object #:nodoc: raise unless exception_classes.any? {|cls| e.kind_of? cls} end end + + def with_options(options) + yield ActiveSupport::OptionMerger.new(self, options) + end end class Class #:nodoc: diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb new file mode 100644 index 0000000000..51a2ea1328 --- /dev/null +++ b/activesupport/lib/active_support/option_merger.rb @@ -0,0 +1,25 @@ +module ActiveSupport + class OptionMerger #:nodoc: + instance_methods.each do |method| + undef_method(method) if method !~ /^(__|instance_eval)/ + end + + def initialize(context, options) + @context, @options = context, options + end + + private + def method_missing(method, *arguments, &block) + merge_argument_options! arguments + @context.send(method, *arguments, &block) + end + + def merge_argument_options!(arguments) + arguments << if arguments.last.respond_to? :merge! + arguments.pop.dup.merge!(@options) + else + @options.dup + end + end + end +end diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb new file mode 100644 index 0000000000..0142db5b65 --- /dev/null +++ b/activesupport/test/option_merger_test.rb @@ -0,0 +1,32 @@ +require 'test/unit' + +$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' +require 'active_support' + +class OptionMergerTest < Test::Unit::TestCase + def setup + @options = {:hello => 'world'} + end + + def test_method_with_options_merges_options_when_options_are_present + local_options = {:cool => true} + + with_options(@options) do |o| + assert_equal local_options, method_with_options(local_options) + assert_equal @options.merge(local_options), + o.method_with_options(local_options) + end + end + + def test_method_with_options_appends_options_when_options_are_missing + with_options(@options) do |o| + assert_equal Hash.new, method_with_options + assert_equal @options, o.method_with_options + end + end + + private + def method_with_options(options = {}) + options + end +end |