actionview 4.2.11.1 → 7.0.2.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +229 -215
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -8
  5. data/lib/action_view/base.rb +116 -43
  6. data/lib/action_view/buffers.rb +20 -3
  7. data/lib/action_view/cache_expiry.rb +66 -0
  8. data/lib/action_view/context.rb +8 -12
  9. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  10. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  11. data/lib/action_view/dependency_tracker.rb +21 -122
  12. data/lib/action_view/digestor.rb +92 -85
  13. data/lib/action_view/flows.rb +15 -16
  14. data/lib/action_view/gem_version.rb +6 -4
  15. data/lib/action_view/helpers/active_model_helper.rb +17 -12
  16. data/lib/action_view/helpers/asset_tag_helper.rb +356 -101
  17. data/lib/action_view/helpers/asset_url_helper.rb +180 -74
  18. data/lib/action_view/helpers/atom_feed_helper.rb +21 -19
  19. data/lib/action_view/helpers/cache_helper.rb +156 -43
  20. data/lib/action_view/helpers/capture_helper.rb +21 -14
  21. data/lib/action_view/helpers/controller_helper.rb +16 -5
  22. data/lib/action_view/helpers/csp_helper.rb +26 -0
  23. data/lib/action_view/helpers/csrf_helper.rb +8 -6
  24. data/lib/action_view/helpers/date_helper.rb +288 -132
  25. data/lib/action_view/helpers/debug_helper.rb +9 -6
  26. data/lib/action_view/helpers/form_helper.rb +956 -173
  27. data/lib/action_view/helpers/form_options_helper.rb +178 -97
  28. data/lib/action_view/helpers/form_tag_helper.rb +220 -101
  29. data/lib/action_view/helpers/javascript_helper.rb +33 -19
  30. data/lib/action_view/helpers/number_helper.rb +88 -63
  31. data/lib/action_view/helpers/output_safety_helper.rb +38 -6
  32. data/lib/action_view/helpers/rendering_helper.rb +21 -10
  33. data/lib/action_view/helpers/sanitize_helper.rb +31 -32
  34. data/lib/action_view/helpers/tag_helper.rb +332 -71
  35. data/lib/action_view/helpers/tags/base.rb +123 -99
  36. data/lib/action_view/helpers/tags/check_box.rb +21 -20
  37. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  38. data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -34
  39. data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
  40. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
  41. data/lib/action_view/helpers/tags/collection_select.rb +5 -3
  42. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  43. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  44. data/lib/action_view/helpers/tags/date_select.rb +38 -37
  45. data/lib/action_view/helpers/tags/datetime_field.rb +4 -3
  46. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  47. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  48. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  49. data/lib/action_view/helpers/tags/file_field.rb +18 -0
  50. data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
  51. data/lib/action_view/helpers/tags/hidden_field.rb +6 -0
  52. data/lib/action_view/helpers/tags/label.rb +7 -2
  53. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  54. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  55. data/lib/action_view/helpers/tags/password_field.rb +3 -1
  56. data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
  57. data/lib/action_view/helpers/tags/radio_button.rb +7 -6
  58. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  59. data/lib/action_view/helpers/tags/search_field.rb +14 -9
  60. data/lib/action_view/helpers/tags/select.rb +11 -10
  61. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  62. data/lib/action_view/helpers/tags/text_area.rb +4 -2
  63. data/lib/action_view/helpers/tags/text_field.rb +8 -8
  64. data/lib/action_view/helpers/tags/time_field.rb +12 -2
  65. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  66. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  67. data/lib/action_view/helpers/tags/translator.rb +15 -16
  68. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  69. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  70. data/lib/action_view/helpers/tags/weekday_select.rb +28 -0
  71. data/lib/action_view/helpers/tags.rb +5 -2
  72. data/lib/action_view/helpers/text_helper.rb +80 -51
  73. data/lib/action_view/helpers/translation_helper.rb +120 -69
  74. data/lib/action_view/helpers/url_helper.rb +398 -171
  75. data/lib/action_view/helpers.rb +29 -27
  76. data/lib/action_view/layouts.rb +68 -63
  77. data/lib/action_view/log_subscriber.rb +77 -10
  78. data/lib/action_view/lookup_context.rb +137 -113
  79. data/lib/action_view/model_naming.rb +4 -2
  80. data/lib/action_view/path_set.rb +28 -32
  81. data/lib/action_view/railtie.rb +74 -13
  82. data/lib/action_view/record_identifier.rb +53 -26
  83. data/lib/action_view/render_parser.rb +188 -0
  84. data/lib/action_view/renderer/abstract_renderer.rb +152 -15
  85. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  86. data/lib/action_view/renderer/object_renderer.rb +34 -0
  87. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
  88. data/lib/action_view/renderer/partial_renderer.rb +51 -333
  89. data/lib/action_view/renderer/renderer.rb +68 -11
  90. data/lib/action_view/renderer/streaming_template_renderer.rb +60 -56
  91. data/lib/action_view/renderer/template_renderer.rb +87 -74
  92. data/lib/action_view/rendering.rb +73 -47
  93. data/lib/action_view/ripper_ast_parser.rb +198 -0
  94. data/lib/action_view/routing_url_for.rb +35 -24
  95. data/lib/action_view/tasks/cache_digests.rake +25 -0
  96. data/lib/action_view/template/error.rb +151 -41
  97. data/lib/action_view/template/handlers/builder.rb +12 -13
  98. data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
  99. data/lib/action_view/template/handlers/erb.rb +29 -89
  100. data/lib/action_view/template/handlers/html.rb +11 -0
  101. data/lib/action_view/template/handlers/raw.rb +4 -4
  102. data/lib/action_view/template/handlers.rb +14 -10
  103. data/lib/action_view/template/html.rb +12 -13
  104. data/lib/action_view/template/inline.rb +22 -0
  105. data/lib/action_view/template/raw_file.rb +25 -0
  106. data/lib/action_view/template/renderable.rb +24 -0
  107. data/lib/action_view/template/resolver.rb +139 -300
  108. data/lib/action_view/template/sources/file.rb +17 -0
  109. data/lib/action_view/template/sources.rb +13 -0
  110. data/lib/action_view/template/text.rb +10 -12
  111. data/lib/action_view/template/types.rb +28 -26
  112. data/lib/action_view/template.rb +123 -91
  113. data/lib/action_view/template_details.rb +66 -0
  114. data/lib/action_view/template_path.rb +64 -0
  115. data/lib/action_view/test_case.rb +70 -53
  116. data/lib/action_view/testing/resolvers.rb +25 -35
  117. data/lib/action_view/unbound_template.rb +57 -0
  118. data/lib/action_view/version.rb +3 -1
  119. data/lib/action_view/view_paths.rb +73 -58
  120. data/lib/action_view.rb +16 -11
  121. data/lib/assets/compiled/rails-ujs.js +746 -0
  122. metadata +52 -32
  123. data/lib/action_view/helpers/record_tag_helper.rb +0 -108
  124. data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,141 +1,40 @@
