Created
October 14, 2013 15:58
-
-
Save bestie/6977917 to your computer and use it in GitHub Desktop.
`Proc#merge_curry` Single argument Proc can be curried to receive an arbitrary number of hashes.
The Proc is finally called with the merge result of all hashes.
Hashes are merged in order, last winning.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module MergeCurry | |
def merge_curry(hash_count) | |
curried_proc = self | |
hashes = [] | |
curry_again = Proc.new { |*args| | |
hashes = hashes.concat(args) | |
if hashes.size >= hash_count | |
final_hash = hashes.reduce({}) { |agg, hash| | |
agg.merge(hash) | |
} | |
curried_proc.call(final_hash) | |
else | |
curry_again | |
end | |
} | |
end | |
end | |
Proc.send(:include, MergeCurry) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
require 'lib/proc_merge_curry_ext' | |
describe Proc do | |
describe "#merge_curry" do | |
let(:spy) { | |
double(:spy, :proc_was_called => "return value") | |
} | |
let(:proc) { | |
Proc.new { |*args| spy.proc_was_called(*args) } | |
} | |
let(:arg_one) { | |
{ :one => 1 } | |
} | |
let(:arg_two) { | |
{ :two => 2 } | |
} | |
let(:arg_three) { | |
{ :three => 3 } | |
} | |
it "returns another proc" do | |
expect(proc.merge_curry(1)).to be_a(Proc) | |
end | |
context "with an arity of 1" do | |
let(:arity) { 1 } | |
it "immediately calls the proc with args given" do | |
curried = proc.merge_curry(arity) | |
curried.call(arg_one) | |
expect(spy).to have_received(:proc_was_called).with(arg_one) | |
end | |
end | |
context "with an arity greater than 1" do | |
let(:arity) { 3 } | |
it "calls the proc after receiving `arity` hashes" do | |
curried = proc.merge_curry(arity) | |
curried_called_once = curried.call(arg_one) | |
curried_called_twice = curried_called_once.call(arg_two) | |
curried_called_thrice = curried_called_twice.call(arg_three) | |
expect(spy).to have_received(:proc_was_called) | |
end | |
it "can receive more than one hash at a time" do | |
curried = proc.merge_curry(arity) | |
curried_called_once_with_two = curried.call(arg_one, arg_two) | |
curried_called_twice = curried_called_once_with_two.call(arg_three) | |
expect(spy).to have_received(:proc_was_called) | |
end | |
it "does not call the proc before it receives `arity` hashes" do | |
curried = proc.merge_curry(arity) | |
curried_called_once = curried.call(arg_one) | |
curried_called_twice = curried_called_once.call(arg_two) | |
expect(spy).not_to have_received(:proc_was_called) | |
end | |
it "calls the proc with a single hash argument" do | |
curried = proc.merge_curry(arity) | |
curried_called_once = curried.call(arg_one) | |
curried_called_twice = curried_called_once.call(arg_two) | |
curried_called_thrice = curried_called_twice.call(arg_three) | |
expect(spy).to have_received(:proc_was_called) do |*args| | |
expect(args.length).to eq(1) | |
end | |
end | |
it "calls the proc with a hash that is the merge result of all passed hashes" do | |
curried = proc.merge_curry(arity) | |
curried_called_once = curried.call(arg_one) | |
curried_called_twice = curried_called_once.call(arg_two) | |
curried_called_thrice = curried_called_twice.call(arg_three) | |
expect(spy).to have_received(:proc_was_called).with( | |
:one => 1, | |
:two => 2, | |
:three => 3, | |
) | |
end | |
it "merges the hashes in the order they are given" do | |
curried = proc.merge_curry(arity) | |
curried_called_once = curried.call( | |
:overwrite_me => "not_overwritten", | |
) | |
curried_called_twice = curried_called_once.call( | |
:whatever => "whatever", | |
) | |
curried_called_thrice = curried_called_twice.call( | |
:overwrite_me => "overwritten", | |
) | |
expect(spy).to have_received(:proc_was_called).with( | |
:whatever => "whatever", | |
:overwrite_me => "overwritten", | |
) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment