summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Roberts <chrisroberts.code@gmail.com>2013-04-18 10:49:32 -0700
committerChris Roberts <chrisroberts.code@gmail.com>2013-04-18 10:49:32 -0700
commit47a51f58bf8f84718e6cc2dbeaf21028b4d711d3 (patch)
tree169983c67b80364221b821c59a86401adb2f440e
parent83e161811cbe483759790d737229efbca2f93021 (diff)
downloadmixlib-cli-47a51f58bf8f84718e6cc2dbeaf21028b4d711d3.tar.gz
Properly pass options during inheritance. Full dup to ensure proper option isolation.
-rw-r--r--lib/mixlib/cli.rb27
-rw-r--r--spec/mixlib/cli_spec.rb36
2 files changed, 62 insertions, 1 deletions
diff --git a/lib/mixlib/cli.rb b/lib/mixlib/cli.rb
index bdaabdb..23fcb9e 100644
--- a/lib/mixlib/cli.rb
+++ b/lib/mixlib/cli.rb
@@ -38,8 +38,32 @@ module Mixlib
# #parse_options. After calling this method, the attribute #config will
# contain a hash of `:option_name => value` pairs.
module CLI
- module ClassMethods
+
+ module InheritMethods
+ def inherited(receiver)
+ receiver.options = deep_dup(self.options)
+ receiver.extend(Mixlib::CLI::InheritMethods)
+ end
+ def deep_dup(thing)
+ new_thing = thing.respond_to?(:dup) ? thing.dup : thing
+ if(new_thing.kind_of?(Enumerable))
+ if(new_thing.kind_of?(Hash))
+ duped = new_thing.map do |key, value|
+ [deep_dup(key), deep_dup(value)]
+ end
+ new_thing = new_thing.class[*duped.flatten]
+ else
+ new_thing.map!{|value| deep_dup(value)}
+ end
+ end
+ new_thing
+ rescue TypeError
+ thing
+ end
+ end
+
+ module ClassMethods
# When this setting is set to +true+, default values supplied to the
# mixlib-cli DSL will be stored in a separate Hash
def use_separate_default_options(true_or_false)
@@ -255,6 +279,7 @@ module Mixlib
def self.included(receiver)
receiver.extend(Mixlib::CLI::ClassMethods)
+ receiver.extend(Mixlib::CLI::InheritMethods)
end
end
diff --git a/spec/mixlib/cli_spec.rb b/spec/mixlib/cli_spec.rb
index 39740b4..9175506 100644
--- a/spec/mixlib/cli_spec.rb
+++ b/spec/mixlib/cli_spec.rb
@@ -235,6 +235,42 @@ describe Mixlib::CLI do
end
+ context "when subclassed" do
+ before do
+ TestCLI.options = {:arg1 => {:boolean => true}}
+ end
+
+ it "should retain previously defined options from parent" do
+ class T1 < TestCLI
+ option :arg2, :boolean => true
+ end
+ T1.options[:arg1].should be_a(Hash)
+ T1.options[:arg2].should be_a(Hash)
+ TestCLI.options[:arg2].should be_nil
+ end
+
+ it "should not be able to modify parent classes options" do
+ class T2 < TestCLI
+ option :arg2, :boolean => true
+ end
+ T2.options[:arg1][:boolean] = false
+ T2.options[:arg1][:boolean].should be_false
+ T1.options[:arg1][:boolean].should be_true
+ end
+
+ it "should pass its options onto child" do
+ class T3 < TestCLI
+ option :arg2, :boolean => true
+ end
+ class T4 < T3
+ option :arg3, :boolean => true
+ end
+ 3.times do |i|
+ T4.options["arg#{i + 1}".to_sym].should be_a(Hash)
+ end
+ end
+ end
+
end