1
- require 'thread_safe'
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+ require "action_view/path_set"
5
+ require "action_view/render_parser"
2
6
 
3
7
  module ActionView
4
8
  class DependencyTracker # :nodoc:
5
- @trackers = ThreadSafe::Cache.new
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :ERBTracker
12
+ autoload :RipperTracker
6
13
 
7
- def self.find_dependencies(name, template)
14
+ @trackers = Concurrent::Map.new
15
+
16
+ def self.find_dependencies(name, template, view_paths = nil)
8
17
  tracker = @trackers[template.handler]
18
+ return [] unless tracker
9
19
 
10
- if tracker.present?
11
- tracker.call(name, template)
12
- else
13
- []
14
- end
20
+ tracker.call(name, template, view_paths)
15
21
  end
16
22
 
17
23
  def self.register_tracker(extension, tracker)
18
24
  handler = Template.handler_for_extension(extension)
19
- @trackers[handler] = tracker
25
+ if tracker.respond_to?(:supports_view_paths?)
26
+ @trackers[handler] = tracker
27
+ else
28
+ @trackers[handler] = lambda { |name, template, _|
29
+ tracker.call(name, template)
30
+ }
31
+ end
20
32
  end
21
33
 
22
34
  def self.remove_tracker(handler)
23
35
  @trackers.delete(handler)
24
36
  end
