Skip to content

Commit 1226fd1

Browse files
authored
Merge pull request rails#52470 from byroot/uncached-code-generation
Refactor CodeGenerator uses in Action View
2 parents bcaac3e + 9c36bcf commit 1226fd1

File tree

3 files changed

+58
-51
lines changed

3 files changed

+58
-51
lines changed

actionview/lib/action_view/helpers/form_helper.rb

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,20 +2020,15 @@ def field_name(method, *methods, multiple: false, index: @options[:index])
20202020
#
20212021
# Please refer to the documentation of the base helper for details.
20222022

2023-
ActiveSupport::CodeGenerator.batch(self, __FILE__, __LINE__) do |code_generator|
2024-
(field_helpers - [:label, :checkbox, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
2025-
code_generator.define_cached_method(selector, namespace: :form_builder) do |batch|
2026-
batch.push <<-RUBY_EVAL
2027-
def #{selector}(method, options = {}) # def text_field(method, options = {})
2028-
@template.public_send( # @template.public_send(
2029-
#{selector.inspect}, # :text_field,
2030-
@object_name, # @object_name,
2031-
method, # method,
2032-
objectify_options(options)) # objectify_options(options))
2033-
end # end
2034-
RUBY_EVAL
2023+
(field_helpers - [:label, :checkbox, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
2024+
ActiveSupport::CodeGenerator.batch(self, __FILE__, __LINE__) do |code_generator|
2025+
code_generator.class_eval do |batch|
2026+
batch <<
2027+
"def #{selector}(method, options = {})" <<
2028+
" @template.#{selector}(@object_name, method, objectify_options(options))" <<
2029+
"end"
2030+
end
20352031
end
2036-
end
20372032
end
20382033
alias_method :text_area, :textarea
20392034

actionview/lib/action_view/helpers/tag_helper.rb

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48,48 +48,51 @@ class TagBuilder # :nodoc:
4848
include CaptureHelper
4949
include OutputSafetyHelper
5050

51-
def self.define_element(name, code_generator:, method_name: name.to_s.underscore)
52-
code_generator.define_cached_method(method_name, namespace: :tag_builder) do |batch|
53-
batch.push(<<~RUBY) unless instance_methods.include?(method_name.to_sym)
54-
def #{method_name}(content = nil, escape: true, **options, &block)
55-
tag_string("#{name}", content, options, escape: escape, &block)
56-
end
57-
RUBY
51+
def deprecated_void_content(name)
52+
ActionView.deprecator.warn <<~TEXT
53+
Putting content inside a void element (#{name}) is invalid
54+
according to the HTML5 spec, and so it is being deprecated
55+
without replacement. In Rails 8.0, passing content as a
56+
positional argument will raise, and using a block will have
57+
no effect.
58+
TEXT
59+
end
60+
61+
def self.define_element(name, code_generator:, method_name: name)
62+
return if method_defined?(name)
63+
64+
code_generator.class_eval do |batch|
65+
batch << "\n" <<
66+
"def #{method_name}(content = nil, escape: true, **options, &block)" <<
67+
" tag_string(#{name.inspect}, content, options, escape: escape, &block)" <<
68+
"end"
5869
end
5970
end
6071

61-
def self.define_void_element(name, code_generator:, method_name: name.to_s.underscore)
62-
code_generator.define_cached_method(method_name, namespace: :tag_builder) do |batch|
63-
batch.push(<<~RUBY)
64-
def #{method_name}(content = nil, escape: true, **options, &block)
65-
if content || block
66-
ActionView.deprecator.warn <<~TEXT
67-
Putting content inside a void element (#{name}) is invalid
68-
according to the HTML5 spec, and so it is being deprecated
69-
without replacement. In Rails 8.0, passing content as a
70-
positional argument will raise, and using a block will have
71-
no effect.
72-
TEXT
73-
tag_string("#{name}", content, options, escape: escape, &block)
74-
else
75-
self_closing_tag_string("#{name}", options, escape, ">")
76-
end
77-
end
78-
RUBY
72+
def self.define_void_element(name, code_generator:, method_name: name)
73+
code_generator.class_eval do |batch|
74+
batch << "\n" <<
75+
"def #{method_name}(content = nil, escape: true, **options, &block)" <<
76+
" p :called; if content || block" <<
77+
" deprecated_void_content(#{name.inspect})" <<
78+
" tag_string(#{name.inspect}, content, options, escape: escape, &block)" <<
79+
" else" <<
80+
" self_closing_tag_string(#{name.inspect}, options, escape, '>')" <<
81+
" end" <<
82+
"end"
7983
end
8084
end
8185

82-
def self.define_self_closing_element(name, code_generator:, method_name: name.to_s.underscore)
83-
code_generator.define_cached_method(method_name, namespace: :tag_builder) do |batch|
84-
batch.push(<<~RUBY)
85-
def #{method_name}(content = nil, escape: true, **options, &block)
86-
if content || block
87-
tag_string("#{name}", content, options, escape: escape, &block)
88-
else
89-
self_closing_tag_string("#{name}", options, escape)
90-
end
91-
end
92-
RUBY
86+
def self.define_self_closing_element(name, code_generator:, method_name: name)
87+
code_generator.class_eval do |batch|
88+
batch << "\n" <<
89+
"def #{method_name}(content = nil, escape: true, **options, &block)" <<
90+
" if content || block" <<
91+
" tag_string(#{name.inspect}, content, options, escape: escape, &block)" <<
92+
" else" <<
93+
" self_closing_tag_string(#{name.inspect}, options, escape)" <<
94+
" end" <<
95+
"end"
9396
end
9497
end
9598

@@ -110,8 +113,8 @@ def #{method_name}(content = nil, escape: true, **options, &block)
110113
define_void_element :wbr, code_generator: code_generator
111114

112115
define_self_closing_element :animate, code_generator: code_generator
113-
define_self_closing_element :animateMotion, code_generator: code_generator
114-
define_self_closing_element :animateTransform, code_generator: code_generator
116+
define_self_closing_element :animateMotion, code_generator: code_generator, method_name: :animate_motion
117+
define_self_closing_element :animateTransform, code_generator: code_generator, method_name: :animate_transform
115118
define_self_closing_element :circle, code_generator: code_generator
116119
define_self_closing_element :ellipse, code_generator: code_generator
117120
define_self_closing_element :line, code_generator: code_generator

activesupport/lib/active_support/code_generator.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ def initialize(owner, path, line)
5555
@path = path
5656
@line = line
5757
@namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
58+
@sources = []
59+
end
60+
61+
def class_eval
62+
yield @sources
5863
end
5964

6065
def define_cached_method(canonical_name, namespace:, as: nil, &block)
@@ -65,6 +70,10 @@ def execute
6570
@namespaces.each_value do |method_set|
6671
method_set.apply(@owner, @path, @line - 1)
6772
end
73+
74+
unless @sources.empty?
75+
@owner.class_eval("# frozen_string_literal: true\n" + @sources.join(";"), @path, @line - 1)
76+
end
6877
end
6978
end
7079
end

0 commit comments

Comments
 (0)