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 +4 -4
- data/CHANGELOG.md +123 -0
- data/lib/action_view/base.rb +1 -4
- data/lib/action_view/cache_expiry.rb +1 -1
- data/lib/action_view/gem_version.rb +1 -1
- data/lib/action_view/helpers/active_model_helper.rb +1 -1
- data/lib/action_view/helpers/asset_url_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +9 -8
- data/lib/action_view/helpers/date_helper.rb +57 -2
- data/lib/action_view/helpers/form_helper.rb +119 -64
- data/lib/action_view/helpers/form_options_helper.rb +6 -3
- data/lib/action_view/helpers/form_tag_helper.rb +53 -6
- data/lib/action_view/helpers/tag_helper.rb +17 -2
- data/lib/action_view/helpers/tags/base.rb +2 -10
- data/lib/action_view/helpers/tags/check_box.rb +1 -1
- data/lib/action_view/helpers/tags/hidden_field.rb +4 -0
- data/lib/action_view/helpers/tags/weekday_select.rb +2 -1
- data/lib/action_view/helpers/translation_helper.rb +9 -39
- data/lib/action_view/helpers/url_helper.rb +56 -10
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/railtie.rb +5 -6
- data/lib/action_view/template.rb +8 -1
- metadata +13 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fdc27b2d3fd239b03e012b641bd23a23a031aa1363a500604091d9ed9754a26
|
4
|
+
data.tar.gz: c3271b7fb9828ee34975baafe1fa8140327aec4f4f7a5368e101644e90f94120
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/lib/action_view/base.rb
CHANGED
@@ -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|
|
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::
|
7
|
+
@execution_lock = Concurrent::ReentrantReadWriteLock.new
|
8
8
|
@cache_expiry = ViewModificationWatcher.new(watcher: watcher) do
|
9
9
|
clear_cache
|
10
10
|
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
|
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
|
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
|
-
|
296
|
-
extend
|
295
|
+
module CachingRegistry # :nodoc:
|
296
|
+
extend self
|
297
297
|
|
298
|
-
|
299
|
-
|
298
|
+
def caching?
|
299
|
+
ActiveSupport::IsolatedExecutionState[:action_view_caching] ||= false
|
300
|
+
end
|
300
301
|
|
301
|
-
def
|
302
|
-
caching_was =
|
303
|
-
|
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
|
-
|
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
|
-
|
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
|
|