actionview 7.0.0.alpha2 → 7.0.0.rc1

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.

@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "action_view/helpers/tag_helper"
4
+ require "active_support/html_safe_translation"
4
5
 
5
6
  module ActionView
6
7
  # = Action View Translation Helpers
@@ -10,6 +11,9 @@ module ActionView
10
11
 
11
12
  include TagHelper
12
13
 
14
+ # Specify whether an error should be raised for missing translations
15
+ singleton_class.attr_accessor :raise_on_missing_translations
16
+
13
17
  included do
14
18
  mattr_accessor :debug_missing_translation, default: true
15
19
  end
@@ -36,7 +40,7 @@ module ActionView
36
40
  #
37
41
  # If you would prefer missing translations to raise an error, you can
38
42
  # opt out of span-wrapping behavior globally by setting
39
- # <tt>ActionView::Base.raise_on_missing_translations = true</tt> or
43
+ # <tt>config.i18n.raise_on_missing_translations = true</tt> or
40
44
  # individually by passing <tt>raise: true</tt> as an option to
41
45
  # <tt>translate</tt>.
42
46
  #
@@ -74,7 +78,7 @@ module ActionView
74
78
  options[:default].is_a?(Array) ? options.delete(:default).compact : [options.delete(:default)]
75
79
  end
76
80
 
77
- options[:raise] = true if options[:raise].nil? && ActionView::Base.raise_on_missing_translations
81
+ options[:raise] = true if options[:raise].nil? && TranslationHelper.raise_on_missing_translations
78
82
  default = MISSING_TRANSLATION
79
83
 
80
84
  translation = while key || alternatives.present?
@@ -84,14 +88,9 @@ module ActionView
84
88
 
85
89
  key = scope_key_by_partial(key)
86
90
 
87
- if html_safe_translation_key?(key)
88
- html_safe_options ||= html_escape_translation_options(options)
89
- translated = I18n.translate(key, **html_safe_options, default: default)
90
- break html_safe_translation(translated) unless translated.equal?(MISSING_TRANSLATION)
91
- else
92
- translated = I18n.translate(key, **options, default: default)
93
- break translated unless translated.equal?(MISSING_TRANSLATION)
94
- end
91
+ translated = ActiveSupport::HtmlSafeTranslation.translate(key, **options, default: default)
92
+
93
+ break translated unless translated.equal?(MISSING_TRANSLATION)
95
94
 
96
95
  if alternatives.present? && !alternatives.first.is_a?(Symbol)
97
96
  break alternatives.first && I18n.translate(**options, default: alternatives)
@@ -126,10 +125,6 @@ module ActionView
126
125
  NO_DEFAULT = [].freeze
127
126
  private_constant :NO_DEFAULT
128
127
 
129
- def self.i18n_option?(name)
130
- (@i18n_option_names ||= I18n::RESERVED_KEYS.to_set).include?(name)
131
- end
132
-
133
128
  def scope_key_by_partial(key)
134
129
  if key&.start_with?(".")
135
130
  if @virtual_path
@@ -144,31 +139,6 @@ module ActionView
144
139
  end
145
140
  end
146
141
 
147
- def html_escape_translation_options(options)
148
- return options if options.empty?
149
- html_safe_options = options.dup
150
-
151
- options.each do |name, value|
152
- unless TranslationHelper.i18n_option?(name) || (name == :count && value.is_a?(Numeric))
153
- html_safe_options[name] = ERB::Util.html_escape(value.to_s)
154
- end
155
- end
156
-
157
- html_safe_options
158
- end
159
-
160
- def html_safe_translation_key?(key)
161
- /(?:_|\b)html\z/.match?(key)
162
- end
163
-
164
- def html_safe_translation(translation)
165
- if translation.respond_to?(:map)
166
- translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element }
167
- else
168
- translation.respond_to?(:html_safe) ? translation.html_safe : translation
169
- end
170
- end
171
-
172
142
  def missing_translation(key, options)
173
143
  keys = I18n.normalize_keys(options[:locale] || I18n.locale, key, options[:scope])
174
144
 
@@ -85,6 +85,8 @@ module ActionView
85
85
  # # name
86
86
  # end
87
87
  #
88
+ # link_to(active_record_model)
89
+ #
88
90
  # ==== Options
89
91
  # * <tt>:data</tt> - This option can be used to add custom data attributes.
90
92
  # * <tt>method: symbol of HTTP verb</tt> - This modifier will dynamically
@@ -137,6 +139,12 @@ module ActionView
137
139
  # link_to nil, "http://example.com"
138
140
  # # => <a href="http://www.example.com">http://www.example.com</a>
139
141
  #
142
+ # More concise yet, when +name+ is an Active Record model that defines a
143
+ # +to_s+ method returning a default value or a model instance attribute
144
+ #
145
+ # link_to @profile
146
+ # # => <a href="http://www.example.com/profiles/1">Eileen</a>
147
+ #
140
148
  # You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
141
149
  #
142
150
  # <%= link_to(@profile) do %>
@@ -204,7 +212,7 @@ module ActionView
204
212
 
205
213
  html_options = convert_options_to_data_attributes(options, html_options)
206
214
 
207
- url = url_for(options)
215
+ url = url_target(name, options)
208
216
  html_options["href"] ||= url
209
217
 
210
218
  content_tag("a", name || url, html_options, &block)
@@ -230,7 +238,15 @@ module ActionView
230
238
  # HTTP verb via the +:method+ option within +html_options+.
231
239
  #
232
240
  # ==== Options
233
- # The +options+ hash accepts the same options as +url_for+.
241
+ # The +options+ hash accepts the same options as +url_for+. To generate a
242
+ # <tt><form></tt> element without an <tt>[action]</tt> attribute, pass
243
+ # <tt>false</tt>:
244
+ #
245
+ # <%= button_to "New", false %>
246
+ # # => "<form method="post" class="button_to">
247
+ # # <button type="submit">New</button>
248
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
249
+ # # </form>"
234
250
  #
235
251
  # Most values in +html_options+ are passed through to the button element,
236
252
  # but there are a few special options:
@@ -316,15 +332,21 @@ module ActionView
316
332
  # #
317
333
  def button_to(name = nil, options = nil, html_options = nil, &block)
318
334
  html_options, options = options, name if block_given?
319
- options ||= {}
320
335
  html_options ||= {}
321
336
  html_options = html_options.stringify_keys
322
337
 
323
- url = options.is_a?(String) ? options : url_for(options)
338
+ url =
339
+ case options
340
+ when FalseClass then nil
341
+ else url_for(options)
342
+ end
343
+
324
344
  remote = html_options.delete("remote")
325
345
  params = html_options.delete("params")
326
346
 
327
- method = html_options.delete("method").to_s
347
+ authenticity_token = html_options.delete("authenticity_token")
348
+
349
+ method = (html_options.delete("method").presence || method_for_options(options)).to_s
328
350
  method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".html_safe
329
351
 
330
352
  form_method = method == "get" ? "get" : "post"
@@ -336,7 +358,7 @@ module ActionView
336
358
 
337
359
  request_token_tag = if form_method == "post"
338
360
  request_method = method.empty? ? "post" : method
339
- token_tag(nil, form_options: { action: url, method: request_method })
361
+ token_tag(authenticity_token, form_options: { action: url, method: request_method })
340
362
  else
341
363
  ""
342
364
  end
@@ -354,7 +376,8 @@ module ActionView
354
376
  inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
355
377
  if params
356
378
  to_form_params(params).each do |param|
357
- inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value])
379
+ inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value],
380
+ autocomplete: "off")
358
381
  end
359
382
  end
360
383
  content_tag("form", inner_tags, form_options)
@@ -719,6 +742,14 @@ module ActionView
719
742
  end
720
743
  end
721
744
 
745
+ def url_target(name, options)
746
+ if name.respond_to?(:model_name) && options.empty?
747
+ url_for(name)
748
+ else
749
+ url_for(options)
750
+ end
751
+ end
752
+
722
753
  def link_to_remote_options?(options)
723
754
  if options.is_a?(Hash)
724
755
  options.delete("remote") || options.delete(:remote)
@@ -736,6 +767,16 @@ module ActionView
736
767
  html_options["data-method"] = method
737
768
  end
738
769
 
770
+ def method_for_options(options)
771
+ if options.is_a?(Array)
772
+ method_for_options(options.last)
773
+ elsif options.respond_to?(:persisted?)
774
+ options.persisted? ? :patch : :post
775
+ elsif options.respond_to?(:to_model)
776
+ method_for_options(options.to_model)
777
+ end
778
+ end
779
+
739
780
  STRINGIFIED_COMMON_METHODS = {
740
781
  get: "get",
741
782
  delete: "delete",
@@ -751,15 +792,20 @@ module ActionView
751
792
 
752
793
  def token_tag(token = nil, form_options: {})
753
794
  if token != false && defined?(protect_against_forgery?) && protect_against_forgery?
754
- token ||= form_authenticity_token(form_options: form_options)
755
- tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
795
+ token =
796
+ if token == true || token.nil?
797
+ form_authenticity_token(form_options: form_options.merge(authenticity_token: token))
798
+ else
799
+ token
800
+ end
801
+ tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token, autocomplete: "off")
756
802
  else
757
803
  ""
758
804
  end
759
805
  end
760
806
 
761
807
  def method_tag(method)
762
- tag("input", type: "hidden", name: "_method", value: method.to_s)
808
+ tag("input", type: "hidden", name: "_method", value: method.to_s, autocomplete: "off")
763
809
  end
