actionview 4.2.10 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +141 -272
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view/base.rb +33 -21
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +52 -20
- data/lib/action_view/digestor.rb +86 -83
- data/lib/action_view/flows.rb +9 -11
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +8 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +74 -38
- data/lib/action_view/helpers/asset_url_helper.rb +160 -59
- data/lib/action_view/helpers/atom_feed_helper.rb +16 -16
- data/lib/action_view/helpers/cache_helper.rb +90 -35
- data/lib/action_view/helpers/capture_helper.rb +7 -6
- data/lib/action_view/helpers/controller_helper.rb +3 -2
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +156 -108
- data/lib/action_view/helpers/debug_helper.rb +3 -4
- data/lib/action_view/helpers/form_helper.rb +475 -94
- data/lib/action_view/helpers/form_options_helper.rb +87 -47
- data/lib/action_view/helpers/form_tag_helper.rb +88 -57
- data/lib/action_view/helpers/javascript_helper.rb +10 -10
- data/lib/action_view/helpers/number_helper.rb +76 -59
- data/lib/action_view/helpers/output_safety_helper.rb +34 -4
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +3 -3
- data/lib/action_view/helpers/sanitize_helper.rb +17 -14
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +132 -97
- data/lib/action_view/helpers/tags/check_box.rb +17 -17
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +9 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +68 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +3 -11
- data/lib/action_view/helpers/tags/collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/date_select.rb +36 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/label.rb +5 -1
- data/lib/action_view/helpers/tags/password_field.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/radio_button.rb +4 -4
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/select.rb +9 -9
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +5 -6
- data/lib/action_view/helpers/tags/translator.rb +15 -13
- data/lib/action_view/helpers/text_helper.rb +47 -30
- data/lib/action_view/helpers/translation_helper.rb +60 -30
- data/lib/action_view/helpers/url_helper.rb +132 -104
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/layouts.rb +59 -54
- data/lib/action_view/log_subscriber.rb +56 -7
- data/lib/action_view/lookup_context.rb +76 -61
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +28 -19
- data/lib/action_view/railtie.rb +30 -6
- data/lib/action_view/record_identifier.rb +51 -25
- data/lib/action_view/renderer/abstract_renderer.rb +19 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +55 -0
- data/lib/action_view/renderer/partial_renderer.rb +208 -206
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +46 -48
- data/lib/action_view/renderer/template_renderer.rb +65 -66
- data/lib/action_view/rendering.rb +16 -9
- data/lib/action_view/routing_url_for.rb +25 -17
- data/lib/action_view/tasks/cache_digests.rake +23 -0
- data/lib/action_view/template/error.rb +14 -13
- data/lib/action_view/template/handlers/builder.rb +7 -7
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +9 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +81 -0
- data/lib/action_view/template/handlers/erb/erubis.rb +81 -0
- data/lib/action_view/template/handlers/erb.rb +9 -76
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/handlers.rb +8 -6
- data/lib/action_view/template/html.rb +2 -4
- data/lib/action_view/template/resolver.rb +133 -109
- data/lib/action_view/template/text.rb +5 -8
- data/lib/action_view/template/types.rb +15 -17
- data/lib/action_view/template.rb +51 -28
- data/lib/action_view/test_case.rb +32 -27
- data/lib/action_view/testing/resolvers.rb +29 -31
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +26 -32
- data/lib/action_view.rb +5 -5
- data/lib/assets/compiled/rails-ujs.js +685 -0
- metadata +23 -23
- data/lib/action_view/tasks/dependencies.rake +0 -23
|
@@ -39,13 +39,13 @@ module ActionView
|
|
|
39
39
|
# This will include both records as part of the cache key and updating either of them will
|
|
40
40
|
# expire the cache.
|
|
41
41
|
#
|
|
42
|
-
# ==== Template digest
|
|
42
|
+
# ==== \Template digest
|
|
43
43
|
#
|
|
44
|
-
# The template digest that's added to the cache key is computed by taking an
|
|
44
|
+
# The template digest that's added to the cache key is computed by taking an MD5 of the
|
|
45
45
|
# contents of the entire template file. This ensures that your caches will automatically
|
|
46
46
|
# expire when you change the template file.
|
|
47
47
|
#
|
|
48
|
-
# Note that the
|
|
48
|
+
# Note that the MD5 is taken of the entire template file, not just what's within the
|
|
49
49
|
# cache do/end call. So it's possible that changing something outside of that call will
|
|
50
50
|
# still expire the cache.
|
|
51
51
|
#
|
|
@@ -69,13 +69,14 @@ module ActionView
|
|
|
69
69
|
# render 'comments/comments'
|
|
70
70
|
# render('comments/comments')
|
|
71
71
|
#
|
|
72
|
-
# render "header"
|
|
72
|
+
# render "header" translates to render("comments/header")
|
|
73
73
|
#
|
|
74
|
-
# render(@topic)
|
|
75
|
-
# render(topics)
|
|
76
|
-
# render(message.topics)
|
|
74
|
+
# render(@topic) translates to render("topics/topic")
|
|
75
|
+
# render(topics) translates to render("topics/topic")
|
|
76
|
+
# render(message.topics) translates to render("topics/topic")
|
|
77
77
|
#
|
|
78
|
-
# It's not possible to derive all render calls like that, though.
|
|
78
|
+
# It's not possible to derive all render calls like that, though.
|
|
79
|
+
# Here are a few examples of things that can't be derived:
|
|
79
80
|
#
|
|
80
81
|
# render group_of_attachments
|
|
81
82
|
# render @project.documents.where(published: true).order('created_at')
|
|
@@ -87,7 +88,7 @@ module ActionView
|
|
|
87
88
|
#
|
|
88
89
|
# === Explicit dependencies
|
|
89
90
|
#
|
|
90
|
-
#
|
|
91
|
+
# Sometimes you'll have template dependencies that can't be derived at all. This is typically
|
|
91
92
|
# the case when you have template rendering that happens in helpers. Here's an example:
|
|
92
93
|
#
|
|
93
94
|
# <%= render_sortable_todolists @project.todolists %>
|
|
@@ -97,22 +98,70 @@ module ActionView
|
|
|
97
98
|
# <%# Template Dependency: todolists/todolist %>
|
|
98
99
|
# <%= render_sortable_todolists @project.todolists %>
|
|
99
100
|
#
|
|
100
|
-
#
|
|
101
|
+
# In some cases, like a single table inheritance setup, you might have
|
|
102
|
+
# a bunch of explicit dependencies. Instead of writing every template out,
|
|
103
|
+
# you can use a wildcard to match any template in a directory:
|
|
104
|
+
#
|
|
105
|
+
# <%# Template Dependency: events/* %>
|
|
106
|
+
# <%= render_categorizable_events @person.events %>
|
|
107
|
+
#
|
|
108
|
+
# This marks every template in the directory as a dependency. To find those
|
|
109
|
+
# templates, the wildcard path must be absolutely defined from app/views or paths
|
|
110
|
+
# otherwise added with +prepend_view_path+ or +append_view_path+.
|
|
111
|
+
# This way the wildcard for `app/views/recordings/events` would be `recordings/events/*` etc.
|
|
112
|
+
#
|
|
113
|
+
# The pattern used to match explicit dependencies is <tt>/# Template Dependency: (\S+)/</tt>,
|
|
114
|
+
# so it's important that you type it out just so.
|
|
101
115
|
# You can only declare one template dependency per line.
|
|
102
116
|
#
|
|
103
117
|
# === External dependencies
|
|
104
118
|
#
|
|
105
|
-
# If you use a helper method, for example, inside
|
|
106
|
-
# you'll have to bump the cache as well.
|
|
119
|
+
# If you use a helper method, for example, inside a cached block and
|
|
120
|
+
# you then update that helper, you'll have to bump the cache as well.
|
|
121
|
+
# It doesn't really matter how you do it, but the MD5 of the template file
|
|
107
122
|
# must change. One recommendation is to simply be explicit in a comment, like:
|
|
108
123
|
#
|
|
109
124
|
# <%# Helper Dependency Updated: May 6, 2012 at 6pm %>
|
|
110
125
|
# <%= some_helper_method(person) %>
|
|
111
126
|
#
|
|
112
|
-
# Now all you
|
|
113
|
-
|
|
127
|
+
# Now all you have to do is change that timestamp when the helper method changes.
|
|
128
|
+
#
|
|
129
|
+
# === Collection Caching
|
|
130
|
+
#
|
|
131
|
+
# When rendering a collection of objects that each use the same partial, a `cached`
|
|
132
|
+
# option can be passed.
|
|
133
|
+
#
|
|
134
|
+
# For collections rendered such:
|
|
135
|
+
#
|
|
136
|
+
# <%= render partial: 'projects/project', collection: @projects, cached: true %>
|
|
137
|
+
#
|
|
138
|
+
# The `cached: true` will make Action View's rendering read several templates
|
|
139
|
+
# from cache at once instead of one call per template.
|
|
140
|
+
#
|
|
141
|
+
# Templates in the collection not already cached are written to cache.
|
|
142
|
+
#
|
|
143
|
+
# Works great alongside individual template fragment caching.
|
|
144
|
+
# For instance if the template the collection renders is cached like:
|
|
145
|
+
#
|
|
146
|
+
# # projects/_project.html.erb
|
|
147
|
+
# <% cache project do %>
|
|
148
|
+
# <%# ... %>
|
|
149
|
+
# <% end %>
|
|
150
|
+
#
|
|
151
|
+
# Any collection renders will find those cached templates when attempting
|
|
152
|
+
# to read multiple templates at once.
|
|
153
|
+
#
|
|
154
|
+
# If your collection cache depends on multiple sources (try to avoid this to keep things simple),
|
|
155
|
+
# you can name all these dependencies as part of a block that returns an array:
|
|
156
|
+
#
|
|
157
|
+
# <%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %>
|
|
158
|
+
#
|
|
159
|
+
# This will include both records as part of the cache key and updating either of them will
|
|
160
|
+
# expire the cache.
|
|
161
|
+
def cache(name = {}, options = {}, &block)
|
|
114
162
|
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
|
115
|
-
|
|
163
|
+
name_options = options.slice(:skip_digest, :virtual_path)
|
|
164
|
+
safe_concat(fragment_for(cache_fragment_name(name, name_options), options, &block))
|
|
116
165
|
else
|
|
117
166
|
yield
|
|
118
167
|
end
|
|
@@ -126,7 +175,7 @@ module ActionView
|
|
|
126
175
|
# <b>All the topics on this project</b>
|
|
127
176
|
# <%= render project.topics %>
|
|
128
177
|
# <% end %>
|
|
129
|
-
def cache_if(condition, name = {}, options =
|
|
178
|
+
def cache_if(condition, name = {}, options = {}, &block)
|
|
130
179
|
if condition
|
|
131
180
|
cache(name, options, &block)
|
|
132
181
|
else
|
|
@@ -142,50 +191,56 @@ module ActionView
|
|
|
142
191
|
# <b>All the topics on this project</b>
|
|
143
192
|
# <%= render project.topics %>
|
|
144
193
|
# <% end %>
|
|
145
|
-
def cache_unless(condition, name = {}, options =
|
|
194
|
+
def cache_unless(condition, name = {}, options = {}, &block)
|
|
146
195
|
cache_if !condition, name, options, &block
|
|
147
196
|
end
|
|
148
197
|
|
|
149
198
|
# This helper returns the name of a cache key for a given fragment cache
|
|
150
|
-
# call. By supplying skip_digest
|
|
199
|
+
# call. By supplying +skip_digest:+ true to cache, the digestion of cache
|
|
151
200
|
# fragments can be manually bypassed. This is useful when cache fragments
|
|
152
201
|
# cannot be manually expired unless you know the exact key which is the
|
|
153
202
|
# case when using memcached.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
203
|
+
#
|
|
204
|
+
# The digest will be generated using +virtual_path:+ if it is provided.
|
|
205
|
+
#
|
|
206
|
+
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
|
|
157
207
|
if skip_digest
|
|
158
208
|
name
|
|
159
209
|
else
|
|
160
|
-
fragment_name_with_digest(name)
|
|
210
|
+
fragment_name_with_digest(name, virtual_path)
|
|
161
211
|
end
|
|
162
212
|
end
|
|
163
213
|
|
|
164
|
-
|
|
214
|
+
attr_reader :cache_hit # :nodoc:
|
|
165
215
|
|
|
166
|
-
|
|
167
|
-
if @virtual_path
|
|
168
|
-
names = Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name)
|
|
169
|
-
digest = Digestor.digest name: @virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
|
|
216
|
+
private
|
|
170
217
|
|
|
171
|
-
|
|
218
|
+
def fragment_name_with_digest(name, virtual_path)
|
|
219
|
+
virtual_path ||= @virtual_path
|
|
220
|
+
if virtual_path
|
|
221
|
+
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
|
|
222
|
+
digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
|
|
223
|
+
[ name, digest ]
|
|
172
224
|
else
|
|
173
225
|
name
|
|
174
226
|
end
|
|
175
227
|
end
|
|
176
228
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
229
|
+
def fragment_for(name = {}, options = nil, &block)
|
|
230
|
+
if content = read_fragment_for(name, options)
|
|
231
|
+
@cache_hit = true
|
|
232
|
+
content
|
|
233
|
+
else
|
|
234
|
+
@cache_hit = false
|
|
235
|
+
write_fragment_for(name, options, &block)
|
|
236
|
+
end
|
|
180
237
|
end
|
|
181
238
|
|
|
182
|
-
def read_fragment_for(name, options)
|
|
239
|
+
def read_fragment_for(name, options)
|
|
183
240
|
controller.read_fragment(name, options)
|
|
184
241
|
end
|
|
185
242
|
|
|
186
|
-
def write_fragment_for(name, options)
|
|
187
|
-
# VIEW TODO: Make #capture usable outside of ERB
|
|
188
|
-
# This dance is needed because Builder can't use capture
|
|
243
|
+
def write_fragment_for(name, options)
|
|
189
244
|
pos = output_buffer.length
|
|
190
245
|
yield
|
|
191
246
|
output_safe = output_buffer.html_safe?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "active_support/core_ext/string/output_safety"
|
|
2
2
|
|
|
3
3
|
module ActionView
|
|
4
4
|
# = Action View Capture Helper
|
|
@@ -9,8 +9,8 @@ module ActionView
|
|
|
9
9
|
# It provides a method to capture blocks into variables through capture and
|
|
10
10
|
# a way to capture a block of markup for use in a layout through content_for.
|
|
11
11
|
module CaptureHelper
|
|
12
|
-
# The capture method
|
|
13
|
-
#
|
|
12
|
+
# The capture method extracts part of a template as a String object.
|
|
13
|
+
# You can then use this object anywhere in your templates, layout, or helpers.
|
|
14
14
|
#
|
|
15
15
|
# The capture method can be used in ERB templates...
|
|
16
16
|
#
|
|
@@ -31,12 +31,13 @@ module ActionView
|
|
|
31
31
|
# <head><title><%= @greeting %></title></head>
|
|
32
32
|
# <body>
|
|
33
33
|
# <b><%= @greeting %></b>
|
|
34
|
-
# </body
|
|
34
|
+
# </body>
|
|
35
|
+
# </html>
|
|
35
36
|
#
|
|
36
37
|
def capture(*args)
|
|
37
38
|
value = nil
|
|
38
39
|
buffer = with_output_buffer { value = yield(*args) }
|
|
39
|
-
if string = buffer.presence || value
|
|
40
|
+
if (string = buffer.presence || value) && string.is_a?(String)
|
|
40
41
|
ERB::Util.html_escape string
|
|
41
42
|
end
|
|
42
43
|
end
|
|
@@ -114,7 +115,7 @@ module ActionView
|
|
|
114
115
|
# <li><%= link_to 'Home', action: 'index' %></li>
|
|
115
116
|
# <% end %>
|
|
116
117
|
#
|
|
117
|
-
# And in
|
|
118
|
+
# And in another place:
|
|
118
119
|
#
|
|
119
120
|
# <% content_for :navigation do %>
|
|
120
121
|
# <li><%= link_to 'Login', action: 'login' %></li>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "active_support/core_ext/module/attr_internal"
|
|
2
2
|
|
|
3
3
|
module ActionView
|
|
4
4
|
module Helpers
|
|
@@ -8,12 +8,13 @@ module ActionView
|
|
|
8
8
|
attr_internal :controller, :request
|
|
9
9
|
|
|
10
10
|
delegate :request_forgery_protection_token, :params, :session, :cookies, :response, :headers,
|
|
11
|
-
:flash, :action_name, :controller_name, :controller_path, :
|
|
11
|
+
:flash, :action_name, :controller_name, :controller_path, to: :controller
|
|
12
12
|
|
|
13
13
|
def assign_controller(controller)
|
|
14
14
|
if @_controller = controller
|
|
15
15
|
@_request = controller.request if controller.respond_to?(:request)
|
|
16
16
|
@_config = controller.config.inheritable_copy if controller.respond_to?(:config)
|
|
17
|
+
@_default_form_builder = controller.default_form_builder if controller.respond_to?(:default_form_builder)
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -14,14 +14,14 @@ module ActionView
|
|
|
14
14
|
#
|
|
15
15
|
# You don't need to use these tags for regular forms as they generate their own hidden fields.
|
|
16
16
|
#
|
|
17
|
-
# For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
|
|
17
|
+
# For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
|
|
18
18
|
# "X-CSRF-Token" HTTP header. If you are using jQuery with jquery-rails this happens automatically.
|
|
19
19
|
#
|
|
20
20
|
def csrf_meta_tags
|
|
21
21
|
if protect_against_forgery?
|
|
22
22
|
[
|
|
23
|
-
tag(
|
|
24
|
-
tag(
|
|
23
|
+
tag("meta", name: "csrf-param", content: request_forgery_protection_token),
|
|
24
|
+
tag("meta", name: "csrf-token", content: form_authenticity_token)
|
|
25
25
|
].join("\n").html_safe
|
|
26
26
|
end
|
|
27
27
|
end
|