Skip to content

Instantly share code, notes, and snippets.

@lukaszx0
Last active August 29, 2015 14:21
Show Gist options
  • Select an option

  • Save lukaszx0/50a29c0aff87f3aefd89 to your computer and use it in GitHub Desktop.

Select an option

Save lukaszx0/50a29c0aff87f3aefd89 to your computer and use it in GitHub Desktop.
kwargs polyfill

kwargs

This is a simple hash extension which imitates behaviour of ruby's 2.1 keyword arguments. Check out examples below and spec file for sample usage.

Examples

Required args

def foobar(args = {})
  # require :foo and :bar keys
  foo, bar = args.kwargs!(:foo, :bar)
  puts foo, bar
end

Default args

def foobar(args = {})
  # set default values for args
  foo = args.kwargs!([:foo, "bar"])
  puts foo
end

Mixed

def foobar(args = {})
  foo, bar = args.kwargs!([:foo, "bar"], :bar)
  puts foo
  puts args[:bar]
end
class Hash
def kwargs!(*args)
return_args = []
expected_args = []
key, val = nil, nil
args.each do |arg|
if arg.is_a?(Symbol) && has_key?(arg)
val = self[arg]
expected_args << arg
elsif arg.is_a?(Array) && arg.first.is_a?(Symbol)
key = arg.first
val = self[key] || arg.last
expected_args << key
else
raise ArgumentError
end
self[key] = val unless key.nil?
return_args << val
key = val = nil
end
raise ArgumentError unless keys & expected_args == keys
return_args
end
end
require 'spec_helper'
describe Hash do
describe 'required' do
context "mising argument" do
it { expect { { foo: "bar" }.kwargs!(:bar) }.to raise_error ArgumentError }
end
context "extra args" do
it { expect { { foo: "foo", bar: "bar" }.kwargs!(:foo) }.to raise_error ArgumentError }
end
end
describe 'defaults' do
it 'should set default value' do
hash = {}
hash.kwargs!([:foo, "foo"])
expect(hash[:foo]).to eq "foo"
end
it 'required and default arg' do
hash = { bar: "yolo" }
hash.kwargs!([:foo, "foo"], :bar)
expect(hash).to eq(foo: "foo", bar: "yolo")
end
end
describe 'returning' do
it 'should return array with args values' do
foo, bar = { bar: "yolo" }.kwargs!([:foo, "foo"], :bar)
expect(foo).to eq "foo"
expect(bar).to eq "yolo"
end
end
end
@lukaszx0

Copy link
Copy Markdown
Author

Because if you'd have mixed args - required and default one, the default one will get overwritten and lost in translation (hash won't get merged) See this case:

def foo(args = { default: 1})
  puts args
end

foo(required: "yolo") => # { required: "yolo" }

@ecin

ecin commented May 18, 2015

Copy link
Copy Markdown

Oh, of course!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment