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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 10a4345b17834e9593bf0b42ccd2170b3cbf15e12f90b46d5022d3f42debe197
4
- data.tar.gz: fe8446b4f105e3dd0b071fb3bd2da626d62221bc10ef3da4f2ba67165e6c4f39
3
+ metadata.gz: 1fdc27b2d3fd239b03e012b641bd23a23a031aa1363a500604091d9ed9754a26
4
+ data.tar.gz: c3271b7fb9828ee34975baafe1fa8140327aec4f4f7a5368e101644e90f94120
5
5
  SHA512:
6
- metadata.gz: eac9c7426ef7c9562fcb5da319e2b553e7703f0ecd3eb7341120d69abf4dd52fe3de8e9f4f179de8c4ed91864ddcf47bb5c80a0c727b4b1bc1063a996cad6527
7
- data.tar.gz: 9ea9389303fa84db67be4603551b2fa71542ede511479f9f7430a55b2d519b4c88305b167167849d19b5b249e33d45a5ab666a860536b9843a7aeed7cfbbcd40
6
+ metadata.gz: 93c9d5284b53225c766696483e059f5063a495a2f46179c575fc5538fdb523e3a313385b308a8242dfc839b489d803cdbcedf7effb6a56ff6d8e0ac67a1272b1
7
+ data.tar.gz: ab29bbd902f1a4cf97cd7b23b71a202918bdfaf461a9ffec421f671d2eb68a1834b5f74179278b662d5fa3bb315e35e1e517912336a72f2224b81a674645270a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,126 @@
1
+ * Support `fields model: [@nested, @model]` the same way as `form_with model:
2
+ [@nested, @model]`.
3
+
4
+ *Sean Doyle*
5
+
6
+ * Infer HTTP verb `[method]` from a model or Array with model as the first
7
+ argument to `button_to` when combined with a block:
8
+
9
+ ```ruby
10
+ button_to(Workshop.find(1)){ "Update" }
11
+ #=> <form method="post" action="/workshops/1" class="button_to">
12
+ #=> <input type="hidden" name="_method" value="patch" autocomplete="off" />
13
+ #=> <button type="submit">Update</button>
14
+ #=> </form>
15
+
16
+ button_to([ Workshop.find(1), Session.find(1) ]) { "Update" }
17
+ #=> <form method="post" action="/workshops/1/sessions/1" class="button_to">
18
+ #=> <input type="hidden" name="_method" value="patch" autocomplete="off" />
19
+ #=> <button type="submit">Update</button>
20
+ #=> </form>
21
+ ```
22
+
23
+ *Sean Doyle*
24
+
25
+ * Support passing a Symbol as the first argument to `FormBuilder#button`:
26
+
27
+ ```ruby
28
+ form.button(:draft, value: true)
29
+ # => <button name="post[draft]" value="true" type="submit">Create post</button>
30
+
31
+ form.button(:draft, value: true) do
32
+ content_tag(:strong, "Save as draft")
33
+ end
34
+ # => <button name="post[draft]" value="true" type="submit">
35
+ # <strong>Save as draft</strong>
36
+ # </button>
37
+ ```
38
+
39
+ *Sean Doyle*
40
+
41
+ * Introduce the `field_name` view helper, along with the
42
+ `FormBuilder#field_name` counterpart:
43
+
44
+ ```ruby
45
+ form_for @post do |f|
46
+ f.field_tag :tag, name: f.field_name(:tag, multiple: true)
47
+ # => <input type="text" name="post[tag][]">
48
+ end
49
+ ```
50
+
51
+ *Sean Doyle*
52
+
53
+ * Execute the `ActionView::Base.field_error_proc` within the context of the
54
+ `ActionView::Base` instance:
55
+
56
+ ```ruby
57
+ config.action_view.field_error_proc = proc { |html| content_tag(:div, html, class: "field_with_errors") }
58
+ ```
59
+
60
+ *Sean Doyle*
61
+
62
+ * Add support for `button_to ..., authenticity_token: false`
63
+
64
+ ```ruby
65
+ button_to "Create", Post.new, authenticity_token: false
66
+ # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button></form>
67
+
68
+ button_to "Create", Post.new, authenticity_token: true
69
+ # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button><input type="hidden" name="form_token" value="abc123..." autocomplete="off" /></form>
70
+
71
+ button_to "Create", Post.new, authenticity_token: "secret"
72
+ # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button><input type="hidden" name="form_token" value="secret" autocomplete="off" /></form>
73
+ ```
74
+
75
+ *Sean Doyle*
76
+
77
+ * Support rendering `<form>` elements _without_ `[action]` attributes by:
78
+
79
+ * `form_with url: false` or `form_with ..., html: { action: false }`
80
+ * `form_for ..., url: false` or `form_for ..., html: { action: false }`
81
+ * `form_tag false` or `form_tag ..., action: false`
82
+ * `button_to "...", false` or `button_to(false) { ... }`
83
+
84
+ *Sean Doyle*
85
+
86
+ * Add `:day_format` option to `date_select`
87
+
88
+ date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
89
+ # generates day options like <option value="1">1st</option>\n<option value="2">2nd</option>...
90
+
91
+ *Shunichi Ikegami*
92
+
93
+ * Allow `link_to` helper to infer link name from `Model#to_s` when it
94
+ is used with a single argument:
95
+
96
+ link_to @profile
97
+ #=> <a href="/profiles/1">Eileen</a>
98
+
99
+ This assumes the model class implements a `to_s` method like this:
100
+
101
+ class Profile < ApplicationRecord
102
+ # ...
103
+ def to_s
104
+ name
105
+ end
106
+ end
107
+
108
+ Previously you had to supply a second argument even if the `Profile`
109
+ model implemented a `#to_s` method that called the `name` method.
110
+
111
+ link_to @profile, @profile.name
112
+ #=> <a href="/profiles/1">Eileen</a>
113
+
114
+ *Olivier Lacan*
115
+
116
+ * Support svg unpaired tags for `tag` helper.
117
+
118
+ tag.svg { tag.use('href' => "#cool-icon") }
119
+ # => <svg><use href="#cool-icon"></svg>
120
+
121
+ *Oleksii Vasyliev*
122
+
123
+
1
124
  ## Rails 7.0.0.alpha2 (September 15, 2021) ##
2
125
 
3
126
  * No changes.
@@ -142,7 +142,7 @@ module ActionView # :nodoc:
142
142
  include Helpers, ::ERB::Util, Context
143
143
 
144
144
  # Specify the proc used to decorate input tags that refer to attributes with errors.
145
- cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
145
+ cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| content_tag :div, html_tag, class: "field_with_errors" }
146
146
 
147
147
  # How to complete the streaming when an exception occurs.
148
148
  # This is our best guess: first try to close the attribute, then the tag.
@@ -156,9 +156,6 @@ module ActionView # :nodoc:
156
156
  # Specify default_formats that can be rendered.
157
157
  cattr_accessor :default_formats
158
158
 
159
- # Specify whether an error should be raised for missing translations
160
- cattr_accessor :raise_on_missing_translations, default: false
161
-
162
159
  # Specify whether submit_tag should automatically disable on click
163
160
  cattr_accessor :automatically_disable_submit_tag, default: true
164
161
 
@@ -4,7 +4,7 @@ module ActionView
4
4
  class CacheExpiry
5
5
  class Executor
6
6
  def initialize(watcher:)
7
- @execution_lock = Concurrent::ReadWriteLock.new
7
+ @execution_lock = Concurrent::ReentrantReadWriteLock.new
8
8
  @cache_expiry = ViewModificationWatcher.new(watcher: watcher) do
9
9
  clear_cache
10
10
  end
@@ -10,7 +10,7 @@ module ActionView
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "alpha2"
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -27,7 +27,7 @@ module ActionView
27
27
 
28
28
  def error_wrapping(html_tag)
29
29
  if object_has_errors?
30
- Base.field_error_proc.call(html_tag, self)
30
+ @template_object.instance_exec(html_tag, self, &Base.field_error_proc)
31
31
  else
32
32
  html_tag
33
33
  end
@@ -121,7 +121,7 @@ module ActionView
121
121
  URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}i
122
122
 
123
123
  # This is the entry point for all assets.
124
- # When using the asset pipeline (i.e. sprockets and sprockets-rails), the
124
+ # When using an asset pipeline gem (e.g. propshaft or sprockets-rails), the
125
125
  # behavior is "enhanced". You can bypass the asset pipeline by passing in
126
126
  # <tt>skip_pipeline: true</tt> to the options.
127
127
  #
@@ -130,7 +130,7 @@ module ActionView
130
130
  # === With the asset pipeline
131
131
  #
132
132
  # All options passed to +asset_path+ will be passed to +compute_asset_path+
133
- # which is implemented by sprockets-rails.
133
+ # which is implemented by asset pipeline gems.
134
134
  #
135
135
  # asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
136
136
  # asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
@@ -292,19 +292,20 @@ module ActionView
292
292
  controller.write_fragment(name, fragment, options)
293
293
  end
294
294
 
295
- class CachingRegistry
296
- extend ActiveSupport::PerThreadRegistry
295
+ module CachingRegistry # :nodoc:
296
+ extend self
297
297
 
298
- attr_accessor :caching
299
- alias caching? caching
298
+ def caching?
299
+ ActiveSupport::IsolatedExecutionState[:action_view_caching] ||= false
300
+ end
300
301
 
301
- def self.track_caching
302
- caching_was = self.caching
303
- self.caching = true
302
+ def track_caching
303
+ caching_was = ActiveSupport::IsolatedExecutionState[:action_view_caching]
304
+ ActiveSupport::IsolatedExecutionState[:action_view_caching] = true
304
305
 