764
810
 
765
811
  # Returns an array of hashes each containing :name and :value keys
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActionView
4
4
  module ModelNaming # :nodoc:
5
- # Converts the given object to an ActiveModel compliant one.
5
+ # Converts the given object to an Active Model compliant one.
6
6
  def convert_to_model(object)
7
7
  object.respond_to?(:to_model) ? object.to_model : object
8
8
  end
@@ -47,6 +47,11 @@ module ActionView
47
47
  end
48
48
  end
49
49
 
50
+ config.after_initialize do |app|
51
+ frozen_string_literal = app.config.action_view.delete(:frozen_string_literal)
52
+ ActionView::Template.frozen_string_literal = frozen_string_literal
53
+ end
54
+
50
55
  config.after_initialize do |app|
51
56
  ActionView::Helpers::AssetTagHelper.image_loading = app.config.action_view.delete(:image_loading)
52
57
  ActionView::Helpers::AssetTagHelper.image_decoding = app.config.action_view.delete(:image_decoding)
@@ -57,12 +62,6 @@ module ActionView
57
62
  config.after_initialize do |app|
58
63
  ActiveSupport.on_load(:action_view) do
59
64
  app.config.action_view.each do |k, v|
60
- if k == :raise_on_missing_translations
61
- ActiveSupport::Deprecation.warn \
62
- "action_view.raise_on_missing_translations is deprecated and will be removed in Rails 7.0. " \
63
- "Set i18n.raise_on_missing_translations instead. " \
64
- "Note that this new setting also affects how missing translations are handled in controllers."
65
- end
66
65
  send "#{k}=", v
67
66
  end
68
67
  end
@@ -114,6 +114,9 @@ module ActionView
114
114
 
115
115
  extend Template::Handlers
116
116
 
117
+ singleton_class.attr_accessor :frozen_string_literal
118
+ @frozen_string_literal = false
119
+
117
120
  attr_reader :identifier, :handler
118
121
  attr_reader :variable, :format, :variant, :locals, :virtual_path
119
122
 
@@ -297,7 +300,11 @@ module ActionView
297
300
  end
298
301
 
299
302
  begin
300
- mod.module_eval(source, identifier, 0)
303
+ if Template.frozen_string_literal
304
+ mod.module_eval("# frozen_string_literal: true\n#{source}", identifier, -1)
305
+ else
306
+ mod.module_eval(source, identifier, 0)
307
+ end
301
308
  rescue SyntaxError
302
309
  # Account for when code in the template is not syntactically valid; e.g. if we're using
303
310
  # ERB and the user writes <%= foo( %>, attempting to call a helper `foo` and interpolate
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0.alpha2
4
+ version: 7.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-15 00:00:00.000000000 Z
11
+ date: 2021-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0.alpha2
19
+ version: 7.0.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.0.alpha2
26
+ version: 7.0.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: builder
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -92,28 +92,28 @@ dependencies:
92
92
  requirements:
93
93
  - - '='
94
94
  - !ruby/object:Gem::Version
95
- version: 7.0.0.alpha2
95
+ version: 7.0.0.rc1
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: 7.0.0.alpha2
102
+ version: 7.0.0.rc1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: activemodel
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 7.0.0.alpha2
109
+ version: 7.0.0.rc1
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - '='
115
115
  - !ruby/object:Gem::Version
116
- version: 7.0.0.alpha2
116
+ version: 7.0.0.rc1
117
117
  description: Simple, battle-tested conventions and helpers for building web pages.
118
118
  email: david@loudthinking.com
119
119
  executables: []
@@ -246,10 +246,11 @@ licenses:
246
246
  - MIT
247
247
  metadata:
248
248
  bug_tracker_uri: https://github.com/rails/rails/issues
249
- changelog_uri: https://github.com/rails/rails/blob/v7.0.0.alpha2/actionview/CHANGELOG.md
250
- documentation_uri: https://api.rubyonrails.org/v7.0.0.alpha2/
249
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.0.rc1/actionview/CHANGELOG.md
250
+ documentation_uri: https://api.rubyonrails.org/v7.0.0.rc1/
251
251
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
252
- source_code_uri: https://github.com/rails/rails/tree/v7.0.0.alpha2/actionview
252
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.0.rc1/actionview
253
+ rubygems_mfa_required: 'true'
253
254
  post_install_message:
254
255
  rdoc_options: []
255
256
  require_paths:
@@ -266,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
267
  version: 1.3.1
267
268
  requirements:
268
269
  - none
269
- rubygems_version: 3.1.6
270
+ rubygems_version: 3.2.22
270
271
  signing_key:
271
272
  specification_version: 4
272
273
  summary: Rendering framework putting the V in MVC (part of Rails).