actionpack 4.0.13 → 4.1.0.beta1

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.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +131 -1636
  3. data/README.rdoc +1 -6
  4. data/lib/abstract_controller.rb +1 -2
  5. data/lib/abstract_controller/base.rb +3 -25
  6. data/lib/abstract_controller/callbacks.rb +4 -2
  7. data/lib/abstract_controller/collector.rb +11 -1
  8. data/lib/abstract_controller/helpers.rb +18 -15
  9. data/lib/abstract_controller/rendering.rb +48 -127
  10. data/lib/action_controller.rb +1 -17
  11. data/lib/action_controller/base.rb +14 -6
  12. data/lib/action_controller/caching.rb +1 -11
  13. data/lib/action_controller/log_subscriber.rb +1 -1
  14. data/lib/action_controller/metal.rb +0 -4
  15. data/lib/action_controller/metal/flash.rb +17 -0
  16. data/lib/action_controller/metal/force_ssl.rb +1 -1
  17. data/lib/action_controller/metal/head.rb +1 -3
  18. data/lib/action_controller/metal/helpers.rb +6 -2
  19. data/lib/action_controller/metal/http_authentication.rb +7 -14
  20. data/lib/action_controller/metal/instrumentation.rb +1 -1
  21. data/lib/action_controller/metal/live.rb +74 -0
  22. data/lib/action_controller/metal/mime_responds.rb +93 -16
  23. data/lib/action_controller/metal/params_wrapper.rb +4 -11
  24. data/lib/action_controller/metal/rack_delegation.rb +1 -1
  25. data/lib/action_controller/metal/redirecting.rb +20 -20
  26. data/lib/action_controller/metal/renderers.rb +8 -5
  27. data/lib/action_controller/metal/rendering.rb +14 -11
  28. data/lib/action_controller/metal/request_forgery_protection.rb +67 -13
  29. data/lib/action_controller/metal/responder.rb +12 -2
  30. data/lib/action_controller/metal/streaming.rb +18 -20
  31. data/lib/action_controller/metal/strong_parameters.rb +22 -34
  32. data/lib/action_controller/railtie.rb +0 -1
  33. data/lib/action_controller/test_case.rb +0 -15
  34. data/lib/action_dispatch.rb +1 -0
  35. data/lib/action_dispatch/http/headers.rb +1 -3
  36. data/lib/action_dispatch/http/mime_negotiation.rb +16 -2
  37. data/lib/action_dispatch/http/mime_type.rb +4 -22
  38. data/lib/action_dispatch/http/mime_types.rb +1 -0
  39. data/lib/action_dispatch/http/parameters.rb +18 -19
  40. data/lib/action_dispatch/http/request.rb +16 -25
  41. data/lib/action_dispatch/http/response.rb +21 -8
  42. data/lib/action_dispatch/http/upload.rb +0 -13
  43. data/lib/action_dispatch/http/url.rb +10 -18
  44. data/lib/action_dispatch/journey/formatter.rb +3 -3
  45. data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -5
  46. data/lib/action_dispatch/journey/parser.rb +1 -1
  47. data/lib/action_dispatch/journey/parser.y +1 -0
  48. data/lib/action_dispatch/journey/router.rb +7 -1
  49. data/lib/action_dispatch/journey/router/utils.rb +1 -1
  50. data/lib/action_dispatch/journey/visitors.rb +26 -47
  51. data/lib/action_dispatch/middleware/callbacks.rb +6 -6
  52. data/lib/action_dispatch/middleware/cookies.rb +15 -15
  53. data/lib/action_dispatch/middleware/debug_exceptions.rb +21 -13
  54. data/lib/action_dispatch/middleware/exception_wrapper.rb +1 -1
  55. data/lib/action_dispatch/middleware/flash.rb +5 -11
  56. data/lib/action_dispatch/middleware/params_parser.rb +1 -1
  57. data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
  58. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  59. data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -3
  60. data/lib/action_dispatch/middleware/show_exceptions.rb +5 -2
  61. data/lib/action_dispatch/middleware/ssl.rb +1 -1
  62. data/lib/action_dispatch/middleware/static.rb +5 -25
  63. data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
  64. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  65. data/lib/action_dispatch/middleware/templates/rescues/{_trace.erb → _trace.html.erb} +0 -0
  66. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +15 -0
  67. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +1 -1
  68. data/lib/action_dispatch/middleware/templates/rescues/{missing_template.erb → missing_template.html.erb} +1 -1
  69. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  70. data/lib/action_dispatch/middleware/templates/rescues/{routing_error.erb → routing_error.html.erb} +1 -1
  71. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  72. data/lib/action_dispatch/middleware/templates/rescues/{template_error.erb → template_error.html.erb} +1 -1
  73. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +8 -0
  74. data/lib/action_dispatch/middleware/templates/rescues/{unknown_action.erb → unknown_action.html.erb} +1 -1
  75. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  76. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -3
  77. data/lib/action_dispatch/railtie.rb +1 -2
  78. data/lib/action_dispatch/request/session.rb +12 -0
  79. data/lib/action_dispatch/request/utils.rb +24 -0
  80. data/lib/action_dispatch/routing.rb +7 -6
  81. data/lib/action_dispatch/routing/inspector.rb +4 -4
  82. data/lib/action_dispatch/routing/mapper.rb +81 -138
  83. data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -0
  84. data/lib/action_dispatch/routing/redirection.rb +34 -27
  85. data/lib/action_dispatch/routing/route_set.rb +43 -37
  86. data/lib/action_dispatch/routing/url_for.rb +3 -1
  87. data/lib/action_dispatch/testing/assertions/response.rb +8 -15
  88. data/lib/action_dispatch/testing/assertions/selector.rb +4 -4
  89. data/lib/action_dispatch/testing/integration.rb +1 -7
  90. data/lib/action_pack/version.rb +1 -1
  91. metadata +43 -167
  92. data/lib/abstract_controller/layouts.rb +0 -423
  93. data/lib/abstract_controller/view_paths.rb +0 -96
  94. data/lib/action_controller/deprecated.rb +0 -7
  95. data/lib/action_controller/deprecated/integration_test.rb +0 -5
  96. data/lib/action_controller/record_identifier.rb +0 -31
  97. data/lib/action_controller/vendor/html-scanner.rb +0 -5
  98. data/lib/action_view.rb +0 -93
  99. data/lib/action_view/base.rb +0 -205
  100. data/lib/action_view/buffers.rb +0 -49
  101. data/lib/action_view/context.rb +0 -36
  102. data/lib/action_view/dependency_tracker.rb +0 -93
  103. data/lib/action_view/digestor.rb +0 -113
  104. data/lib/action_view/flows.rb +0 -76
  105. data/lib/action_view/helpers.rb +0 -58
  106. data/lib/action_view/helpers/active_model_helper.rb +0 -49
  107. data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
  108. data/lib/action_view/helpers/asset_url_helper.rb +0 -355
  109. data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
  110. data/lib/action_view/helpers/cache_helper.rb +0 -196
  111. data/lib/action_view/helpers/capture_helper.rb +0 -216
  112. data/lib/action_view/helpers/controller_helper.rb +0 -25
  113. data/lib/action_view/helpers/csrf_helper.rb +0 -32
  114. data/lib/action_view/helpers/date_helper.rb +0 -1087
  115. data/lib/action_view/helpers/debug_helper.rb +0 -39
  116. data/lib/action_view/helpers/form_helper.rb +0 -1882
  117. data/lib/action_view/helpers/form_options_helper.rb +0 -838
  118. data/lib/action_view/helpers/form_tag_helper.rb +0 -785
  119. data/lib/action_view/helpers/javascript_helper.rb +0 -117
  120. data/lib/action_view/helpers/number_helper.rb +0 -451
  121. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  122. data/lib/action_view/helpers/record_tag_helper.rb +0 -106
  123. data/lib/action_view/helpers/rendering_helper.rb +0 -90
  124. data/lib/action_view/helpers/sanitize_helper.rb +0 -256
  125. data/lib/action_view/helpers/tag_helper.rb +0 -173
  126. data/lib/action_view/helpers/tags.rb +0 -39
  127. data/lib/action_view/helpers/tags/base.rb +0 -148
  128. data/lib/action_view/helpers/tags/check_box.rb +0 -64
  129. data/lib/action_view/helpers/tags/checkable.rb +0 -16
  130. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -53
  131. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
  132. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
  133. data/lib/action_view/helpers/tags/collection_select.rb +0 -28
  134. data/lib/action_view/helpers/tags/color_field.rb +0 -25
  135. data/lib/action_view/helpers/tags/date_field.rb +0 -13
  136. data/lib/action_view/helpers/tags/date_select.rb +0 -72
  137. data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
  138. data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
  139. data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
  140. data/lib/action_view/helpers/tags/email_field.rb +0 -8
  141. data/lib/action_view/helpers/tags/file_field.rb +0 -8
  142. data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
  143. data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
  144. data/lib/action_view/helpers/tags/label.rb +0 -65
  145. data/lib/action_view/helpers/tags/month_field.rb +0 -13
  146. data/lib/action_view/helpers/tags/number_field.rb +0 -18
  147. data/lib/action_view/helpers/tags/password_field.rb +0 -12
  148. data/lib/action_view/helpers/tags/radio_button.rb +0 -31
  149. data/lib/action_view/helpers/tags/range_field.rb +0 -8
  150. data/lib/action_view/helpers/tags/search_field.rb +0 -22
  151. data/lib/action_view/helpers/tags/select.rb +0 -40
  152. data/lib/action_view/helpers/tags/tel_field.rb +0 -8
  153. data/lib/action_view/helpers/tags/text_area.rb +0 -18
  154. data/lib/action_view/helpers/tags/text_field.rb +0 -30
  155. data/lib/action_view/helpers/tags/time_field.rb +0 -13
  156. data/lib/action_view/helpers/tags/time_select.rb +0 -8
  157. data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
  158. data/lib/action_view/helpers/tags/url_field.rb +0 -8
  159. data/lib/action_view/helpers/tags/week_field.rb +0 -13
  160. data/lib/action_view/helpers/text_helper.rb +0 -448
  161. data/lib/action_view/helpers/translation_helper.rb +0 -112
  162. data/lib/action_view/helpers/url_helper.rb +0 -635
  163. data/lib/action_view/locale/en.yml +0 -56
  164. data/lib/action_view/log_subscriber.rb +0 -30
  165. data/lib/action_view/lookup_context.rb +0 -248
  166. data/lib/action_view/model_naming.rb +0 -12
  167. data/lib/action_view/path_set.rb +0 -77
  168. data/lib/action_view/railtie.rb +0 -43
  169. data/lib/action_view/record_identifier.rb +0 -84
  170. data/lib/action_view/renderer/abstract_renderer.rb +0 -47
  171. data/lib/action_view/renderer/partial_renderer.rb +0 -500
  172. data/lib/action_view/renderer/renderer.rb +0 -50
  173. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
  174. data/lib/action_view/renderer/template_renderer.rb +0 -96
  175. data/lib/action_view/routing_url_for.rb +0 -107
  176. data/lib/action_view/tasks/dependencies.rake +0 -17
  177. data/lib/action_view/template.rb +0 -339
  178. data/lib/action_view/template/error.rb +0 -138
  179. data/lib/action_view/template/handlers.rb +0 -53
  180. data/lib/action_view/template/handlers/builder.rb +0 -26
  181. data/lib/action_view/template/handlers/erb.rb +0 -146
  182. data/lib/action_view/template/handlers/raw.rb +0 -11
  183. data/lib/action_view/template/resolver.rb +0 -340
  184. data/lib/action_view/template/text.rb +0 -34
  185. data/lib/action_view/template/types.rb +0 -57
  186. data/lib/action_view/test_case.rb +0 -270
  187. data/lib/action_view/testing/resolvers.rb +0 -50
  188. data/lib/action_view/vendor/html-scanner.rb +0 -20
  189. data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
  190. data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
  191. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
  192. data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
  193. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
  194. data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
