Skip to content

Commit 570e07f

Browse files
committed
Define method using class_eval instead of define_method.
1 parent cea163c commit 570e07f

2 files changed

Lines changed: 28 additions & 10 deletions

File tree

lib/simple_json/simple_json_renderer.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ def load_template_from_file(template_path)
3939
SimpleJson.template_paths.each do |path|
4040
file_path = Rails.root.join("#{path}/#{template_path}.simple_json.rb").to_path
4141

42-
if File.exist?(file_path)
43-
return define_template_method(template_path, file_path)
44-
end
42+
return define_template_method(template_path, file_path) if File.exist?(file_path)
4543
end
4644

4745
nil
@@ -52,9 +50,7 @@ def define_template_method(template_path, file_path)
5250
@template_num += 1
5351
method_name = :"template_#{@template_num}"
5452
render_methods[template_path] = method_name
55-
define_method(method_name, &SimpleJsonTemplate.new(file_path).lambda)
56-
57-
return method_name
53+
SimpleJsonTemplate.new(file_path).define_to_class(self, method_name)
5854
end
5955

6056
def render_methods

lib/simple_json/simple_json_template.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,42 @@ def initialize(path)
77
@source = File.read(path)
88
end
99

10-
def lambda
11-
@lambda ||= eval(code, TOPLEVEL_BINDING, @path) # rubocop:disable Security/Eval
10+
def define_to_class(klass, method_name)
11+
method_string = to_method_string(method_name)
12+
klass.class_eval(method_string, @path)
13+
14+
method_name
1215
end
1316

17+
private
18+
1419
def code
1520
@code ||= lambda_stringify(@source)
1621
end
1722

18-
private
19-
2023
def lambda_stringify(source)
2124
return source if source.match?(/^(?:\s*(?:#.*?)?\n)*\s*->/)
2225

2326
"-> { #{source} }"
2427
end
28+
29+
def method_string_from_lambda(source, method_name)
30+
replaced = source.sub(/\A(?<prefix>(?:[ \t]*(?:#.*?)?\n)*)(?<indent>[ \t]*)->\s*(?<args>\([^)]*\))?[ \t]*\{?[ \t]*(?<rest>[^\n]*)/) do
31+
header = "#{Regexp.last_match(:prefix)}#{Regexp.last_match(:indent)}def #{method_name}#{Regexp.last_match(:args)}"
32+
rest = Regexp.last_match(:rest)
33+
rest.strip.empty? ? header : "#{header}; #{rest.lstrip}"
34+
end
35+
return unless replaced != source
36+
37+
brace_index = replaced.rindex('}')
38+
return replaced unless brace_index
39+
40+
replaced[brace_index] = 'end'
41+
replaced
42+
end
43+
44+
def to_method_string(method_name)
45+
method_string_from_lambda(code, method_name)
46+
end
2547
end
2648
end

0 commit comments

Comments
 (0)