actionpack 3.0.0.beta3 → 3.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (83) hide show
  1. data/CHANGELOG +19 -0
  2. data/lib/abstract_controller.rb +1 -1
  3. data/lib/abstract_controller/asset_paths.rb +9 -0
  4. data/lib/abstract_controller/base.rb +5 -13
  5. data/lib/abstract_controller/callbacks.rb +1 -1
  6. data/lib/abstract_controller/helpers.rb +0 -1
  7. data/lib/abstract_controller/layouts.rb +3 -3
  8. data/lib/abstract_controller/logger.rb +1 -1
  9. data/lib/abstract_controller/rendering.rb +1 -0
  10. data/lib/action_controller/base.rb +5 -1
  11. data/lib/action_controller/caching.rb +2 -3
  12. data/lib/action_controller/caching/actions.rb +1 -1
  13. data/lib/action_controller/caching/fragments.rb +1 -1
  14. data/lib/action_controller/caching/pages.rb +8 -8
  15. data/lib/action_controller/caching/sweeping.rb +1 -0
  16. data/lib/action_controller/deprecated/base.rb +10 -36
  17. data/lib/action_controller/metal.rb +45 -3
  18. data/lib/action_controller/metal/compatibility.rb +2 -2
  19. data/lib/action_controller/metal/helpers.rb +3 -3
  20. data/lib/action_controller/metal/http_authentication.rb +158 -0
  21. data/lib/action_controller/metal/instrumentation.rb +5 -5
  22. data/lib/action_controller/metal/rack_delegation.rb +4 -4
  23. data/lib/action_controller/metal/renderers.rb +3 -3
  24. data/lib/action_controller/metal/request_forgery_protection.rb +45 -74
  25. data/lib/action_controller/metal/responder.rb +1 -1
  26. data/lib/action_controller/metal/url_for.rb +8 -0
  27. data/lib/action_controller/railtie.rb +26 -39
  28. data/lib/action_controller/test_case.rb +147 -135
  29. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -0
  30. data/lib/action_dispatch.rb +0 -1
  31. data/lib/action_dispatch/http/parameters.rb +2 -1
  32. data/lib/action_dispatch/http/request.rb +19 -7
  33. data/lib/action_dispatch/http/response.rb +3 -33
  34. data/lib/action_dispatch/middleware/cookies.rb +44 -10
  35. data/lib/action_dispatch/middleware/flash.rb +11 -1
  36. data/lib/action_dispatch/middleware/params_parser.rb +3 -1
  37. data/lib/action_dispatch/middleware/session/abstract_store.rb +47 -83
  38. data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -165
  39. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
  40. data/lib/action_dispatch/middleware/show_exceptions.rb +18 -12
  41. data/lib/action_dispatch/middleware/stack.rb +17 -67
  42. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
  43. data/lib/action_dispatch/railtie.rb +0 -2
  44. data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -0
  45. data/lib/action_dispatch/routing/mapper.rb +89 -23
  46. data/lib/action_dispatch/routing/route_set.rb +22 -16
  47. data/lib/action_dispatch/routing/url_for.rb +1 -1
  48. data/lib/action_dispatch/testing/assertions/routing.rb +1 -0
  49. data/lib/action_dispatch/testing/assertions/selector.rb +11 -7
  50. data/lib/action_dispatch/testing/test_process.rb +3 -2
  51. data/lib/action_pack/version.rb +1 -1
  52. data/lib/action_view.rb +5 -1
  53. data/lib/action_view/base.rb +10 -4
  54. data/lib/action_view/helpers/active_model_helper.rb +1 -8
  55. data/lib/action_view/helpers/asset_tag_helper.rb +7 -4
  56. data/lib/action_view/helpers/cache_helper.rb +14 -14
  57. data/lib/action_view/helpers/capture_helper.rb +25 -6
  58. data/lib/action_view/helpers/date_helper.rb +33 -44
  59. data/lib/action_view/helpers/form_helper.rb +47 -27
  60. data/lib/action_view/helpers/form_options_helper.rb +26 -3
  61. data/lib/action_view/helpers/form_tag_helper.rb +8 -4
  62. data/lib/action_view/helpers/number_helper.rb +5 -2
  63. data/lib/action_view/helpers/prototype_helper.rb +1 -1
  64. data/lib/action_view/helpers/tag_helper.rb +1 -1
  65. data/lib/action_view/helpers/text_helper.rb +55 -46
  66. data/lib/action_view/helpers/translation_helper.rb +19 -8
  67. data/lib/action_view/helpers/url_helper.rb +2 -4
  68. data/lib/action_view/locale/en.yml +14 -14
  69. data/lib/action_view/lookup_context.rb +52 -22
  70. data/lib/action_view/paths.rb +1 -0
  71. data/lib/action_view/render/layouts.rb +3 -12
  72. data/lib/action_view/render/partials.rb +21 -10
  73. data/lib/action_view/render/rendering.rb +1 -1
  74. data/lib/action_view/template.rb +172 -26
  75. data/lib/action_view/template/error.rb +25 -27
  76. data/lib/action_view/template/handlers.rb +1 -1
  77. data/lib/action_view/template/handlers/erb.rb +92 -45
  78. data/lib/action_view/template/resolver.rb +4 -1
  79. data/lib/action_view/test_case.rb +105 -72
  80. data/lib/action_view/testing/resolvers.rb +43 -0
  81. metadata +62 -20
  82. data/lib/abstract_controller/assigns.rb +0 -21
  83. data/lib/action_dispatch/middleware/cascade.rb +0 -29
