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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
# File 'lib/takes_macro.rb', line 8
def takes(*args)
positional_args = args.reject { |arg| arg.is_a?(Array) }
keyword_args = if args.last.is_a?(Array)
args.last.map(&:to_s)
else
[]
end
all_args = (positional_args + keyword_args).flatten.map do |arg|
arg.to_s.delete("!")
end
args_code = [
positional_args,
]
if keyword_args.one? && !keyword_args.first.include?("!")
args_code << "options = {}"
elsif keyword_args.any?
args_code << "options"
end
args_code = args_code.flatten.compact.join(", ")
bind_positional_args_code = positional_args.map do |arg|
"@#{arg} = #{arg}"
end.join("\n")
bind_keywords_args_code = keyword_args.map do |arg|
code = if arg =~ /!$/
arg = arg.delete("!")
"@#{arg} = options.fetch(:#{arg})"
else
"@#{arg} = options[:#{arg}]"
end
[code, "options.delete(:#{arg})"].join("\n")
end.join("\n")
define_private_attr_readers_code = all_args.map do |arg|
<<-RUBY
attr_reader :#{arg}
private :#{arg}
RUBY
end.join("\n")
ensure_options_are_empty =
if keyword_args.any?
<<-EOS
unless options == {}
raise ArgumentError, "Not all initialize args were used: \#{options.keys.inspect}"
end
EOS
else
""
end
code = <<-RUBY
def initialize(#{args_code})
#{bind_positional_args_code}
#{bind_keywords_args_code}
#{ensure_options_are_empty}
after_takes
end
#{define_private_attr_readers_code}
def after_takes; end
RUBY
class_eval code
end
|