@@ -1,138 +0,0 @@
1
- require "active_support/core_ext/enumerable"
2
-
3
- module ActionView
4
- # = Action View Errors
5
- class ActionViewError < StandardError #:nodoc:
6
- end
7
-
8
- class EncodingError < StandardError #:nodoc:
9
- end
10
-
11
- class MissingRequestError < StandardError #:nodoc:
12
- end
13
-
14
- class WrongEncodingError < EncodingError #:nodoc:
15
- def initialize(string, encoding)
16
- @string, @encoding = string, encoding
17
- end
18
-
19
- def message
20
- @string.force_encoding(Encoding::ASCII_8BIT)
21
- "Your template was not saved as valid #{@encoding}. Please " \
22
- "either specify #{@encoding} as the encoding for your template " \
23
- "in your text editor, or mark the template with its " \
24
- "encoding by inserting the following as the first line " \
25
- "of the template:\n\n# encoding: <name of correct encoding>.\n\n" \
26
- "The source of your template was:\n\n#{@string}"
27
- end
28
- end
29
-
30
- class MissingTemplate < ActionViewError #:nodoc:
31
- attr_reader :path
32
-
33
- def initialize(paths, path, prefixes, partial, details, *)
34
- @path = path
35
- prefixes = Array(prefixes)
36
- template_type = if partial
37
- "partial"
38
- elsif path =~ /layouts/i
39
- 'layout'
40
- else
41
- 'template'
42
- end
43
-
44
- searched_paths = prefixes.map { |prefix| [prefix, path].join("/") }
45
-
46
- out = "Missing #{template_type} #{searched_paths.join(", ")} with #{details.inspect}. Searched in:\n"
47
- out += paths.compact.map { |p| " * #{p.to_s.inspect}\n" }.join
48
- super out
49
- end
50
- end
51
-
52
- class Template
53
- # The Template::Error exception is raised when the compilation or rendering of the template
54
- # fails. This exception then gathers a bunch of intimate details and uses it to report a
55
- # precise exception message.
56
- class Error < ActionViewError #:nodoc:
57
- SOURCE_CODE_RADIUS = 3
58
-
59
- attr_reader :original_exception
60
-
61
- def initialize(template, original_exception)
62
- super(original_exception.message)
63
- @template, @original_exception = template, original_exception
64
- @sub_templates = nil
65
- set_backtrace(original_exception.backtrace)
66
- end
67
-
68
- def file_name
69
- @template.identifier
70
- end
71
-
72
- def sub_template_message
73
- if @sub_templates
74
- "Trace of template inclusion: " +
75
- @sub_templates.collect { |template| template.inspect }.join(", ")
76
- else
77
- ""
78
- end
79
- end
80
-
81
- def source_extract(indentation = 0, output = :console)
82
- return unless num = line_number
83
- num = num.to_i
84
-
85
- source_code = @template.source.split("\n")
86
-
87
- start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
88
- end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
89
-
90
- indent = end_on_line.to_s.size + indentation
91
- return unless source_code = source_code[start_on_line..end_on_line]
92
-
93
- formatted_code_for(source_code, start_on_line, indent, output)
94
- end
95
-
96
- def sub_template_of(template_path)
97
- @sub_templates ||= []
98
- @sub_templates << template_path
99
- end
100
-
101
- def line_number
102
- @line_number ||=
103
- if file_name
104
- regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
105
- $1 if message =~ regexp || backtrace.find { |line| line =~ regexp }
106
- end
107
- end
108
-
109
- def annoted_source_code
110
- source_extract(4)
111
- end
112
-
113
- private
114
-
115
- def source_location
116
- if line_number
117
- "on line ##{line_number} of "
118
- else
119
- 'in '
120
- end + file_name
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
134
- end
135
- end
136
-
137
- TemplateError = Template::Error
138
- end
@@ -1,53 +0,0 @@
1
- module ActionView #:nodoc:
2
- # = Action View Template Handlers
3
- class Template
4
- module Handlers #:nodoc:
5
- autoload :ERB, 'action_view/template/handlers/erb'
6
- autoload :Builder, 'action_view/template/handlers/builder'
7
- autoload :Raw, 'action_view/template/handlers/raw'
8
-
9
- def self.extended(base)
10
- base.register_default_template_handler :erb, ERB.new
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
14
- end
15
-
16
- @@template_handlers = {}
17
- @@default_template_handlers = nil
18
-
19
- def self.extensions
20
- @@template_extensions ||= @@template_handlers.keys
21
- end
22
-
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
32
- @@template_extensions = nil
33
- end
34
-
35
- def template_handler_extensions
36
- @@template_handlers.keys.map {|key| key.to_s }.sort
37
- end
38
-
39
- def registered_template_handler(extension)
40
- extension && @@template_handlers[extension.to_sym]
41
- end
42
-
43
- def register_default_template_handler(extension, klass)
44
- register_template_handler(extension, klass)
45
- @@default_template_handlers = klass
46
- end
47
-
48
- def handler_for_extension(extension)
49
- registered_template_handler(extension) || @@default_template_handlers
50
- end
51
- end
52
- end
53
- end
@@ -1,26 +0,0 @@
1
- module ActionView
2
- module Template::Handlers
3
- class Builder
4
- # Default format used by Builder.
5
- class_attribute :default_format
6
- self.default_format = :xml
7
-
8
- def call(template)
9
- require_engine
10
- "xml = ::Builder::XmlMarkup.new(:indent => 2);" +
11
- "self.output_buffer = xml.target!;" +
12
- template.source +
13
- ";xml.target!;"
14
- end
15
-
16
- protected
17
-
18
- def require_engine
19
- @required ||= begin
20
- require "builder"
21
- true
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,146 +0,0 @@
1
- require 'action_dispatch/http/mime_type'
2
- require 'erubis'
3
-
4
- module ActionView
5
- class Template
6
- module Handlers
7
- class Erubis < ::Erubis::Eruby
8
- def add_preamble(src)
9
- @newline_pending = 0
10
- src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
11
- end
12
-
13
- def add_text(src, text)
14
- return if text.empty?
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
26
- end
27
-
28
- # Erubis toggles <%= and <%== behavior when escaping is enabled.
29
- # We override to always treat <%== as escaped.
30
- def add_expr(src, code, indicator)
31
- case indicator
32
- when '=='
33
- add_expr_escaped(src, code)
34
- else
35
- super
36
- end
37
- end
38
-
39
- BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
40
-
41
- def add_expr_literal(src, code)
42
- flush_newline_if_pending(src)
43
- if code =~ BLOCK_EXPR
44
- src << '@output_buffer.append= ' << code
45
- else
46
- src << '@output_buffer.append=(' << code << ');'
47
- end
48
- end
49
-
50
- def add_expr_escaped(src, code)
51
- flush_newline_if_pending(src)
52
- if code =~ BLOCK_EXPR
53
- src << "@output_buffer.safe_append= " << code
54
- else
55
- src << "@output_buffer.safe_append=(" << code << ");"
56
- end
57
- end
58
-
59
- def add_stmt(src, code)
60
- flush_newline_if_pending(src)
61
- super
62
- end
63
-
64
- def add_postamble(src)
65
- flush_newline_if_pending(src)
66
- src << '@output_buffer.to_s'
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
75
- end
76
-
77
- class ERB
78
- # Specify trim mode for the ERB compiler. Defaults to '-'.
79
- # See ERB documentation for suitable values.
80
- class_attribute :erb_trim_mode
81
- self.erb_trim_mode = '-'
82
-
83
- # Default implementation used.
84
- class_attribute :erb_implementation
85
- self.erb_implementation = Erubis
86
-
87
- # Do not escape templates of these mime types.
88
- class_attribute :escape_whitelist
89
- self.escape_whitelist = ["text/plain"]
90
-
91
- ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
92
-
93
- def self.call(template)
94
- new.call(template)
95
- end
96
-
97
- def supports_streaming?
98
- true
99
- end
100
-
101
- def handles_encoding?
102
- true
103
- end
104
-
105
- def call(template)
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)
111
-
112
- erb = template_source.gsub(ENCODING_TAG, '')
113
- encoding = $2
114
-
115
- erb.force_encoding valid_encoding(template.source.dup, encoding)
116
-
117
- # Always make sure we return a String in the default_internal
118
- erb.encode!
119
-
120
- self.class.erb_implementation.new(
121
- erb,
122
- :escape => (self.class.escape_whitelist.include? template.type),
123
- :trim => (self.class.erb_trim_mode == "-")
124
- ).src
125
- end
126
-
127
- private
128
-
129
- def valid_encoding(string, encoding)
130
- # If a magic encoding comment was found, tag the
131
- # String with this encoding. This is for a case
132
- # where the original String was assumed to be,
133
- # for instance, UTF-8, but a magic comment
134
- # proved otherwise
135
- string.force_encoding(encoding) if encoding
136
-
137
- # If the String is valid, return the encoding we found
138
- return string.encoding if string.valid_encoding?
139
-
140
- # Otherwise, raise an exception
141
- raise WrongEncodingError.new(string, string.encoding)
142
- end
143
- end
144
- end
145
- end
146
- end
@@ -1,11 +0,0 @@
1
- module ActionView
2
- module Template::Handlers
3
- class Raw
4
- def call(template)
5
- escaped = template.source.gsub(':', '\:')
6
-
7
- '%q:' + escaped + ':;'
8
- end
9
- end
10
- end
11
- end
@@ -1,340 +0,0 @@
1
- require "pathname"
2
- require "active_support/core_ext/class"
3
- require "active_support/core_ext/class/attribute_accessors"
4
- require "action_view/template"
5
- require "thread"
6
- require "thread_safe"
7
-
8
- module ActionView
9
- # = Action View Resolver
10
- class Resolver
11
- # Keeps all information about view path and builds virtual path.
12
- class Path
13
- attr_reader :name, :prefix, :partial, :virtual
14
- alias_method :partial?, :partial
15
-
16
- def self.build(name, prefix, partial)
17
- virtual = ""
18
- virtual << "#{prefix}/" unless prefix.empty?
19
- virtual << (partial ? "_#{name}" : name)
20
- new name, prefix, partial, virtual
21
- end
22
-
23
- def initialize(name, prefix, partial, virtual)
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 }
94
- end
95
- end
96
-
97
- cattr_accessor :caching
98
- self.caching = true
99
-
100
- class << self
101
- alias :caching? :caching
102
- end
103
-
104
- def initialize
105
- @cache = Cache.new
106
- end
107
-
108
- def clear_cache
109
- @cache.clear
110
- end
111
-
112
- # Normalizes the arguments and passes it on to find_templates.
113
- def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
114
- cached(key, [name, prefix, partial], details, locals) do
115
- find_templates(name, prefix, partial, details)
116
- end
117
- end
118
-
119
- private
120
-
121
- delegate :caching?, to: :class
122
-
123
- # This is what child classes implement. No defaults are needed
124
- # because Resolver guarantees that the arguments are present and
125
- # normalized.
126
- def find_templates(name, prefix, partial, details)
127
- raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details) method"
128
- end
129
-
130
- # Helpers that builds a path. Useful for building virtual paths.
131
- def build_path(name, prefix, partial)
132
- Path.build(name, prefix, partial)
133
- end
134
-
135
- # Handles templates caching. If a key is given and caching is on
136
- # always check the cache before hitting the resolver. Otherwise,
137
- # it always hits the resolver but if the key is present, check if the
138
- # resolver is fresher before returning it.
139
- def cached(key, path_info, details, locals) #:nodoc:
140
- name, prefix, partial = path_info
141
- locals = locals.map { |x| x.to_s }.sort!
142
-
143
- if key
144
- @cache.cache(key, name, prefix, partial, locals) do
145
- decorate(yield, path_info, details, locals)
146
- end
147
- else
148
- decorate(yield, path_info, details, locals)
149
- end
150
- end
151
-
152
- # Ensures all the resolver information is set in the template.
153
- def decorate(templates, path_info, details, locals) #:nodoc:
154
- cached = nil
155
- templates.each do |t|
156
- t.locals = locals
157
- t.formats = details[:formats] || [:html] if t.formats.empty?
158
- t.virtual_path ||= (cached ||= build_path(*path_info))
159
- end
160
- end
161
- end
162
-
163
- # An abstract class that implements a Resolver with path semantics.
164
- class PathResolver < Resolver #:nodoc:
165
- EXTENSIONS = [:locale, :formats, :handlers]
166
- DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}"
167
-
168
- def initialize(pattern=nil)
169
- @pattern = pattern || DEFAULT_PATTERN
170
- super()
171
- end
172
-
173
- private
174
-
175
- def find_templates(name, prefix, partial, details)
176
- path = Path.build(name, prefix, partial)
177
- query(path, details, details[:formats])
178
- end
179
-
180
- def query(path, details, formats)
181
- query = build_query(path, details)
182
-
183
- template_paths = find_template_paths query
184
-
185
- template_paths.map { |template|
186
- handler, format = extract_handler_and_format(template, formats)
187
- contents = File.binread template
188
-
189
- Template.new(contents, File.expand_path(template), handler,
190
- :virtual_path => path.virtual,
191
- :format => format,
192
- :updated_at => mtime(template))
193
- }
194
- end
195
-
196
- if RUBY_VERSION >= '2.2.0'
197
- def find_template_paths(query)
198
- Dir[query].reject { |filename|
199
- File.directory?(filename) ||
200
- # deals with case-insensitive file systems.
201
- !File.fnmatch(query, filename, File::FNM_EXTGLOB)
202
- }
203
- end
204
- else
205
- def find_template_paths(query)
206
- # deals with case-insensitive file systems.
207
- sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
208
-
209
- Dir[query].reject { |filename|
210
- File.directory?(filename) ||
211
- !sanitizer[File.dirname(filename)].include?(filename)
212
- }
213
- end
214
- end
215
-
216
- # Helper for building query glob string based on resolver's pattern.
217
- def build_query(path, details)
218
- query = @pattern.dup
219
-
220
- prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1"
221
- query.gsub!(/\:prefix(\/)?/, prefix)
222
-
223
- partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
224
- query.gsub!(/\:action/, partial)
225
-
226
- details.each do |ext, variants|
227
- query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
228
- end
229
-
230
- File.expand_path(query, @path)
231
- end
232
-
233
- def escape_entry(entry)
234
- entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
235
- end
236
-
237
- # Returns the file mtime from the filesystem.
238
- def mtime(p)
239
- File.mtime(p)
240
- end
241
-
242
- # Extract handler and formats from path. If a format cannot be a found neither
243
- # from the path, or the handler, we should return the array of formats given
244
- # to the resolver.
245
- def extract_handler_and_format(path, default_formats)
246
- pieces = File.basename(path).split(".")
247
- pieces.shift
248
-
249
- extension = pieces.pop
250
- unless extension
251
- message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
252
- "but will change to RAW in the future."
253
- ActiveSupport::Deprecation.warn message
254
- end
255
-
256
- handler = Template.handler_for_extension(extension)
257
- format = pieces.last && Template::Types[pieces.last]
258
- [handler, format]
259
- end
260
- end
261
-
262
- # A resolver that loads files from the filesystem. It allows setting your own
263
- # resolving pattern. Such pattern can be a glob string supported by some variables.
264
- #
265
- # ==== Examples
266
- #
267
- # Default pattern, loads views the same way as previous versions of rails, eg. when you're
268
- # looking for `users/new` it will produce query glob: `users/new{.{en},}{.{html,js},}{.{erb,haml},}`
269
- #
270
- # FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}")
271
- #
272
- # This one allows you to keep files with different formats in separate subdirectories,
273
- # eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`,
274
- # `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc.
275
- #
276
- # FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{.:handlers,}")
277
- #
278
- # If you don't specify a pattern then the default will be used.
279
- #
280
- # In order to use any of the customized resolvers above in a Rails application, you just need
281
- # to configure ActionController::Base.view_paths in an initializer, for example:
282
- #
283
- # ActionController::Base.view_paths = FileSystemResolver.new(
284
- # Rails.root.join("app/views"),
285
- # ":prefix{/:locale}/:action{.:formats,}{.:handlers,}"
286
- # )
287
- #
288
- # ==== Pattern format and variables
289
- #
290
- # Pattern has to be a valid glob string, and it allows you to use the
291
- # following variables:
292
- #
293
- # * <tt>:prefix</tt> - usually the controller path
294
- # * <tt>:action</tt> - name of the action
295
- # * <tt>:locale</tt> - possible locale versions
296
- # * <tt>:formats</tt> - possible request formats (for example html, json, xml...)
297
- # * <tt>:handlers</tt> - possible handlers (for example erb, haml, builder...)
298
- #
299
- class FileSystemResolver < PathResolver
300
- def initialize(path, pattern=nil)
301
- raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
302
- super(pattern)
303
- @path = File.expand_path(path)
304
- end
305
-
306
- def to_s
307
- @path.to_s
308
- end
309
- alias :to_path :to_s
310
-
311
- def eql?(resolver)
312
- self.class.equal?(resolver.class) && to_path == resolver.to_path
313
- end
314
- alias :== :eql?
315
- end
316
-
317
- # An Optimized resolver for Rails' most common case.
318
- class OptimizedFileSystemResolver < FileSystemResolver #:nodoc:
319
- def build_query(path, details)
320
- exts = EXTENSIONS.map { |ext| details[ext] }
321
- query = escape_entry(File.join(@path, path))
322
-
323
- query + exts.map { |ext|
324
- "{#{ext.compact.uniq.map { |e| ".#{e}," }.join}}"
325
- }.join
326
- end
327
- end
328
-
329
- # The same as FileSystemResolver but does not allow templates to store
330
- # a virtual path since it is invalid for such resolvers.
331
- class FallbackFileSystemResolver < FileSystemResolver #:nodoc:
332
- def self.instances
333
- [new(""), new("/")]
334
- end
335
-
336
- def decorate(*)
337
- super.each { |t| t.virtual_path = nil }
338
- end
339
- end
340
- end