actionpack 3.2.19 → 4.0.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 +7 -0
- data/CHANGELOG.md +850 -401
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -288
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +39 -37
- data/lib/abstract_controller/callbacks.rb +101 -82
- data/lib/abstract_controller/collector.rb +7 -3
- data/lib/abstract_controller/helpers.rb +25 -13
- data/lib/abstract_controller/layouts.rb +74 -74
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/rendering.rb +30 -13
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller/view_paths.rb +1 -1
- data/lib/abstract_controller.rb +1 -8
- data/lib/action_controller/base.rb +46 -22
- data/lib/action_controller/caching/fragments.rb +23 -53
- data/lib/action_controller/caching.rb +46 -33
- data/lib/action_controller/deprecated/integration_test.rb +3 -0
- data/lib/action_controller/deprecated.rb +5 -1
- data/lib/action_controller/log_subscriber.rb +16 -8
- data/lib/action_controller/metal/conditional_get.rb +76 -32
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +24 -9
- data/lib/action_controller/metal/force_ssl.rb +70 -12
- data/lib/action_controller/metal/head.rb +25 -4
- data/lib/action_controller/metal/helpers.rb +5 -9
- data/lib/action_controller/metal/hide_actions.rb +0 -1
- data/lib/action_controller/metal/http_authentication.rb +107 -83
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +2 -1
- data/lib/action_controller/metal/live.rb +175 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -47
- data/lib/action_controller/metal/params_wrapper.rb +112 -74
- data/lib/action_controller/metal/rack_delegation.rb +9 -3
- data/lib/action_controller/metal/redirecting.rb +15 -20
- data/lib/action_controller/metal/renderers.rb +11 -9
- data/lib/action_controller/metal/rendering.rb +9 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
- data/lib/action_controller/metal/responder.rb +20 -19
- data/lib/action_controller/metal/streaming.rb +12 -18
- data/lib/action_controller/metal/strong_parameters.rb +520 -0
- data/lib/action_controller/metal/testing.rb +13 -18
- data/lib/action_controller/metal/url_for.rb +28 -25
- data/lib/action_controller/metal.rb +17 -32
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +33 -17
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/record_identifier.rb +18 -72
- data/lib/action_controller/test_case.rb +251 -131
- data/lib/action_controller/vendor/html-scanner.rb +4 -19
- data/lib/action_controller.rb +15 -6
- data/lib/action_dispatch/http/cache.rb +63 -11
- data/lib/action_dispatch/http/filter_parameters.rb +18 -8
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +49 -17
- data/lib/action_dispatch/http/mime_negotiation.rb +24 -1
- data/lib/action_dispatch/http/mime_type.rb +154 -100
- data/lib/action_dispatch/http/mime_types.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +28 -28
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +64 -18
- data/lib/action_dispatch/http/response.rb +130 -35
- data/lib/action_dispatch/http/upload.rb +63 -20
- data/lib/action_dispatch/http/url.rb +98 -35
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +146 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +124 -0
- data/lib/action_dispatch/journey/parser.rb +206 -0
- data/lib/action_dispatch/journey/parser.y +47 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +196 -0
- data/lib/action_dispatch/journey/route.rb +124 -0
- data/lib/action_dispatch/journey/router/strexp.rb +24 -0
- data/lib/action_dispatch/journey/router/utils.rb +54 -0
- data/lib/action_dispatch/journey/router.rb +166 -0
- data/lib/action_dispatch/journey/routes.rb +75 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +197 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/middleware/callbacks.rb +9 -4
- data/lib/action_dispatch/middleware/cookies.rb +259 -114
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
- data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -3
- data/lib/action_dispatch/middleware/flash.rb +58 -58
- data/lib/action_dispatch/middleware/params_parser.rb +14 -29
- data/lib/action_dispatch/middleware/public_exceptions.rb +30 -14
- data/lib/action_dispatch/middleware/reloader.rb +6 -6
- data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
- data/lib/action_dispatch/middleware/request_id.rb +2 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cookie_store.rb +82 -28
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
- data/lib/action_dispatch/middleware/ssl.rb +70 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +2 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +7 -9
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +127 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
- data/lib/action_dispatch/railtie.rb +16 -6
- data/lib/action_dispatch/request/session.rb +181 -0
- data/lib/action_dispatch/routing/inspector.rb +240 -0
- data/lib/action_dispatch/routing/mapper.rb +540 -291
- data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
- data/lib/action_dispatch/routing/redirection.rb +46 -29
- data/lib/action_dispatch/routing/route_set.rb +207 -164
- data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
- data/lib/action_dispatch/routing/url_for.rb +48 -33
- data/lib/action_dispatch/routing.rb +48 -83
- data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
- data/lib/action_dispatch/testing/assertions/response.rb +32 -40
- data/lib/action_dispatch/testing/assertions/routing.rb +42 -41
- data/lib/action_dispatch/testing/assertions/selector.rb +17 -22
- data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
- data/lib/action_dispatch/testing/integration.rb +65 -51
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +7 -3
- data/lib/action_dispatch.rb +21 -15
- data/lib/action_pack/version.rb +7 -6
- data/lib/action_pack.rb +1 -1
- data/lib/action_view/base.rb +15 -34
- data/lib/action_view/buffers.rb +7 -1
- data/lib/action_view/context.rb +4 -4
- data/lib/action_view/dependency_tracker.rb +93 -0
- data/lib/action_view/digestor.rb +85 -0
- data/lib/action_view/flows.rb +1 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +215 -352
- data/lib/action_view/helpers/asset_url_helper.rb +355 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
- data/lib/action_view/helpers/cache_helper.rb +150 -18
- data/lib/action_view/helpers/capture_helper.rb +44 -31
- data/lib/action_view/helpers/csrf_helper.rb +0 -2
- data/lib/action_view/helpers/date_helper.rb +269 -248
- data/lib/action_view/helpers/debug_helper.rb +10 -11
- data/lib/action_view/helpers/form_helper.rb +931 -537
- data/lib/action_view/helpers/form_options_helper.rb +341 -166
- data/lib/action_view/helpers/form_tag_helper.rb +190 -90
- data/lib/action_view/helpers/javascript_helper.rb +23 -16
- data/lib/action_view/helpers/number_helper.rb +148 -329
- data/lib/action_view/helpers/output_safety_helper.rb +3 -3
- data/lib/action_view/helpers/record_tag_helper.rb +17 -22
- data/lib/action_view/helpers/rendering_helper.rb +2 -2
- data/lib/action_view/helpers/sanitize_helper.rb +3 -6
- data/lib/action_view/helpers/tag_helper.rb +46 -33
- data/lib/action_view/helpers/tags/base.rb +147 -0
- data/lib/action_view/helpers/tags/check_box.rb +64 -0
- data/lib/action_view/helpers/tags/checkable.rb +16 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
- data/lib/action_view/helpers/tags/collection_select.rb +28 -0
- data/lib/action_view/helpers/tags/color_field.rb +25 -0
- data/lib/action_view/helpers/tags/date_field.rb +13 -0
- data/lib/action_view/helpers/tags/date_select.rb +72 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
- data/lib/action_view/helpers/tags/email_field.rb +8 -0
- data/lib/action_view/helpers/tags/file_field.rb +8 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
- data/lib/action_view/helpers/tags/label.rb +65 -0
- data/lib/action_view/helpers/tags/month_field.rb +13 -0
- data/lib/action_view/helpers/tags/number_field.rb +18 -0
- data/lib/action_view/helpers/tags/password_field.rb +12 -0
- data/lib/action_view/helpers/tags/radio_button.rb +31 -0
- data/lib/action_view/helpers/tags/range_field.rb +8 -0
- data/lib/action_view/helpers/tags/search_field.rb +24 -0
- data/lib/action_view/helpers/tags/select.rb +40 -0
- data/lib/action_view/helpers/tags/tel_field.rb +8 -0
- data/lib/action_view/helpers/tags/text_area.rb +18 -0
- data/lib/action_view/helpers/tags/text_field.rb +29 -0
- data/lib/action_view/helpers/tags/time_field.rb +13 -0
- data/lib/action_view/helpers/tags/time_select.rb +8 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
- data/lib/action_view/helpers/tags/url_field.rb +8 -0
- data/lib/action_view/helpers/tags/week_field.rb +13 -0
- data/lib/action_view/helpers/tags.rb +39 -0
- data/lib/action_view/helpers/text_helper.rb +130 -114
- data/lib/action_view/helpers/translation_helper.rb +32 -16
- data/lib/action_view/helpers/url_helper.rb +211 -270
- data/lib/action_view/helpers.rb +2 -4
- data/lib/action_view/locale/en.yml +1 -105
- data/lib/action_view/log_subscriber.rb +6 -4
- data/lib/action_view/lookup_context.rb +15 -28
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +8 -20
- data/lib/action_view/railtie.rb +6 -22
- data/lib/action_view/record_identifier.rb +84 -0
- data/lib/action_view/renderer/abstract_renderer.rb +25 -19
- data/lib/action_view/renderer/partial_renderer.rb +158 -81
- data/lib/action_view/renderer/renderer.rb +8 -12
- data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
- data/lib/action_view/renderer/template_renderer.rb +12 -10
- data/lib/action_view/routing_url_for.rb +107 -0
- data/lib/action_view/template/error.rb +22 -12
- data/lib/action_view/template/handlers/builder.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +40 -19
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/handlers.rb +12 -9
- data/lib/action_view/template/resolver.rb +107 -53
- data/lib/action_view/template/text.rb +12 -8
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/template.rb +25 -23
- data/lib/action_view/test_case.rb +67 -42
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +13 -2
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +9 -9
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/action_view.rb +17 -8
- metadata +184 -214
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require "active_support/core_ext/array/wrap"
|
|
2
1
|
require "active_support/core_ext/enumerable"
|
|
3
2
|
|
|
4
3
|
module ActionView
|
|
@@ -9,13 +8,16 @@ module ActionView
|
|
|
9
8
|
class EncodingError < StandardError #:nodoc:
|
|
10
9
|
end
|
|
11
10
|
|
|
11
|
+
class MissingRequestError < StandardError #:nodoc:
|
|
12
|
+
end
|
|
13
|
+
|
|
12
14
|
class WrongEncodingError < EncodingError #:nodoc:
|
|
13
15
|
def initialize(string, encoding)
|
|
14
16
|
@string, @encoding = string, encoding
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def message
|
|
18
|
-
@string.force_encoding(
|
|
20
|
+
@string.force_encoding(Encoding::ASCII_8BIT)
|
|
19
21
|
"Your template was not saved as valid #{@encoding}. Please " \
|
|
20
22
|
"either specify #{@encoding} as the encoding for your template " \
|
|
21
23
|
"in your text editor, or mark the template with its " \
|
|
@@ -30,7 +32,7 @@ module ActionView
|
|
|
30
32
|
|
|
31
33
|
def initialize(paths, path, prefixes, partial, details, *)
|
|
32
34
|
@path = path
|
|
33
|
-
prefixes = Array
|
|
35
|
+
prefixes = Array(prefixes)
|
|
34
36
|
template_type = if partial
|
|
35
37
|
"partial"
|
|
36
38
|
elsif path =~ /layouts/i
|
|
@@ -56,9 +58,9 @@ module ActionView
|
|
|
56
58
|
|
|
57
59
|
attr_reader :original_exception, :backtrace
|
|
58
60
|
|
|
59
|
-
def initialize(template,
|
|
61
|
+
def initialize(template, original_exception)
|
|
60
62
|
super(original_exception.message)
|
|
61
|
-
@template, @
|
|
63
|
+
@template, @original_exception = template, original_exception
|
|
62
64
|
@sub_templates = nil
|
|
63
65
|
@backtrace = original_exception.backtrace
|
|
64
66
|
end
|
|
@@ -76,7 +78,7 @@ module ActionView
|
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
|
|
79
|
-
def source_extract(indentation = 0)
|
|
81
|
+
def source_extract(indentation = 0, output = :console)
|
|
80
82
|
return unless num = line_number
|
|
81
83
|
num = num.to_i
|
|
82
84
|
|
|
@@ -85,14 +87,10 @@ module ActionView
|
|
|
85
87
|
start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
|
|
86
88
|
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
|
87
89
|
|
|
88
|
-
indent =
|
|
89
|
-
line_counter = start_on_line
|
|
90
|
+
indent = end_on_line.to_s.size + indentation
|
|
90
91
|
return unless source_code = source_code[start_on_line..end_on_line]
|
|
91
92
|
|
|
92
|
-
source_code
|
|
93
|
-
line_counter += 1
|
|
94
|
-
"#{indent}#{line_counter}: #{line}\n"
|
|
95
|
-
end
|
|
93
|
+
formatted_code_for(source_code, start_on_line, indent, output)
|
|
96
94
|
end
|
|
97
95
|
|
|
98
96
|
def sub_template_of(template_path)
|
|
@@ -121,6 +119,18 @@ module ActionView
|
|
|
121
119
|
'in '
|
|
122
120
|
end + file_name
|
|
123
121
|
end
|
|
122
|
+
|
|
123
|
+
def formatted_code_for(source_code, line_counter, indent, output)
|
|
124
|
+
start_value = (output == :html) ? {} : ""
|
|
125
|
+
source_code.inject(start_value) do |result, line|
|
|
126
|
+
line_counter += 1
|
|
127
|
+
if output == :html
|
|
128
|
+
result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
|
|
129
|
+
else
|
|
130
|
+
result << "%#{indent}s: %s\n" % [line_counter, line]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
124
134
|
end
|
|
125
135
|
end
|
|
126
136
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'action_dispatch/http/mime_type'
|
|
2
|
-
require 'active_support/core_ext/class/attribute'
|
|
3
2
|
require 'erubis'
|
|
4
3
|
|
|
5
4
|
module ActionView
|
|
@@ -7,12 +6,23 @@ module ActionView
|
|
|
7
6
|
module Handlers
|
|
8
7
|
class Erubis < ::Erubis::Eruby
|
|
9
8
|
def add_preamble(src)
|
|
9
|
+
@newline_pending = 0
|
|
10
10
|
src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def add_text(src, text)
|
|
14
14
|
return if text.empty?
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
if text == "\n"
|
|
17
|
+
@newline_pending += 1
|
|
18
|
+
else
|
|
19
|
+
src << "@output_buffer.safe_append='"
|
|
20
|
+
src << "\n" * @newline_pending if @newline_pending > 0
|
|
21
|
+
src << escape_text(text)
|
|
22
|
+
src << "';"
|
|
23
|
+
|
|
24
|
+
@newline_pending = 0
|
|
25
|
+
end
|
|
16
26
|
end
|
|
17
27
|
|
|
18
28
|
# Erubis toggles <%= and <%== behavior when escaping is enabled.
|
|
@@ -29,24 +39,39 @@ module ActionView
|
|
|
29
39
|
BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
|
|
30
40
|
|
|
31
41
|
def add_expr_literal(src, code)
|
|
42
|
+
flush_newline_if_pending(src)
|
|
32
43
|
if code =~ BLOCK_EXPR
|
|
33
44
|
src << '@output_buffer.append= ' << code
|
|
34
45
|
else
|
|
35
|
-
src << '@output_buffer.append=
|
|
46
|
+
src << '@output_buffer.append=(' << code << ');'
|
|
36
47
|
end
|
|
37
48
|
end
|
|
38
49
|
|
|
39
50
|
def add_expr_escaped(src, code)
|
|
51
|
+
flush_newline_if_pending(src)
|
|
40
52
|
if code =~ BLOCK_EXPR
|
|
41
53
|
src << "@output_buffer.safe_append= " << code
|
|
42
54
|
else
|
|
43
|
-
src << "@output_buffer.
|
|
55
|
+
src << "@output_buffer.safe_append=(" << code << ");"
|
|
44
56
|
end
|
|
45
57
|
end
|
|
46
58
|
|
|
59
|
+
def add_stmt(src, code)
|
|
60
|
+
flush_newline_if_pending(src)
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
|
|
47
64
|
def add_postamble(src)
|
|
65
|
+
flush_newline_if_pending(src)
|
|
48
66
|
src << '@output_buffer.to_s'
|
|
49
67
|
end
|
|
68
|
+
|
|
69
|
+
def flush_newline_if_pending(src)
|
|
70
|
+
if @newline_pending > 0
|
|
71
|
+
src << "@output_buffer.safe_append='#{"\n" * @newline_pending}';"
|
|
72
|
+
@newline_pending = 0
|
|
73
|
+
end
|
|
74
|
+
end
|
|
50
75
|
end
|
|
51
76
|
|
|
52
77
|
class ERB
|
|
@@ -78,27 +103,23 @@ module ActionView
|
|
|
78
103
|
end
|
|
79
104
|
|
|
80
105
|
def call(template)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
template_source = template.source.dup.force_encoding("BINARY")
|
|
106
|
+
# First, convert to BINARY, so in case the encoding is
|
|
107
|
+
# wrong, we can still find an encoding tag
|
|
108
|
+
# (<%# encoding %>) inside the String using a regular
|
|
109
|
+
# expression
|
|
110
|
+
template_source = template.source.dup.force_encoding(Encoding::ASCII_8BIT)
|
|
87
111
|
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
erb = template_source.gsub(ENCODING_TAG, '')
|
|
113
|
+
encoding = $2
|
|
90
114
|
|
|
91
|
-
|
|
115
|
+
erb.force_encoding valid_encoding(template.source.dup, encoding)
|
|
92
116
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
else
|
|
96
|
-
erb = template.source.dup
|
|
97
|
-
end
|
|
117
|
+
# Always make sure we return a String in the default_internal
|
|
118
|
+
erb.encode!
|
|
98
119
|
|
|
99
120
|
self.class.erb_implementation.new(
|
|
100
121
|
erb,
|
|
101
|
-
:escape => (self.class.escape_whitelist.include? template.
|
|
122
|
+
:escape => (self.class.escape_whitelist.include? template.type),
|
|
102
123
|
:trim => (self.class.erb_trim_mode == "-")
|
|
103
124
|
).src
|
|
104
125
|
end
|
|
@@ -4,10 +4,13 @@ module ActionView #:nodoc:
|
|
|
4
4
|
module Handlers #:nodoc:
|
|
5
5
|
autoload :ERB, 'action_view/template/handlers/erb'
|
|
6
6
|
autoload :Builder, 'action_view/template/handlers/builder'
|
|
7
|
+
autoload :Raw, 'action_view/template/handlers/raw'
|
|
7
8
|
|
|
8
9
|
def self.extended(base)
|
|
9
10
|
base.register_default_template_handler :erb, ERB.new
|
|
10
11
|
base.register_template_handler :builder, Builder.new
|
|
12
|
+
base.register_template_handler :raw, Raw.new
|
|
13
|
+
base.register_template_handler :ruby, :source.to_proc
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
@@template_handlers = {}
|
|
@@ -17,15 +20,15 @@ module ActionView #:nodoc:
|
|
|
17
20
|
@@template_extensions ||= @@template_handlers.keys
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
# Register
|
|
21
|
-
#
|
|
22
|
-
# The
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
# Register an object that knows how to handle template files with the given
|
|
24
|
+
# extensions. This can be used to implement new template types.
|
|
25
|
+
# The handler must respond to `:call`, which will be passed the template
|
|
26
|
+
# and should return the rendered template as a String.
|
|
27
|
+
def register_template_handler(*extensions, handler)
|
|
28
|
+
raise(ArgumentError, "Extension is required") if extensions.empty?
|
|
29
|
+
extensions.each do |extension|
|
|
30
|
+
@@template_handlers[extension.to_sym] = handler
|
|
31
|
+
end
|
|
29
32
|
@@template_extensions = nil
|
|
30
33
|
end
|
|
31
34
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
require "pathname"
|
|
2
2
|
require "active_support/core_ext/class"
|
|
3
|
-
require "active_support/core_ext/
|
|
3
|
+
require "active_support/core_ext/class/attribute_accessors"
|
|
4
4
|
require "action_view/template"
|
|
5
|
+
require "thread"
|
|
6
|
+
require "thread_safe"
|
|
5
7
|
|
|
6
8
|
module ActionView
|
|
7
9
|
# = Action View Resolver
|
|
8
10
|
class Resolver
|
|
9
11
|
# Keeps all information about view path and builds virtual path.
|
|
10
|
-
class Path
|
|
12
|
+
class Path
|
|
11
13
|
attr_reader :name, :prefix, :partial, :virtual
|
|
12
14
|
alias_method :partial?, :partial
|
|
13
15
|
|
|
@@ -19,8 +21,76 @@ module ActionView
|
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def initialize(name, prefix, partial, virtual)
|
|
22
|
-
@name
|
|
23
|
-
|
|
24
|
+
@name = name
|
|
25
|
+
@prefix = prefix
|
|
26
|
+
@partial = partial
|
|
27
|
+
@virtual = virtual
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_str
|
|
31
|
+
@virtual
|
|
32
|
+
end
|
|
33
|
+
alias :to_s :to_str
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Threadsafe template cache
|
|
37
|
+
class Cache #:nodoc:
|
|
38
|
+
class SmallCache < ThreadSafe::Cache
|
|
39
|
+
def initialize(options = {})
|
|
40
|
+
super(options.merge(:initial_capacity => 2))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# preallocate all the default blocks for performance/memory consumption reasons
|
|
45
|
+
PARTIAL_BLOCK = lambda {|cache, partial| cache[partial] = SmallCache.new}
|
|
46
|
+
PREFIX_BLOCK = lambda {|cache, prefix| cache[prefix] = SmallCache.new(&PARTIAL_BLOCK)}
|
|
47
|
+
NAME_BLOCK = lambda {|cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK)}
|
|
48
|
+
KEY_BLOCK = lambda {|cache, key| cache[key] = SmallCache.new(&NAME_BLOCK)}
|
|
49
|
+
|
|
50
|
+
# usually a majority of template look ups return nothing, use this canonical preallocated array to save memory
|
|
51
|
+
NO_TEMPLATES = [].freeze
|
|
52
|
+
|
|
53
|
+
def initialize
|
|
54
|
+
@data = SmallCache.new(&KEY_BLOCK)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Cache the templates returned by the block
|
|
58
|
+
def cache(key, name, prefix, partial, locals)
|
|
59
|
+
if Resolver.caching?
|
|
60
|
+
@data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
|
|
61
|
+
else
|
|
62
|
+
fresh_templates = yield
|
|
63
|
+
cached_templates = @data[key][name][prefix][partial][locals]
|
|
64
|
+
|
|
65
|
+
if templates_have_changed?(cached_templates, fresh_templates)
|
|
66
|
+
@data[key][name][prefix][partial][locals] = canonical_no_templates(fresh_templates)
|
|
67
|
+
else
|
|
68
|
+
cached_templates || NO_TEMPLATES
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def clear
|
|
74
|
+
@data.clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def canonical_no_templates(templates)
|
|
80
|
+
templates.empty? ? NO_TEMPLATES : templates
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def templates_have_changed?(cached_templates, fresh_templates)
|
|
84
|
+
# if either the old or new template list is empty, we don't need to (and can't)
|
|
85
|
+
# compare modification times, and instead just check whether the lists are different
|
|
86
|
+
if cached_templates.blank? || fresh_templates.blank?
|
|
87
|
+
return fresh_templates.blank? != cached_templates.blank?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
cached_templates_max_updated_at = cached_templates.map(&:updated_at).max
|
|
91
|
+
|
|
92
|
+
# if a template has changed, it will be now be newer than all the cached templates
|
|
93
|
+
fresh_templates.any? { |t| t.updated_at > cached_templates_max_updated_at }
|
|
24
94
|
end
|
|
25
95
|
end
|
|
26
96
|
|
|
@@ -32,15 +102,14 @@ module ActionView
|
|
|
32
102
|
end
|
|
33
103
|
|
|
34
104
|
def initialize
|
|
35
|
-
@
|
|
36
|
-
h2[k2] = Hash.new { |h3,k3| h3[k3] = Hash.new { |h4,k4| h4[k4] = {} } } } }
|
|
105
|
+
@cache = Cache.new
|
|
37
106
|
end
|
|
38
107
|
|
|
39
108
|
def clear_cache
|
|
40
|
-
@
|
|
109
|
+
@cache.clear
|
|
41
110
|
end
|
|
42
111
|
|
|
43
|
-
# Normalizes the arguments and passes it on to
|
|
112
|
+
# Normalizes the arguments and passes it on to find_templates.
|
|
44
113
|
def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
|
|
45
114
|
cached(key, [name, prefix, partial], details, locals) do
|
|
46
115
|
find_templates(name, prefix, partial, details)
|
|
@@ -49,7 +118,7 @@ module ActionView
|
|
|
49
118
|
|
|
50
119
|
private
|
|
51
120
|
|
|
52
|
-
delegate :caching?, :
|
|
121
|
+
delegate :caching?, to: :class
|
|
53
122
|
|
|
54
123
|
# This is what child classes implement. No defaults are needed
|
|
55
124
|
# because Resolver guarantees that the arguments are present and
|
|
@@ -65,27 +134,18 @@ module ActionView
|
|
|
65
134
|
|
|
66
135
|
# Handles templates caching. If a key is given and caching is on
|
|
67
136
|
# always check the cache before hitting the resolver. Otherwise,
|
|
68
|
-
# it always hits the resolver but
|
|
69
|
-
# before returning it.
|
|
137
|
+
# it always hits the resolver but if the key is present, check if the
|
|
138
|
+
# resolver is fresher before returning it.
|
|
70
139
|
def cached(key, path_info, details, locals) #:nodoc:
|
|
71
140
|
name, prefix, partial = path_info
|
|
72
141
|
locals = locals.map { |x| x.to_s }.sort!
|
|
73
142
|
|
|
74
|
-
if key
|
|
75
|
-
@
|
|
76
|
-
|
|
77
|
-
fresh = decorate(yield, path_info, details, locals)
|
|
78
|
-
return fresh unless key
|
|
79
|
-
|
|
80
|
-
scope = @cached[key][name][prefix][partial]
|
|
81
|
-
cache = scope[locals]
|
|
82
|
-
mtime = cache && cache.map(&:updated_at).max
|
|
83
|
-
|
|
84
|
-
if !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime }
|
|
85
|
-
scope[locals] = fresh
|
|
86
|
-
else
|
|
87
|
-
cache
|
|
143
|
+
if key
|
|
144
|
+
@cache.cache(key, name, prefix, partial, locals) do
|
|
145
|
+
decorate(yield, path_info, details, locals)
|
|
88
146
|
end
|
|
147
|
+
else
|
|
148
|
+
decorate(yield, path_info, details, locals)
|
|
89
149
|
end
|
|
90
150
|
end
|
|
91
151
|
|
|
@@ -120,7 +180,13 @@ module ActionView
|
|
|
120
180
|
def query(path, details, formats)
|
|
121
181
|
query = build_query(path, details)
|
|
122
182
|
|
|
123
|
-
|
|
183
|
+
# deals with case-insensitive file systems.
|
|
184
|
+
sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
|
|
185
|
+
|
|
186
|
+
template_paths = Dir[query].reject { |filename|
|
|
187
|
+
File.directory?(filename) ||
|
|
188
|
+
!sanitizer[File.dirname(filename)].include?(filename)
|
|
189
|
+
}
|
|
124
190
|
|
|
125
191
|
template_paths.map { |template|
|
|
126
192
|
handler, format = extract_handler_and_format(template, formats)
|
|
@@ -133,26 +199,6 @@ module ActionView
|
|
|
133
199
|
}
|
|
134
200
|
end
|
|
135
201
|
|
|
136
|
-
if RUBY_VERSION >= '2.2.0'
|
|
137
|
-
def find_template_paths(query)
|
|
138
|
-
Dir[query].reject { |filename|
|
|
139
|
-
File.directory?(filename) ||
|
|
140
|
-
# deals with case-insensitive file systems.
|
|
141
|
-
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
|
|
142
|
-
}
|
|
143
|
-
end
|
|
144
|
-
else
|
|
145
|
-
def find_template_paths(query)
|
|
146
|
-
# deals with case-insensitive file systems.
|
|
147
|
-
sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
|
|
148
|
-
|
|
149
|
-
Dir[query].reject { |filename|
|
|
150
|
-
File.directory?(filename) ||
|
|
151
|
-
!sanitizer[File.dirname(filename)].include?(filename)
|
|
152
|
-
}
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
202
|
# Helper for building query glob string based on resolver's pattern.
|
|
157
203
|
def build_query(path, details)
|
|
158
204
|
query = @pattern.dup
|
|
@@ -185,13 +231,21 @@ module ActionView
|
|
|
185
231
|
def extract_handler_and_format(path, default_formats)
|
|
186
232
|
pieces = File.basename(path).split(".")
|
|
187
233
|
pieces.shift
|
|
188
|
-
|
|
189
|
-
|
|
234
|
+
|
|
235
|
+
extension = pieces.pop
|
|
236
|
+
unless extension
|
|
237
|
+
message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
|
|
238
|
+
"but will change to RAW in the future."
|
|
239
|
+
ActiveSupport::Deprecation.warn message
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
handler = Template.handler_for_extension(extension)
|
|
243
|
+
format = pieces.last && Template::Types[pieces.last]
|
|
190
244
|
[handler, format]
|
|
191
245
|
end
|
|
192
246
|
end
|
|
193
247
|
|
|
194
|
-
# A resolver that loads files from the filesystem. It allows
|
|
248
|
+
# A resolver that loads files from the filesystem. It allows setting your own
|
|
195
249
|
# resolving pattern. Such pattern can be a glob string supported by some variables.
|
|
196
250
|
#
|
|
197
251
|
# ==== Examples
|
|
@@ -201,13 +255,13 @@ module ActionView
|
|
|
201
255
|
#
|
|
202
256
|
# FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}")
|
|
203
257
|
#
|
|
204
|
-
# This one allows you to keep files with different formats in
|
|
258
|
+
# This one allows you to keep files with different formats in separate subdirectories,
|
|
205
259
|
# eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`,
|
|
206
260
|
# `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc.
|
|
207
261
|
#
|
|
208
262
|
# FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{.:handlers,}")
|
|
209
263
|
#
|
|
210
|
-
# If you don't specify pattern then the default will be used.
|
|
264
|
+
# If you don't specify a pattern then the default will be used.
|
|
211
265
|
#
|
|
212
266
|
# In order to use any of the customized resolvers above in a Rails application, you just need
|
|
213
267
|
# to configure ActionController::Base.view_paths in an initializer, for example:
|
|
@@ -219,10 +273,10 @@ module ActionView
|
|
|
219
273
|
#
|
|
220
274
|
# ==== Pattern format and variables
|
|
221
275
|
#
|
|
222
|
-
# Pattern
|
|
276
|
+
# Pattern has to be a valid glob string, and it allows you to use the
|
|
223
277
|
# following variables:
|
|
224
278
|
#
|
|
225
|
-
# * <tt>:prefix</tt> -
|
|
279
|
+
# * <tt>:prefix</tt> - usually the controller path
|
|
226
280
|
# * <tt>:action</tt> - name of the action
|
|
227
281
|
# * <tt>:locale</tt> - possible locale versions
|
|
228
282
|
# * <tt>:formats</tt> - possible request formats (for example html, json, xml...)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module ActionView #:nodoc:
|
|
2
2
|
# = Action View Text Template
|
|
3
3
|
class Template
|
|
4
|
-
class Text
|
|
5
|
-
attr_accessor :
|
|
4
|
+
class Text #:nodoc:
|
|
5
|
+
attr_accessor :type
|
|
6
6
|
|
|
7
|
-
def initialize(string,
|
|
8
|
-
|
|
9
|
-
@
|
|
10
|
-
@
|
|
7
|
+
def initialize(string, type = nil)
|
|
8
|
+
@string = string.to_s
|
|
9
|
+
@type = Types[type] || type if type
|
|
10
|
+
@type ||= Types[:text]
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def identifier
|
|
@@ -18,12 +18,16 @@ module ActionView #:nodoc:
|
|
|
18
18
|
'text template'
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
def to_str
|
|
22
|
+
@string
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def render(*args)
|
|
22
|
-
|
|
26
|
+
to_str
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def formats
|
|
26
|
-
[@
|
|
30
|
+
[@type.to_sym]
|
|
27
31
|
end
|
|
28
32
|
end
|
|
29
33
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
|
3
|
+
|
|
4
|
+
module ActionView
|
|
5
|
+
class Template
|
|
6
|
+
class Types
|
|
7
|
+
class Type
|
|
8
|
+
cattr_accessor :types
|
|
9
|
+
self.types = Set.new
|
|
10
|
+
|
|
11
|
+
def self.register(*t)
|
|
12
|
+
types.merge(t.map { |type| type.to_s })
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
register :html, :text, :js, :css, :xml, :json
|
|
16
|
+
|
|
17
|
+
def self.[](type)
|
|
18
|
+
return type if type.is_a?(self)
|
|
19
|
+
|
|
20
|
+
if type.is_a?(Symbol) || types.member?(type.to_s)
|
|
21
|
+
new(type)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attr_reader :symbol
|
|
26
|
+
|
|
27
|
+
def initialize(symbol)
|
|
28
|
+
@symbol = symbol.to_sym
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
delegate :to_s, :to_sym, :to => :symbol
|
|
32
|
+
alias to_str to_s
|
|
33
|
+
|
|
34
|
+
def ref
|
|
35
|
+
to_sym || to_s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(type)
|
|
39
|
+
return false if type.blank?
|
|
40
|
+
symbol.to_sym == type.to_sym
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
cattr_accessor :type_klass
|
|
45
|
+
|
|
46
|
+
def self.delegate_to(klass)
|
|
47
|
+
self.type_klass = klass
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
delegate_to Type
|
|
51
|
+
|
|
52
|
+
def self.[](type)
|
|
53
|
+
type_klass[type]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|