feat(data): allow for setting & getting Arrays through #store & #data_for_path

Seeing that in #touch_file that a value in data could be an Array or Hash, loosen contracts to allow for other storage & retrieval methods to set the same types. Array & Hash being allowable is strongly tied to what *could* be returned after passing through Util.recursively_enhance

[close #1803]
This commit is contained in:
Steven Sloan 2016-02-17 16:58:04 -05:00
parent a24e5986a2
commit fc0f5d24d6
3 changed files with 110 additions and 4 deletions

View file

@ -67,7 +67,7 @@ module Middleman
# @param [Symbol] name Name of the data, used for namespacing
# @param [Hash] content The content for this data
# @return [Hash]
Contract Symbol, Hash => Hash
Contract Symbol, Or[Hash, Array] => Hash
def store(name=nil, content=nil)
@local_sources[name.to_s] = content unless name.nil? || content.nil?
@local_sources
@ -148,7 +148,7 @@ module Middleman
#
# @param [String, Symbol] path The name of the data namespace
# @return [Hash, nil]
Contract Or[String, Symbol] => Maybe[Hash]
Contract Or[String, Symbol] => Maybe[Or[Array, IsA['Middleman::Util::EnhancedHash']]]
def data_for_path(path)
response = if store.key?(path.to_s)
store[path.to_s]

View file

@ -29,7 +29,7 @@ module Middleman
if obj.is_a? ::Array
obj.map { |e| recursively_enhance(e) }
elsif obj.is_a? ::Hash
::Hashie::Mash.new(obj)
EnhancedHash.new(obj)
else
obj
end

View file

@ -7,6 +7,112 @@ end
describe Middleman::CoreExtensions::Data::DataStore do
describe "#store" do
before :each do
@subject = described_class.new instance_double("Middleman::Application"),
Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
end
context "when given a name and data" do
it "adds data at the given name" do
@subject.store :foo, { 'bar' => 'baz' }
@subject.store :baz, [:wu, :tang]
expect( @subject.store['foo'] ).to eq({ 'bar' => 'baz' })
expect( @subject.store['baz'] ).to match_array [:wu, :tang]
end
it "overwrites previous keys if given the same key" do
@subject.store :foo, { 'bar' => 'baz' }
@subject.store :foo, [:wu, :tang]
expect( @subject.store['foo'] ).to match_array [:wu, :tang]
end
end
context "when given no args" do
it "returns @local_sources instance var" do
@subject.instance_variable_set :"@local_sources", { foo: 'bar' }
expect( @subject.store ).to eq({ foo: 'bar' })
end
end
end
describe "#callbacks" do
before :each do
@subject = described_class.new instance_double("Middleman::Application"),
Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
end
context "when given a name and proc" do
it "adds a callback at the given name" do
@subject.callbacks :foo, lambda { "bar" }
callback = @subject.instance_variable_get(:@callback_sources)['foo']
expect( callback.call ).to eq "bar"
end
it "overwrites previous keys if given the same key" do
@subject.callbacks :foo, lambda { "bar" }
@subject.callbacks :foo, lambda { "baz" }
callback = @subject.instance_variable_get(:@callback_sources)['foo']
expect( callback.call ).to eq "baz"
end
end
context "when given no args" do
it "returns @callback_sources instance var" do
@subject.instance_variable_set :"@callback_sources", { foo: 'bar' }
expect( @subject.callbacks ).to eq({ foo: 'bar' })
end
end
end
describe "#data_for_path" do
before :each do
@subject = described_class.new instance_double("Middleman::Application"),
Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
end
context "given path matches local data" do
it "returns hash for key" do
@subject.store :foo, { 'bar' => 'baz' }
expect( @subject.data_for_path(:foo) ).to eq({ 'bar' => 'baz' })
end
it "returns array for key" do
@subject.store :foo, [:bar, :baz]
expect( @subject.data_for_path(:foo) ).to match_array [:bar, :baz]
end
end
context "given path matches callback data" do
it "returns value of calback lambda" do
@subject.callbacks :foo, lambda { { 'bar' => 'baz' } }
@subject.callbacks :wu, lambda { [:tang, :clan] }
expect( @subject.data_for_path(:foo) ).to eq({ 'bar' => 'baz' })
expect( @subject.data_for_path(:wu) ).to match_array [:tang, :clan]
end
end
context "given path matches both sources" do
it "returns match from local data" do
@subject.store :foo, { 'local' => 'data' }
@subject.callbacks :foo, lambda { { 'callback' => 'data' } }
expect( @subject.data_for_path(:foo) ).to eq({ 'local' => 'data' })
end
end
context "given path matches no sources" do
it "returns nil" do
expect( @subject.data_for_path(:missing) ).to be_nil
end
end
end
describe "#key?" do
it "returns true if key included in local_data, local_sources, or callback_sources" do
@ -38,4 +144,4 @@ describe Middleman::CoreExtensions::Data::DataStore do
end
end
end