@@ -4,6 +4,25 @@ module ActionView
4
4
  class ActionViewError < StandardError #:nodoc:
5
5
  end
6
6
 
7
+ class EncodingError < StandardError #:nodoc:
8
+ end
9
+
10
+ class WrongEncodingError < EncodingError #:nodoc:
11
+ def initialize(string, encoding)
12
+ @string, @encoding = string, encoding
13
+ end
14
+
15
+ def message
16
+ @string.force_encoding("BINARY")
17
+ "Your template was not saved as valid #{@encoding}. Please " \
18
+ "either specify #{@encoding} as the encoding for your template " \
19
+ "in your text editor, or mark the template with its " \
20
+ "encoding by inserting the following as the first line " \
21
+ "of the template:\n\n# encoding: <name of correct encoding>.\n\n" \
22
+ "The source of your template was:\n\n#{@string}"
23
+ end
24
+ end
25
+
7
26
  class MissingTemplate < ActionViewError #:nodoc:
8
27
  attr_reader :path
9
28
 
@@ -21,17 +40,18 @@ module ActionView
21
40
  super("Missing #{template_type} #{path} with #{details.inspect} in view paths #{display_paths}")
22
41
  end
23
42
  end
43
+
24
44
  class Template
25
45
  # The Template::Error exception is raised when the compilation of the template fails. This exception then gathers a
26
46
  # bunch of intimate details and uses it to report a very precise exception message.
27
47
  class Error < ActionViewError #:nodoc:
28
48
  SOURCE_CODE_RADIUS = 3
29
49
 
30
- attr_reader :original_exception
50
+ attr_reader :original_exception, :backtrace
31
51
 
32
52
  def initialize(template, assigns, original_exception)
33
53
  @template, @assigns, @original_exception = template, assigns.dup, original_exception
34
- @backtrace = compute_backtrace
54
+ @backtrace = original_exception.backtrace
35
55
  end
36
56
 
37
57
  def file_name
@@ -42,14 +62,6 @@ module ActionView
42
62
  ActiveSupport::Deprecation.silence { original_exception.message }
43
63
  end
44
64
 
45
- def clean_backtrace
46
- if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
47
- Rails.backtrace_cleaner.clean(original_exception.backtrace)
48
- else
49
- original_exception.backtrace
50
- end
51
- end
52
-
53
65
  def sub_template_message
