Skip to content

Instantly share code, notes, and snippets.

@bestie
Created October 14, 2013 15:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bestie/6977917 to your computer and use it in GitHub Desktop.
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.
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)
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