Skip to content

Commit cec57e0

Browse files
committed
Added readme and a few more tests
1 parent 365a08a commit cec57e0

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Delivered: Simple runtime type checking for Ruby method signatures
2+
3+
Delivered gives you the ability to define method signatures in Ruby, and have them checked at
4+
runtime. This is useful for ensuring that your methods are being called with the correct arguments,
5+
and for providing better error messages when they are not.
6+
7+
Simply define a method signature using the `sig` method directly before the method to be checked,
8+
and Delivered will check that the method is being called with the correct arguments and types. it
9+
can alos chreck the return value of the method.
10+
11+
```ruby
12+
class User
13+
sig String, age: Integer, returns: String
14+
def create(name, age:)
15+
"User #{name} created with age #{age}"
16+
end
17+
end
18+
```

lib/delivered/signature.rb

+12-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
module Delivered
44
module Signature
5-
def sig(*sig_args, returns: nil, **sig_kwargs) # rubocop:disable Lint/UnusedMethodArgument
5+
NULL = Object.new
6+
7+
def sig(*sig_args, returns: NULL, **sig_kwargs)
68
meta = class << self; self; end
79
meta.send :define_method, :method_added do |name|
810
meta.send :remove_method, :method_added
@@ -17,11 +19,15 @@ def sig(*sig_args, returns: nil, **sig_kwargs) # rubocop:disable Lint/UnusedMeth
1719
value => ^(sig_kwargs[key])
1820
end
1921

20-
if block
21-
send(:"__#{name}", *args, **kwargs, &block).tap { |x| x => returns }
22-
else
23-
send(:"__#{name}", *args, **kwargs).tap { |x| x => returns }
24-
end
22+
result = if block
23+
send(:"__#{name}", *args, **kwargs, &block)
24+
else
25+
send(:"__#{name}", *args, **kwargs)
26+
end
27+
28+
result => ^returns if returns != NULL
29+
30+
result
2531
end
2632
end
2733
end

test/delivered/signature.rb

+26-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class User
66

77
attr_reader :town, :blk
88

9-
sig String, Integer, town: String, returns: User
9+
sig String, Integer, town: String
1010
def initialize(name, age = nil, town: nil, &block)
1111
@name = name
1212
@age = age
@@ -16,17 +16,41 @@ def initialize(name, age = nil, town: nil, &block)
1616

1717
sig returns: String
1818
def to_s = "#{@name}, #{@age}"
19+
20+
sig returns: Integer
21+
def age = @age.to_s
22+
23+
sig Integer, returns: Integer
24+
attr_writer :age
1925
end
2026

2127
it 'supports positional args' do
22-
expect(User.new('Joel', 47).to_s).to be == 'Joel, 47'
28+
user = User.new('Joel', 47)
29+
expect(user.to_s).to be == 'Joel, 47'
2330
end
2431

32+
# it 'supports optional positional args'
33+
2534
it 'supports block' do
2635
user = User.new('Joel', 47) { 'Hello' }
2736
expect(user.blk.call).to be == 'Hello'
2837
end
2938

39+
it 'checks return type' do
40+
user = User.new('Joel', 47)
41+
expect(user.to_s).to be == 'Joel, 47'
42+
end
43+
44+
it 'raises on incorrect return type' do
45+
user = User.new('Joel', 47)
46+
expect { user.age }.to raise_exception NoMatchingPatternError
47+
end
48+
49+
it 'checks return type with args' do
50+
user = User.new('Joel', 47)
51+
expect(user.age = 48).to be == 48
52+
end
53+
3054
it 'raises on missing args' do
3155
expect { User.new }.to raise_exception NoMatchingPatternError
3256
end

0 commit comments

Comments
 (0)