54
66
  if @sub_templates
55
67
  "Trace of template inclusion: " +
@@ -87,29 +99,15 @@ module ActionView
87
99
  @line_number ||=
88
100
  if file_name
89
101
  regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
90
-
91
- $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp }
102
+ $1 if message =~ regexp || backtrace.find { |line| line =~ regexp }
92
103
  end
93
104
  end
94
105
 
95
- def to_s
96
- "\n#{self.class} (#{message}) #{source_location}:\n" +
97
- "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n"
98
- end
99
-
100
- # don't do anything nontrivial here. Any raised exception from here becomes fatal
101
- # (and can't be rescued).
102
- def backtrace
103
- @backtrace
106
+ def annoted_source_code
107
+ source_extract(4)
104
108
  end
105
109
 
106
110
  private
107
- def compute_backtrace
108
- [
109
- "#{source_location.capitalize}\n\n#{source_extract(4)}\n " +
110
- clean_backtrace.join("\n ")
111
- ]
112
- end
113
111
 
114
112
  def source_location
115
113
  if line_number
@@ -19,7 +19,7 @@ module ActionView #:nodoc:
19
19
  @@default_template_handlers = nil
20
20
 
21
21
  def self.extensions
22
- @@template_handlers.keys
22
+ @@template_extensions ||= @@template_handlers.keys
23
23
  end
24
24
 
25
25
  # Register a class that knows how to handle template files with the given
@@ -1,9 +1,15 @@
1
1
  require 'active_support/core_ext/class/attribute_accessors'
2
2
  require 'active_support/core_ext/string/output_safety'
3
+ require "action_view/template"
3
4
  require 'erubis'
4
5
 
5
6
  module ActionView
6
7
  class OutputBuffer < ActiveSupport::SafeBuffer
8
+ def initialize(*)
9
+ super
10
+ encode! if encoding_aware?
11
+ end
12
+
7
13
  def <<(value)
8
14
  super(value.to_s)
9
15
  end
@@ -17,65 +23,106 @@ module ActionView
17
23
  end
18
24
  end
19
25
 
20
- module Template::Handlers
21
- class Erubis < ::Erubis::Eruby
22
- def add_preamble(src)
23
- src << "@output_buffer = ActionView::OutputBuffer.new;"
24
- end
26
+ class Template
27
+ module Handlers
28
+ class Erubis < ::Erubis::Eruby
29
+ def add_preamble(src)
30
+ src << "@output_buffer = ActionView::OutputBuffer.new;"
31
+ end
25
32
 
26
- def add_text(src, text)
27
- return if text.empty?
28
- src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
29
- end
33
+ def add_text(src, text)
34
+ return if text.empty?
35
+ src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
36
+ end
30
37
 