25
37
 
26
- class ERBTracker # :nodoc:
27
- EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
28
-
29
- # A valid ruby identifier - suitable for class, method and specially variable names
30
- IDENTIFIER = /
31
- [[:alpha:]_] # at least one uppercase letter, lowercase letter or underscore
32
- [[:word:]]* # followed by optional letters, numbers or underscores
33
- /x
34
-
35
- # Any kind of variable name. e.g. @instance, @@class, $global or local.
36
- # Possibly following a method call chain
37
- VARIABLE_OR_METHOD_CHAIN = /
38
- (?:\$|@{1,2})? # optional global, instance or class variable indicator
39
- (?:#{IDENTIFIER}\.)* # followed by an optional chain of zero-argument method calls
40
- (?<dynamic>#{IDENTIFIER}) # and a final valid identifier, captured as DYNAMIC
41
- /x
42
-
43
- # A simple string literal. e.g. "School's out!"
44
- STRING = /
45
- (?<quote>['"]) # an opening quote
46
- (?<static>.*?) # with anything inside, captured as STATIC
47
- \k<quote> # and a matching closing quote
48
- /x
49
-
50
- # Part of any hash containing the :partial key
51
- PARTIAL_HASH_KEY = /
52
- (?:\bpartial:|:partial\s*=>) # partial key in either old or new style hash syntax
53
- \s* # followed by optional spaces
54
- /x
55
-
56
- # Part of any hash containing the :layout key
57
- LAYOUT_HASH_KEY = /
58
- (?:\blayout:|:layout\s*=>) # layout key in either old or new style hash syntax
59
- \s* # followed by optional spaces
60
- /x
61
-
62
- # Matches:
63
- # partial: "comments/comment", collection: @all_comments => "comments/comment"
64
- # (object: @single_comment, partial: "comments/comment") => "comments/comment"
65
- #
66
- # "comments/comments"
67
- # 'comments/comments'
68
- # ('comments/comments')
69
- #
70
- # (@topic) => "topics/topic"
71
- # topics => "topics/topic"
72
- # (message.topics) => "topics/topic"
73
- RENDER_ARGUMENTS = /\A
74
- (?:\s*\(?\s*) # optional opening paren surrounded by spaces
75
- (?:.*?#{PARTIAL_HASH_KEY}|#{LAYOUT_HASH_KEY})? # optional hash, up to the partial or layout key declaration
76
- (?:#{STRING}|#{VARIABLE_OR_METHOD_CHAIN}) # finally, the dependency name of interest
77
- /xm
78
-
79
- def self.call(name, template)
80
- new(name, template).dependencies
81
- end
82
-
83
- def initialize(name, template)
84
- @name, @template = name, template
85
- end
86
-
87
- def dependencies
88
- render_dependencies + explicit_dependencies
89
- end
90
-
91
- attr_reader :name, :template
92
- private :name, :template
93
-
94
-
95
- private
96
- def source
97
- template.source
98
- end
99
-
100
- def directory
101
- name.split("/")[0..-2].join("/")
102
- end
103
-
104
- def render_dependencies
105
- render_dependencies = []
106
- render_calls = source.split(/\brender\b/).drop(1)
107
-
108
- render_calls.each do |arguments|
109
- arguments.scan(RENDER_ARGUMENTS) do
110
- add_dynamic_dependency(render_dependencies, Regexp.last_match[:dynamic])
111
- add_static_dependency(render_dependencies, Regexp.last_match[:static])
112
- end
113
- end
114
-
115
- render_dependencies.uniq
116
- end
117
-
118
- def add_dynamic_dependency(dependencies, dependency)
119
- if dependency
120
- dependencies << "#{dependency.pluralize}/#{dependency.singularize}"
121
- end
122
- end
123
-
124
- def add_static_dependency(dependencies, dependency)
125
- if dependency
126
- if dependency.include?('/')
127
- dependencies << dependency
128
- else
129
- dependencies << "#{directory}/#{dependency}"
130
- end
131
- end
132
- end
133
-
134
- def explicit_dependencies
135
- source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
136
- end
137
- end
138
-
139
38
  register_tracker :erb, ERBTracker
140
39
  end
141
40
  end
@@ -1,123 +1,130 @@
1
- require 'thread_safe'
2
- require 'action_view/dependency_tracker'
3
- require 'monitor'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view/dependency_tracker"
4
4
 
5
5
  module ActionView
6
6
  class Digestor
7
- cattr_reader(:cache)
8
- @@cache = ThreadSafe::Cache.new
9
- @@digest_monitor = Monitor.new
7
+ @@digest_mutex = Mutex.new
10
8
 
11
9
  class << self
12
10
  # Supported options:
13
11
  #
14
- # * <tt>name</tt> - Template name
15
- # * <tt>finder</tt> - An instance of ActionView::LookupContext
16
- # * <tt>dependencies</tt> - An array of dependent views
17
- # * <tt>partial</tt> - Specifies whether the template is a partial
18
- def digest(options)
19
- options.assert_valid_keys(:name, :finder, :dependencies, :partial)
20
-
21
- cache_key = ([ options[:name], options[:finder].details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
12
+ # * <tt>name</tt> - Template name
13
+ # * <tt>format</tt> - Template format
14
+ # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
15
+ # * <tt>dependencies</tt> - An array of dependent views
16
+ def digest(name:, format: nil, finder:, dependencies: nil)
17
+ if dependencies.nil? || dependencies.empty?
18
+ cache_key = "#{name}.#{format}"
19
+ else
20
+ dependencies_suffix = dependencies.flatten.tap(&:compact!).join(".")
21
+ cache_key = "#{name}.#{format}.#{dependencies_suffix}"
22
+ end
22
23
 
23
24
  # this is a correctly done double-checked locking idiom
24
- # (ThreadSafe::Cache's lookups have volatile semantics)
25
- @@cache[cache_key] || @@digest_monitor.synchronize do
26
- @@cache.fetch(cache_key) do # re-check under lock
27
- compute_and_store_digest(cache_key, options)
25
+ # (Concurrent::Map's lookups have volatile semantics)
26
+ finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
27
+ finder.digest_cache.fetch(cache_key) do # re-check under lock
28
+ path = TemplatePath.parse(name)
29
+ root = tree(path.to_s, finder, path.partial?)
30
+ dependencies.each do |injected_dep|
31
+ root.children << Injected.new(injected_dep, nil, nil)
32
+ end if dependencies
33
+ finder.digest_cache[cache_key] = root.digest(finder)
28
34
  end
29
35
  end
30
36
  end
31
37
 
32
- private
33
- def compute_and_store_digest(cache_key, options) # called under @@digest_monitor lock
34
- klass = if options[:partial] || options[:name].include?("/_")
35
- # Prevent re-entry or else recursive templates will blow the stack.
36
- # There is no need to worry about other threads seeing the +false+ value,
37
- # as they will then have to wait for this thread to let go of the @@digest_monitor lock.
38
- pre_stored = @@cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
39
- PartialDigestor
40
- else
41
- Digestor
42
- end
38
+ def logger
39
+ ActionView::Base.logger || NullLogger
40
+ end
43
41
 
44
- digest = klass.new(options).digest
45
- # Store the actual digest if config.cache_template_loading is true
46
- @@cache[cache_key] = stored_digest = digest if ActionView::Resolver.caching?
47
- digest
48
- ensure
49
- # something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
50
- @@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
51
- end
52
- end
42
+ # Create a dependency tree for template named +name+.
43
+ def tree(name, finder, partial = false, seen = {})
44
+ logical_name = name.gsub(%r|/_|, "/")
45
+ interpolated = name.include?("#")
53
46
 
54
- attr_reader :name, :finder, :options
47
+ path = TemplatePath.parse(name)
55
48
 
56
- def initialize(options)
57
- @name, @finder = options.values_at(:name, :finder)
58
- @options = options.except(:name, :finder)
59
- end
49
+ if !interpolated && (template = find_template(finder, path.name, [path.prefix], partial, []))
50
+ if node = seen[template.identifier] # handle cycles in the tree
51
+ node
52
+ else
53
+ node = seen[template.identifier] = Node.create(name, logical_name, template, partial)
60
54
 
61
- def digest
62
- Digest::MD5.hexdigest("#{source}-#{dependency_digest}").tap do |digest|
63
- logger.try :debug, " Cache digest for #{template.inspect}: #{digest}"
55
+ deps = DependencyTracker.find_dependencies(name, template, finder.view_paths)
56
+ deps.uniq { |n| n.gsub(%r|/_|, "/") }.each do |dep_file|
57
+ node.children << tree(dep_file, finder, true, seen)
58
+ end
59
+ node
60
+ end
61
+ else
62
+ unless interpolated # Dynamic template partial names can never be tracked
63
+ logger.error " Couldn't find template for digesting: #{name}"
64
+ end
65
+
66
+ seen[name] ||= Missing.new(name, logical_name, nil)
67
+ end
64
68
  end
65
- rescue ActionView::MissingTemplate
66
- logger.try :error, " Couldn't find template for digesting: #{name}"
67
- ''
68
- end
69
69
 
70
- def dependencies
71
- DependencyTracker.find_dependencies(name, template)
72
- rescue ActionView::MissingTemplate
73
- logger.try :error, " '#{name}' file doesn't exist, so no dependencies"
74
- []
70
+ private
71
+ def find_template(finder, name, prefixes, partial, keys)
72
+ finder.disable_cache do
73
+ finder.find_all(name, prefixes, partial, keys).first
74
+ end
75
+ end
75
76
  end
76
77
 
77
- def nested_dependencies
78
- dependencies.collect do |dependency|
79
- dependencies = PartialDigestor.new(name: dependency, finder: finder).nested_dependencies
80
- dependencies.any? ? { dependency => dependencies } : dependency
81
- end
82
- end
78
+ class Node
79
+ attr_reader :name, :logical_name, :template, :children
83
80
 
84
- private
85
- def logger
86
- ActionView::Base.logger
81
+ def self.create(name, logical_name, template, partial)
82
+ klass = partial ? Partial : Node
83
+ klass.new(name, logical_name, template, [])
87
84
  end
88
85
 
89
- def logical_name
90
- name.gsub(%r|/_|, "/")
86
+ def initialize(name, logical_name, template, children = [])
87
+ @name = name
88
+ @logical_name = logical_name
89
+ @template = template
90
+ @children = children
91
91
  end
92
92
 
93
- def partial?
94
- false
93
+ def digest(finder, stack = [])
94
+ ActiveSupport::Digest.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
95
95
  end
96
96
 
97
- def template
98
- @template ||= finder.disable_cache { finder.find(logical_name, [], partial?) }
97
+ def dependency_digest(finder, stack)
98
+ children.map do |node|
99
+ if stack.include?(node)
100
+ false
101
+ else
102
+ finder.digest_cache[node.name] ||= begin
103
+ stack.push node
104
+ node.digest(finder, stack).tap { stack.pop }
105
+ end
106
+ end
107
+ end.join("-")
99
108
  end
100
109
 
101
- def source
102
- template.source
110
+ def to_dep_map
111
+ children.any? ? { name => children.map(&:to_dep_map) } : name
103
112
  end
113
+ end
104
114
 
105
- def dependency_digest
106
- template_digests = dependencies.collect do |template_name|
107
- Digestor.digest(name: template_name, finder: finder, partial: true)
108
- end
115
+ class Partial < Node; end
109
116
 
110
- (template_digests + injected_dependencies).join("-")
111
- end
117
+ class Missing < Node
118
+ def digest(finder, _ = []) "" end
119
+ end
112
120
 
113
- def injected_dependencies
114
- Array.wrap(options[:dependencies])
115
- end
116
- end
121
+ class Injected < Node
122
+ def digest(finder, _ = []) name end
123
+ end
117
124
 
118
- class PartialDigestor < Digestor # :nodoc:
119
- def partial?
120
- true
125
+ class NullLogger
126
+ def self.debug(_); end
127
+ def self.error(_); end
121
128
  end
122
129
  end
123
130
  end
@@ -1,11 +1,13 @@
1
- require 'active_support/core_ext/string/output_safety'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/output_safety"
2
4
 
3
5
  module ActionView
4
- class OutputFlow #:nodoc:
6
+ class OutputFlow # :nodoc:
5
7
  attr_reader :content
6
8
 
7
9
  def initialize
8
- @content = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
10
+ @content = Hash.new { |h, k| h[k] = ActiveSupport::SafeBuffer.new }
9
11
  end
10
12
 
11
13
  # Called by _layout_for to read stored values.
@@ -15,18 +17,17 @@ module ActionView
15
17
 
16
18
  # Called by each renderer object to set the layout contents.
17
19
  def set(key, value)
18
- @content[key] = ActiveSupport::SafeBuffer.new(value)
20
+ @content[key] = ActiveSupport::SafeBuffer.new(value.to_s)
19
21
  end
20
22
 
21
23
  # Called by content_for
22
24
  def append(key, value)
23
- @content[key] << value
25
+ @content[key] << value.to_s
24
26
  end
25
27
  alias_method :append!, :append
26
-
27
28
  end
28
29
 
29
- class StreamingFlow < OutputFlow #:nodoc:
30
+ class StreamingFlow < OutputFlow # :nodoc:
30
31
  def initialize(view, fiber)
31
32
  @view = view
32
33
  @parent = nil
@@ -37,9 +38,8 @@ module ActionView
37
38
  end
38
39
 
39
40
  # Try to get stored content. If the content
40
- # is not available and we are inside the layout
41
- # fiber, we set that we are waiting for the given
42
- # key and yield.
41
+ # is not available and we're inside the layout fiber,
42
+ # then it will begin waiting for the given key and yield.
43
43
  def get(key)
44
44
  return super if @content.key?(key)
45
45
 
@@ -60,17 +60,16 @@ module ActionView
60
60
  end
61
61
 
62
62
  # Appends the contents for the given key. This is called
63
- # by provides and resumes back to the fiber if it is
64
- # the key it is waiting for.
63
+ # by providing and resuming back to the fiber,
64
+ # if that's the key it's waiting for.
65
65
  def append!(key, value)
66
66
  super
67
67
  @fiber.resume if @waiting_for == key
68
68
  end
69
69
 
70
70
  private
71
-
72
- def inside_fiber?
73
- Fiber.current.object_id != @root
74
- end
71
+ def inside_fiber?
72
+ Fiber.current.object_id != @root
73
+ end
75
74
  end
76
75
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  # Returns the version of the currently loaded Action View as a <tt>Gem::Version</tt>
3
5
  def self.gem_version
@@ -5,10 +7,10 @@ module ActionView
5
7
  end
6
8
 
7
9
  module VERSION
8
- MAJOR = 4
9
- MINOR = 2
10
- TINY = 11
11
- PRE = "1"
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 2
13
+ PRE = "4"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
16
  end
@@ -1,9 +1,11 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/enumerable'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attribute_accessors"
4
+ require "active_support/core_ext/enumerable"
3
5
 
4
6
  module ActionView
5
7
  # = Active Model Helpers
6
- module Helpers
8
+ module Helpers # :nodoc:
7
9
  module ActiveModelHelper
8
10
  end
9
11
 
@@ -15,8 +17,8 @@ module ActionView
15
17
  end
16
18
  end
17
19
 
18
- def content_tag(*)
19
- error_wrapping(super)
20
+ def content_tag(type, options, *)
21
+ select_markup_helper?(type) ? super : error_wrapping(super)
20
22
  end
21
23
 
22
24
  def tag(type, options, *)
@@ -25,7 +27,7 @@ module ActionView
25
27
 
26
28
  def error_wrapping(html_tag)
27
29
  if object_has_errors?
28
- Base.field_error_proc.call(html_tag, self)
30
+ @template_object.instance_exec(html_tag, self, &Base.field_error_proc)
29
31
  else
30
32
  html_tag
31
33
  end
@@ -36,14 +38,17 @@ module ActionView
36
38
  end
37
39
 
38
40
  private
41
+ def object_has_errors?
42
+ object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present?
43
+ end
39
44
 
40
- def object_has_errors?
41
- object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present?
42
- end
45
+ def select_markup_helper?(type)
46
+ ["optgroup", "option"].include?(type)
47
+ end
43
48
 
44
- def tag_generate_errors?(options)
45
- options['type'] != 'hidden'
46
- end
49
+ def tag_generate_errors?(options)
50
+ options["type"] != "hidden"
51
+ end
47
52
  end
48
53
  end
49
54
  end