From b46daa82bcd6147961519f8d6e72b31bd63353ad Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 15 Apr 2012 15:57:31 -0500 Subject: [PATCH] Ability to define configuration classes on plugins --- lib/vagrant/plugin/v1.rb | 31 ++++++++++++++--- test/unit/vagrant/plugin/v1_test.rb | 52 ++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/lib/vagrant/plugin/v1.rb b/lib/vagrant/plugin/v1.rb index 16d4adab9..bf69a3135 100644 --- a/lib/vagrant/plugin/v1.rb +++ b/lib/vagrant/plugin/v1.rb @@ -32,11 +32,36 @@ module Vagrant get_or_set(:description, value) end + # Defines additional configuration keys to be available in the + # Vagrantfile. The configuration class should be returned by a + # block passed to this method. This is done to ensure that the class + # is lazy loaded, so if your class inherits from any classes that + # are specific to Vagrant 1.0, then the plugin can still be defined + # without breaking anything in future versions of Vagrant. + # + # @param [String] name Configuration key. + def self.config(name=UNSET_VALUE, &block) + data[:config] ||= Registry.new + + # Register a new config class only if a name was given. + data[:config].register(name, &block) if name != UNSET_VALUE + + # Return the registry + data[:config] + end + protected # Sentinel value denoting that a value has not been set. UNSET_VALUE = Object.new + # Returns the internal data associated with this plugin. + # + # @return [Hash] + def self.data + @data ||= {} + end + # Helper method that will set a value if a value is given, or otherwise # return the already set value. # @@ -44,13 +69,11 @@ module Vagrant # @param [Object] value Value to store. # @return [Object] Stored value. def self.get_or_set(key, value=UNSET_VALUE) - @data ||= {} - # If no value is to be set, then return the value we have already set - return @data[key] if value.eql?(UNSET_VALUE) + return data[key] if value.eql?(UNSET_VALUE) # Otherwise set the value - @data[key] = value + data[key] = value end # Registers the plugin. This makes the plugin actually work with diff --git a/test/unit/vagrant/plugin/v1_test.rb b/test/unit/vagrant/plugin/v1_test.rb index 03011b266..e648efd3a 100644 --- a/test/unit/vagrant/plugin/v1_test.rb +++ b/test/unit/vagrant/plugin/v1_test.rb @@ -23,24 +23,52 @@ describe Vagrant::Plugin::V1 do plugin.description.should == "bar" end - it "should have no registered plugins" do - described_class.registered.should be_empty - end - - it "should register a plugin when a name is set" do + it "should register configuration classes" do plugin = Class.new(described_class) do - name "foo" + config("foo") { "bar" } end - described_class.registered.should == [plugin] + plugin.config["foo"].should == "bar" end - it "should register a plugin only once" do - plugin = Class.new(described_class) do - name "foo" - name "bar" + it "should lazily register configuration classes" do + # Below would raise an error if the value of the config class was + # evaluated immediately. By asserting that this does not raise an + # error, we verify that the value is actually lazily loaded + plugin = nil + expect { + plugin = Class.new(described_class) do + config("foo") { raise StandardError, "FAIL!" } + end + }.to_not raise_error + + # Now verify when we actually get the configuration key that + # a proper error is raised. + expect { + plugin.config["foo"] + }.to raise_error(StandardError) + end + + describe "plugin registration" do + it "should have no registered plugins" do + described_class.registered.should be_empty end - described_class.registered.should == [plugin] + it "should register a plugin when a name is set" do + plugin = Class.new(described_class) do + name "foo" + end + + described_class.registered.should == [plugin] + end + + it "should register a plugin only once" do + plugin = Class.new(described_class) do + name "foo" + name "bar" + end + + described_class.registered.should == [plugin] + end end end