31
- BLOCK_EXPR = /(do|\{)(\s*\|[^|]*\|)?\s*\Z/
38
+ BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
32
39
 
33
- def add_expr_literal(src, code)
34
- if code =~ BLOCK_EXPR
35
- src << '@output_buffer.append= ' << code
36
- else
37
- src << '@output_buffer.append= (' << code << ');'
40
+ def add_expr_literal(src, code)
41
+ if code =~ BLOCK_EXPR
42
+ src << '@output_buffer.append= ' << code
43
+ else
44
+ src << '@output_buffer.append= (' << code << ');'
45
+ end
38
46
  end
39
- end
40
47
 
41
- def add_stmt(src, code)
42
- if code =~ BLOCK_EXPR
43
- src << '@output_buffer.append_if_string= ' << code
44
- else
45
- super
48
+ def add_stmt(src, code)
49
+ if code =~ BLOCK_EXPR
50
+ src << '@output_buffer.append_if_string= ' << code
51
+ else
52
+ super
53
+ end
46
54
  end
47
- end
48
55
 
49
- def add_expr_escaped(src, code)
50
- src << '@output_buffer.append= ' << escaped_expr(code) << ';'
51
- end
56
+ def add_expr_escaped(src, code)
57
+ src << '@output_buffer.append= ' << escaped_expr(code) << ';'
58
+ end
52
59
 
53
- def add_postamble(src)
54
- src << '@output_buffer.to_s'
60
+ def add_postamble(src)
61
+ src << '@output_buffer.to_s'
62
+ end
55
63
  end
56
- end
57
64
 
58
- class ERB < Template::Handler
59
- include Compilable
65
+ class ERB < Handler
66
+ include Compilable
60
67
 
61
- ##
62
- # :singleton-method:
63
- # Specify trim mode for the ERB compiler. Defaults to '-'.
64
- # See ERb documentation for suitable values.
65
- cattr_accessor :erb_trim_mode
66
- self.erb_trim_mode = '-'
68
+ ##
69
+ # :singleton-method:
70
+ # Specify trim mode for the ERB compiler. Defaults to '-'.
71
+ # See ERb documentation for suitable values.
72
+ cattr_accessor :erb_trim_mode
73
+ self.erb_trim_mode = '-'
67
74
 
68
- self.default_format = Mime::HTML
75
+ self.default_format = Mime::HTML
69
76
 
70
- cattr_accessor :erb_implementation
71
- self.erb_implementation = Erubis
77
+ cattr_accessor :erb_implementation
78
+ self.erb_implementation = Erubis
72
79
 
73
- def compile(template)
74
- source = template.source.gsub(/\A(<%(#.*coding[:=]\s*(\S+)\s*)-?%>)\s*\n?/, '')
75
- erb = "<% __in_erb_template=true %>#{source}"
76
- result = self.class.erb_implementation.new(erb, :trim=>(self.class.erb_trim_mode == "-")).src
77
- result = "#{$2}\n#{result}" if $2
78
- result
80
+ ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
81
+
82
+ def self.handles_encoding?
83
+ true
84
+ end
85
+
86
+ def compile(template)
87
+ if template.source.encoding_aware?
88
+ # First, convert to BINARY, so in case the encoding is
89
+ # wrong, we can still find an encoding tag
90
+ # (<%# encoding %>) inside the String using a regular
91
+ # expression
92
+ template_source = template.source.dup.force_encoding("BINARY")
93
+
94
+ erb = template_source.gsub(ENCODING_TAG, '')
95
+ encoding = $2
96
+
97
+ erb.force_encoding valid_encoding(template.source.dup, encoding)
98
+
99
+ # Always make sure we return a String in the default_internal
100
+ erb.encode!
101
+ else
102
+ erb = template.source.dup
103
+ end
104
+
105
+ self.class.erb_implementation.new(
106
+ erb,
107
+ :trim => (self.class.erb_trim_mode == "-")
108
+ ).src
109
+ end
110
+
111
+ private
112
+ def valid_encoding(string, encoding)
113
+ # If a magic encoding comment was found, tag the
114
+ # String with this encoding. This is for a case
115
+ # where the original String was assumed to be,
116
+ # for instance, UTF-8, but a magic comment
117
+ # proved otherwise
118
+ string.force_encoding(encoding) if encoding
119
+
120
+ # If the String is valid, return the encoding we found
121
+ return string.encoding if string.valid_encoding?
122
+
123
+ # Otherwise, raise an exception
124
+ raise WrongEncodingError.new(string, string.encoding)
125
+ end
79
126
  end
80
127
  end
81
128
  end
@@ -70,7 +70,10 @@ module ActionView
70
70
 
71
71
  Dir[query].reject { |p| File.directory?(p) }.map do |p|
72
72
  handler, format = extract_handler_and_format(p, formats)
73
- Template.new(File.read(p), File.expand_path(p), handler,
73
+
74
+ contents = File.open(p, "rb") {|io| io.read }
75
+
76
+ Template.new(contents, File.expand_path(p), handler,
74
77
  :virtual_path => path, :format => format)
75
78
  end
76
79
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/object/blank'
2
+ require 'action_controller'
2
3
  require 'action_controller/test_case'
3
4
  require 'action_view'
4
5
 
@@ -9,11 +10,16 @@ module ActionView
9
10
 
10
11
  attr_accessor :request, :response, :params
11
12
 
12
- def self.controller_path
13
- ''
13
+ class << self
14
+ attr_writer :controller_path
15
+ end
16
+
17
+ def controller_path=(path)
18
+ self.class.controller_path=(path)
14
19
  end
15
20
 
16
21
  def initialize
22
+ self.class.controller_path = ""
17
23
  @request = ActionController::TestRequest.new
18
24
  @response = ActionController::TestResponse.new
19
25
 
@@ -23,80 +29,99 @@ module ActionView
23
29
  end
24
30
  end
25
31
 
26
- include ActionDispatch::Assertions, ActionDispatch::TestProcess
27
- include ActionController::TemplateAssertions
28
- include ActionView::Context
32
+ module Behavior
33
+ extend ActiveSupport::Concern
29
34
 
30
- include ActionController::PolymorphicRoutes
31
- include ActionController::RecordIdentifier
35
+ include ActionDispatch::Assertions, ActionDispatch::TestProcess
36
+ include ActionController::TemplateAssertions
37
+ include ActionView::Context
32
38
 
33
- include ActionView::Helpers
34
- include ActionController::Helpers
39
+ include ActionController::PolymorphicRoutes
40
+ include ActionController::RecordIdentifier
35
41
 
36
- class_inheritable_accessor :helper_class
37
- attr_accessor :controller, :output_buffer, :rendered
42
+ include AbstractController::Helpers
43
+ include ActionView::Helpers
38
44
 
39
- setup :setup_with_controller
40
- def setup_with_controller
41
- @controller = TestController.new
42
- @output_buffer = ActiveSupport::SafeBuffer.new
43
- @rendered = ''
45
+ attr_accessor :controller, :output_buffer, :rendered
46
+
47
+ module ClassMethods
48
+ def tests(helper_class)
49
+ self.helper_class = helper_class
50
+ end
44
51
 
45
- self.class.send(:include_helper_modules!)
46
- make_test_case_available_to_view!
47
- end
52
+ def determine_default_helper_class(name)
53
+ mod = name.sub(/Test$/, '').constantize
54
+ mod.is_a?(Class) ? nil : mod
55
+ rescue NameError
56
+ nil
57
+ end
48
58
 
49
- def config
50
- @controller.config if @controller.respond_to?(:config)
51
- end
59
+ def helper_method(*methods)
60
+ # Almost a duplicate from ActionController::Helpers
61
+ methods.flatten.each do |method|
62
+ _helpers.module_eval <<-end_eval
63
+ def #{method}(*args, &block) # def current_user(*args, &block)
64
+ _test_case.send(%(#{method}), *args, &block) # test_case.send(%(current_user), *args, &block)
65
+ end # end
66
+ end_eval
67
+ end
68
+ end
52
69
 
53
- def render(options = {}, local_assigns = {}, &block)
54
- @rendered << output = _view.render(options, local_assigns, &block)
55
- output
56
- end
70
+ attr_writer :helper_class
57
71
 
58
- def protect_against_forgery?
59
- false
60
- end
72
+ def helper_class
73
+ @helper_class ||= determine_default_helper_class(name)
74
+ end
61
75
 
62
- class << self
63
- def tests(helper_class)
64
- self.helper_class = helper_class
65
- end
76
+ private
66
77
 
67
- def helper_class
68
- if current_helper_class = read_inheritable_attribute(:helper_class)
69
- current_helper_class
70
- else
71
- self.helper_class = determine_default_helper_class(name)
78
+ def include_helper_modules!
79
+ helper(helper_class) if helper_class
80
+ include _helpers
72
81
  end
82
+
73
83
  end
74
84
 
75
- def determine_default_helper_class(name)
76
- name.sub(/Test$/, '').constantize
77
- rescue NameError
78
- nil
85
+ def setup_with_controller
86
+ @controller = ActionView::TestCase::TestController.new
87
+ @output_buffer = ActiveSupport::SafeBuffer.new
88
+ @rendered = ''
89
+
90
+ self.class.send(:include_helper_modules!)
91
+ make_test_case_available_to_view!
92
+ say_no_to_protect_against_forgery!
79
93
  end
80
94
 
81
- def helper_method(*methods)
82
- # Almost a duplicate from ActionController::Helpers
83
- methods.flatten.each do |method|
84
- _helpers.module_eval <<-end_eval
85
- def #{method}(*args, &block) # def current_user(*args, &block)
86
- _test_case.send(%(#{method}), *args, &block) # test_case.send(%(current_user), *args, &block)
87
- end # end
88
- end_eval
89
- end
95
+ def config
96
+ @controller.config if @controller.respond_to?(:config)
90
97
  end
91
98
 
92
- private
93
- def include_helper_modules!
94
- helper(helper_class) if helper_class
95
- include _helpers
96
- end
97
- end
99
+ def render(options = {}, local_assigns = {}, &block)
100
+ @rendered << output = _view.render(options, local_assigns, &block)
101
+ output
102
+ end
103
+
104
+ included do
105
+ setup :setup_with_controller
106
+ end
98
107
 
99
108
  private
109
+
110
+ # Support the selector assertions
111
+ #
112
+ # Need to experiment if this priority is the best one: rendered => output_buffer
113
+ def response_from_page_or_rjs
114
+ HTML::Document.new(@rendered.blank? ? @output_buffer : @rendered).root
115
+ end
116
+
117
+ def say_no_to_protect_against_forgery!
118
+ _helpers.module_eval do
119
+ def protect_against_forgery?
120
+ false
121
+ end
122
+ end
123
+ end
124
+
100
125
  def make_test_case_available_to_view!
101
126
  test_case_instance = self
102
127
  _helpers.module_eval do
@@ -106,32 +131,35 @@ module ActionView
106
131
  end
107
132
 
108
133
  def _view
109
- view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
110
- view.singleton_class.send :include, _helpers
111
- view.singleton_class.send :include, @controller._router.url_helpers
112
- view.output_buffer = self.output_buffer
113
- view
114
- end
115
-
116
- # Support the selector assertions
117
- #
118
- # Need to experiment if this priority is the best one: rendered => output_buffer
119
- def response_from_page_or_rjs
120
- HTML::Document.new(rendered.blank? ? output_buffer : rendered).root
134
+ @_view ||= begin
135
+ view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
136
+ view.singleton_class.send :include, _helpers
137
+ view.singleton_class.send :include, @controller._router.url_helpers
138
+ view.singleton_class.send :delegate, :alert, :notice, :to => "request.flash"
139
+ view.output_buffer = self.output_buffer
140
+ view
141
+ end
121
142
  end
122
143
 
123
144
  EXCLUDE_IVARS = %w{
145
+ @_result
124
146
  @output_buffer
125
- @fixture_cache
147
+ @rendered
148
+ @templates
149
+ @view_context_class
150
+ @layouts
151
+ @partials
152
+ @controller
153
+
126
154
  @method_name
127
- @_result
155
+ @fixture_cache
128
156
  @loaded_fixtures
129
157
  @test_passed
130
- @view
131
158
  }
132
159
 
133
160
  def _instance_variables
134
161
  instance_variables - EXCLUDE_IVARS
162
+ instance_variables
135
163
  end
136
164
 
137
165
  def _assigns
@@ -154,5 +182,10 @@ module ActionView
154
182
  super
155
183
  end
156
184
  end
185
+
186
+ end
187
+
188
+ include Behavior
189
+
157
190
  end
158
191
  end