305
306
  yield
306
307
  ensure
307
- self.caching = caching_was
308
+ ActiveSupport::IsolatedExecutionState[:action_view_caching] = caching_was
308
309
  end
309
310
  end
310
311
  end
@@ -206,6 +206,7 @@ module ActionView
206
206
  # you are creating new record. While editing existing record, <tt>:end_year</tt> defaults to
207
207
  # the current selected year plus 5.
208
208
  # * <tt>:year_format</tt> - Set format of years for year select. Lambda should be passed.
209
+ # * <tt>:day_format</tt> - Set format of days for day select. Lambda should be passed.
209
210
  # * <tt>:discard_day</tt> - Set to true if you don't want to show a day select. This includes the day
210
211
  # as a hidden field instead of showing a select field. Also note that this implicitly sets the day to be the
211
212
  # first of the given month in order to not create invalid dates like 31 February.
@@ -279,6 +280,9 @@ module ActionView
279
280
  # # Generates a date select with custom year format.
280
281
  # date_select("article", "written_on", year_format: ->(year) { "Heisei #{year - 1988}" })
281
282
  #
283
+ # # Generates a date select with custom day format.
284
+ # date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
285
+ #
282
286
  # The selects are prepared for multi-parameter assignment to an Active Record object.
283
287
  #
284
288
  # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
@@ -811,7 +815,7 @@ module ActionView
811
815
  if @options[:use_hidden] || @options[:discard_day]
812
816
  build_hidden(:day, day || 1)
813
817
  else
814
- build_options_and_select(:day, day, start: 1, end: 31, leading_zeros: false, use_two_digit_numbers: @options[:use_two_digit_numbers])
818
+ build_select(:day, build_day_options(day))
815
819
  end
816
820
  end
817
821
 
@@ -899,6 +903,27 @@ module ActionView
899
903
  I18n.translate(key, locale: @options[:locale])
900
904
  end
901
905
 
906
+ # Looks up day names by number.
907
+ #
908
+ # day_name(1) # => 1
909
+ #
910
+ # If the <tt>use_two_digit_numbers: true</tt> option is passed to DateTimeSelector:
911
+ #
912
+ # day_name(1) # => "01"
913
+ #
914
+ # If the <tt>day_format: ->(day) { day.ordinalize }</tt> option is passed to DateTimeSelector:
915
+ #
916
+ # day_name(1) # => "1st"
917
+ def day_name(number)
918
+ if day_format_lambda = @options[:day_format]
919
+ day_format_lambda.call(number)
920
+ elsif @options[:use_two_digit_numbers]
921
+ "%02d" % number
922
+ else
923
+ number
924
+ end
925
+ end
926
+
902
927
  # Looks up month names by number (1-based):
903
928
  #
904
929
  # month_name(1) # => "January"
@@ -1011,6 +1036,35 @@ module ActionView
1011
1036
  (select_options.join("\n") + "\n").html_safe
1012
1037
  end
1013
1038
 
1039
+ # Build select option HTML for day.
1040
+ # build_day_options(2)
1041
+ # => "<option value="1">1</option>
1042
+ # <option value="2" selected="selected">2</option>
1043
+ # <option value="3">3</option>..."
1044
+ #
1045
+ # If <tt>day_format: ->(day) { day.ordinalize }</tt> option is passed to DateTimeSelector
1046
+ # build_day_options(2)
1047
+ # => "<option value="1">1st</option>
1048
+ # <option value="2" selected="selected">2nd</option>
1049
+ # <option value="3">3rd</option>..."
1050
+ #
1051
+ # If <tt>use_two_digit_numbers: true</tt> option is passed to DateTimeSelector
1052
+ # build_day_options(2)
1053
+ # => "<option value="1">01</option>
1054
+ # <option value="2" selected="selected">02</option>
1055
+ # <option value="3">03</option>..."
1056
+ def build_day_options(selected)
1057
+ select_options = []
1058
+ (1..31).each do |value|
1059
+ tag_options = { value: value }
1060
+ tag_options[:selected] = "selected" if selected == value
1061
+ text = day_name(value)
1062
+ select_options << content_tag("option", text, tag_options)
1063
+ end
1064
+
1065
+ (select_options.join("\n") + "\n").html_safe
1066
+ end
1067
+
1014
1068
  # Build select option HTML for year.
1015
1069
  # If <tt>year_format</tt> option is not passed
1016
1070
  # build_year_options(1998, start: 1998, end: 2000)
@@ -1101,7 +1155,8 @@ module ActionView
1101
1155
  type: "hidden",
1102
1156
  id: input_id_from_type(type),
1103
1157
  name: input_name_from_type(type),
1104
- value: value
1158
+ value: value,
1159
+ autocomplete: "off"
1105
1160
  }.merge!(@html_options.slice(:disabled))
1106
1161
  select_options[:disabled] = "disabled" if @options[:disabled]
1107
1162