-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added class methods support #4
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,28 +6,44 @@ module Signature | |
|
||
def sig(*sig_args, returns: NULL, **sig_kwargs) | ||
meta = class << self; self; end | ||
sig_check = ->(klass, name, *args, **kwargs, &block) { | ||
sig_args.each.with_index do |arg, i| | ||
args[i] => ^arg | ||
end | ||
|
||
kwargs.each do |key, value| | ||
value => ^(sig_kwargs[key]) | ||
end | ||
|
||
result = if block | ||
klass.send(:"__#{name}", *args, **kwargs, &block) | ||
else | ||
klass.send(:"__#{name}", *args, **kwargs) | ||
end | ||
|
||
result => ^returns if returns != NULL | ||
|
||
result | ||
} | ||
meta.send :define_method, :method_added do |name| | ||
meta.send :remove_method, :method_added | ||
meta.send :remove_method, :singleton_method_added | ||
|
||
alias_method :"__#{name}", name | ||
define_method name do |*args, **kwargs, &block| | ||
sig_args.each.with_index do |arg, i| | ||
args[i] => ^arg | ||
end | ||
|
||
kwargs.each do |key, value| | ||
value => ^(sig_kwargs[key]) | ||
end | ||
sig_check.call(self, name, *args, **kwargs, &block) | ||
end | ||
end | ||
|
||
result = if block | ||
send(:"__#{name}", *args, **kwargs, &block) | ||
else | ||
send(:"__#{name}", *args, **kwargs) | ||
end | ||
meta.send :define_method, :singleton_method_added do |name| | ||
next if name == :singleton_method_added | ||
|
||
result => ^returns if returns != NULL | ||
meta.send :remove_method, :singleton_method_added | ||
meta.send :remove_method, :method_added | ||
Comment on lines
28
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, we wait for either a singleton method or an instance method, whatever happens first will remove both method_added callbacks |
||
|
||
result | ||
meta.alias_method :"__#{name}", name | ||
define_singleton_method name do |*args, **kwargs, &block| | ||
sig_check.call(self, name, *args, **kwargs, &block) | ||
end | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,16 @@ def age = @age.to_s | |
|
||
sig Integer, returns: Integer | ||
attr_writer :age | ||
|
||
sig String, age: Integer, returns: Array | ||
def self.where(_name, age: nil) | ||
[] | ||
end | ||
|
||
sig String, returns: Array | ||
def find_by_name(name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo? should be a class method I think. |
||
User.new(name) | ||
end | ||
end | ||
|
||
it 'supports positional args' do | ||
|
@@ -66,4 +76,31 @@ def age = @age.to_s | |
it 'raises on incorrect kwarg type' do | ||
expect { User.new('Joel', town: 1) }.to raise_exception NoMatchingPatternError | ||
end | ||
|
||
with 'class methods' do | ||
it 'supports class method signatures' do | ||
users = User.where('Joel') | ||
expect(users.length).to be == 0 | ||
end | ||
|
||
it 'raises on incorrect return type' do | ||
expect { User.find_by_name('Hugo') }.to raise_exception NoMatchingPatternError | ||
end | ||
|
||
it 'raises on missing args' do | ||
expect { User.where }.to raise_exception NoMatchingPatternError | ||
end | ||
|
||
it 'raises on incorrect arg type' do | ||
expect { User.where(1) }.to raise_exception NoMatchingPatternError | ||
end | ||
|
||
it 'supports keyword args' do | ||
expect(User.where('hugo', age: 27)).to be == [] | ||
end | ||
|
||
it 'raises on incorrect kwarg type' do | ||
expect { User.where(1, age: 'twentyseven') }.to raise_exception NoMatchingPatternError | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't found this documented anywhere in ruby, but looks like defining
singleton_method_added
also calls itself. Tried isolating this on a simple example just in casedefine_method
orsend
where causing it somehow, but it also happened on isolation