8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# File 'lib/debouncer/debounceable.rb', line 8
def debounce(name, delay, rescue_with: nil, grouped: false, reduce_with: nil, class_method: false)
name =~ /^(\w+)([?!=]?)$/ or
raise ArgumentError, 'Invalid method name'
base_name = $1
suffix = $2
immediate = "#{base_name}_immediately#{suffix}"
debouncer = "@#{base_name}#{SUFFIXES[suffix]}_debouncer"
= ''
if reduce_with
arity = __send__(class_method ? :method : :instance_method, reduce_with).arity
expected = grouped ? 2..3 : 2
unless arity < 0 || expected === arity
raise ArgumentError, 'Expected %s%s%s to accept %s arguments, but it accepts %s.' %
[self.name, class_method ? '.' : '#', reduce_with, expected, arity]
end
if grouped
<< ".reducer { |old, new| [new.first, *self.#{reduce_with}(old[1..-1] || [], new[1..-1]#{', new.first' unless arity == 2})] }"
else
<< ".reducer { |old, new| self.#{reduce_with} old, new }"
end
end
<< ".rescuer { |ex| self.#{rescue_with} ex }" if rescue_with
class_eval <<-RUBY, __FILE__, __LINE__ + 1
#{'class << self' if class_method}
alias_method :#{immediate}, :#{name}
def #{name}(*args, &block)
#{debouncer} ||= ::Debouncer.new(#{delay}) { |*args| self.#{immediate} *args }#{}
#{debouncer}#{'.group(args.first)' if grouped}.call *args, &block
end
def flush_#{name}(*args)
#{debouncer}.flush *args if #{debouncer}
end
def flush_and_join_#{name}(*args)
#{debouncer}.flush! *args if #{debouncer}
end
def join_#{name}(*args)
#{debouncer}.join *args if #{debouncer}
end
def cancel_#{name}(*args)
#{debouncer}.kill *args if #{debouncer}
end
#{'end' if class_method}
RUBY
end
|