diff --git a/lib/vagrant/config/top.rb b/lib/vagrant/config/top.rb index 8c2d0e5f4..51e814b45 100644 --- a/lib/vagrant/config/top.rb +++ b/lib/vagrant/config/top.rb @@ -7,6 +7,8 @@ module Vagrant # # If you're looking to create your own configuration class, see {Base}. class Top < Base + attr_reader :keys + def initialize(registry=nil) @keys = {} @registry = registry || Vagrant.config_keys @@ -28,6 +30,24 @@ module Vagrant end end + # Custom implementation to merge each key separately. + def merge(other) + result = self.class.new + @keys.each do |key, value| + result.keys[key] = value.merge(other.send(key)) + end + + other.keys.each do |key, value| + if !@keys.has_key?(key) + # This is a key that the other configuration class has + # that we don't, so just copy it in. + result.keys[key] = value.dup + end + end + + result + end + # Validates the configuration classes of this instance and raises an # exception if they are invalid. If you are implementing a custom configuration # class, the method you want to implement is {Base#validate}. This is diff --git a/test/unit/vagrant/config/top_test.rb b/test/unit/vagrant/config/top_test.rb index 21daf8c8e..b0d1c75b9 100644 --- a/test/unit/vagrant/config/top_test.rb +++ b/test/unit/vagrant/config/top_test.rb @@ -24,4 +24,46 @@ describe Vagrant::Config::Top do it "still raises a method missing error if invalid key" do expect { instance.foo }.to raise_error(NoMethodError) end + + describe "merging" do + let(:foo_class) do + Class.new do + attr_accessor :one + attr_accessor :two + + def merge(other) + result = self.class.new + result.one = other.one || one + result.two = other.two || two + result + end + end + end + + it "merges each key by calling `merge` on the class" do + registry.register(:foo, foo_class) + + instance.foo.one = 1 + instance.foo.two = 2 + + another = described_class.new(registry) + another.foo.one = 2 + + result = instance.merge(another) + result.foo.one.should == 2 + result.foo.two.should == 2 + end + + it "merges keys that aren't in the source instance" do + reg = Vagrant::Registry.new + reg.register(:foo, foo_class) + + another = described_class.new(reg) + another.foo.one = 2 + + result = instance.merge(another) + result.foo.one.should == 2 + result.foo.two.should be_nil + end + end end