diff options
Diffstat (limited to 'actionpack')
78 files changed, 710 insertions, 221 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index ec85f67e58..68cce142a2 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,23 @@ ## Rails 4.0.0 (unreleased) ## +* Fixed issue with where Digest authentication would not work behind a proxy. *Arthur Smith* + +* Added ActionController::Live. Mix it in to your controller and you can + stream data to the client live. For example: + + class FooController < ActionController::Base + include ActionController::Live + + def index + 100.times { + # Client will see this as it's written + response.stream.write "hello world\n" + sleep 1 + } + response.stream.close + end + end + * Remove ActionDispatch::Head middleware in favor of Rack::Head. *Santiago Pastorino* * Deprecate `:confirm` in favor of `:data => { :confirm => "Text" }` option for `button_to`, `button_tag`, `image_submit_tag`, `link_to` and `submit_tag` helpers. diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index b95ea5f0b2..867a7954e0 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -1,9 +1,6 @@ require 'action_pack' -require 'active_support/concern' -require 'active_support/dependencies/autoload' -require 'active_support/core_ext/class/attribute' +require 'active_support/rails' require 'active_support/core_ext/module/attr_internal' -require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/anonymous' require 'active_support/i18n' diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 7c10fcbb8a..ceb90f8cee 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,5 +1,7 @@ +require 'active_support/rails' require 'abstract_controller' require 'action_dispatch' +require 'action_controller/metal/live' module ActionController extend ActiveSupport::Autoload @@ -53,11 +55,9 @@ require 'action_view' require 'action_controller/vendor/html-scanner' # Common Active Support usage in Action Controller -require 'active_support/concern' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/load_error' require 'active_support/core_ext/module/attr_internal' -require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/name_error' require 'active_support/core_ext/uri' require 'active_support/inflector' diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index 0fb419f941..a7c0e971e7 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' module ActionController class LogSubscriber < ActiveSupport::LogSubscriber diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 92433ab462..b38f990efa 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/object/blank' require 'action_dispatch/middleware/stack' module ActionController @@ -187,7 +185,7 @@ module ActionController end def performed? - !!response_body + response_body || (response && response.committed?) end def dispatch(name, request) #:nodoc: diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 2fcd933d32..747e1273be 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -29,19 +29,19 @@ module ActionController self.status = status self.location = url_for(location) if location - if include_content_headers?(self.status) + if include_content?(self.status) self.content_type = content_type || (Mime[formats.first] if formats) + self.response_body = " " else headers.delete('Content-Type') headers.delete('Content-Length') + self.response_body = "" end - - self.response_body = " " end private # :nodoc: - def include_content_headers?(status) + def include_content?(status) case status when 100..199 false diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 66cdfd40ff..d2cbbd3330 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/class/attribute' module ActionController # The \Rails framework provides a large number of helpers for working with assets, dates, forms, diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb index b55c4643be..420b22cf56 100644 --- a/actionpack/lib/action_controller/metal/hide_actions.rb +++ b/actionpack/lib/action_controller/metal/hide_actions.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/class/attribute' module ActionController # Adds the ability to prevent public methods on a controller to be called as actions. diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 0050ede806..03b8d8db1a 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -1,5 +1,4 @@ require 'base64' -require 'active_support/core_ext/object/blank' module ActionController # Makes it dead easy to do HTTP Basic, Digest and Token authentication. @@ -194,7 +193,7 @@ module ActionController return false unless password method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD'] - uri = credentials[:uri][0,1] == '/' ? request.original_fullpath : request.original_url + uri = credentials[:uri] [true, false].any? do |trailing_question_mark| [true, false].any? do |password_is_ha1| @@ -229,9 +228,9 @@ module ActionController end def decode_credentials(header) - Hash[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair| + HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair| key, value = pair.split('=', 2) - [key.strip.to_sym, value.to_s.gsub(/^"|"$/,'').delete('\'')] + [key.strip, value.to_s.gsub(/^"|"$/,'').delete('\'')] end] end @@ -372,7 +371,7 @@ module ActionController # def test_access_granted_from_xml # get( # "/notes/1.xml", nil, - # :authorization => ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) + # 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) # ) # # assert_equal 200, status diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb new file mode 100644 index 0000000000..43a9e3aa9d --- /dev/null +++ b/actionpack/lib/action_controller/metal/live.rb @@ -0,0 +1,138 @@ +require 'action_dispatch/http/response' +require 'delegate' + +module ActionController + # Mix this module in to your controller, and all actions in that controller + # will be able to stream data to the client as it's written. + # + # class MyController < ActionController::Base + # include ActionController::Live + # + # def stream + # response.headers['Content-Type'] = 'text/event-stream' + # 100.times { + # response.stream.write "hello world\n" + # sleep 1 + # } + # response.stream.close + # end + # end + # + # There are a few caveats with this use. You *cannot* write headers after the + # response has been committed (Response#committed? will return truthy). + # Calling +write+ or +close+ on the response stream will cause the response + # object to be committed. Make sure all headers are set before calling write + # or close on your stream. + # + # You *must* call close on your stream when you're finished, otherwise the + # socket may be left open forever. + # + # The final caveat is that your actions are executed in a separate thread than + # the main thread. Make sure your actions are thread safe, and this shouldn't + # be a problem (don't share state across threads, etc). + module Live + class Buffer < ActionDispatch::Response::Buffer #:nodoc: + def initialize(response) + super(response, Queue.new) + end + + def write(string) + unless @response.committed? + @response.headers["Cache-Control"] = "no-cache" + @response.headers.delete("Content-Length") + end + + super + end + + def each + while str = @buf.pop + yield(str) + end + end + + def close + super + @buf.push(nil) + end + end + + class Response < ActionDispatch::Response #:nodoc: all + class Header < DelegateClass(Hash) + def initialize(response, header) + @response = response + super(header) + end + + def []=(k,v) + if @response.committed? + raise ActionDispatch::IllegalStateError, 'header already sent' + end + + super + end + + def to_hash + __getobj__.dup + end + end + + def initialize(status = 200, header = {}, body = []) + header = Header.new(self, header) + super(status, header, body) + end + + def commit! + headers.freeze + super + end + + private + + def build_buffer(response, body) + buf = Live::Buffer.new(response) + body.each { |part| buf.write(part) } + buf + end + end + + def process(name) + t1 = Thread.current + locals = t1.keys.map { |key| [key, t1[key]] } + + # This processes the action in a child thread. It lets us return the + # response code and headers back up the rack stack, and still process + # the body in parallel with sending data to the client + Thread.new { + t2 = Thread.current + t2.abort_on_exception = true + + # Since we're processing the view in a different thread, copy the + # thread locals from the main thread to the child thread. :'( + locals.each { |k,v| t2[k] = v } + + begin + super(name) + ensure + @_response.commit! + end + } + + @_response.await_commit + end + + def response_body=(body) + super + response.stream.close if response + end + + def set_response!(request) + if request.env["HTTP_VERSION"] == "HTTP/1.0" + super + else + @_response = Live::Response.new + @_response.request = request + end + end + end +end diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 4665fea91a..18ae2c3bfc 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -1,6 +1,4 @@ require 'abstract_controller/collector' -require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/object/inclusion' module ActionController #:nodoc: module MimeResponds @@ -343,9 +341,9 @@ module ActionController #:nodoc: config = self.class.mimes_for_respond_to[mime] if config[:except] - !action.in?(config[:except]) + !config[:except].include?(action) elsif config[:only] - action.in?(config[:only]) + config[:only].include?(action) else true end diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index aa67fa7f23..2736948ce0 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/module/anonymous' diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index 1927c8bdc7..78aeeef2bf 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/object/blank' require 'set' module ActionController diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 53534c0307..d5f1cbc1a8 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/class/attribute' require 'action_controller/metal/exceptions' module ActionController #:nodoc: diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index e28c05cc2d..dd5ceb3478 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -27,7 +27,7 @@ module ActionController :host => request.host, :port => request.optional_port, :protocol => request.protocol, - :_path_segments => request.symbolized_path_parameters + :_recall => request.symbolized_path_parameters ).freeze if _routes.equal?(env["action_dispatch.routes"]) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 5f50bf5de6..bb693c6494 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,7 +1,5 @@ require 'rack/session/abstract/id' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/to_query' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/module/anonymous' module ActionController @@ -220,14 +218,7 @@ module ActionController class TestResponse < ActionDispatch::TestResponse def recycle! - @status = 200 - @header = {} - @writer = lambda { |x| @body << x } - @block = nil - @length = 0 - @body = [] - @charset = @content_type = nil - @request = @template = nil + initialize end end @@ -524,20 +515,36 @@ module ActionController end def setup_controller_request_and_response - @request = TestRequest.new - @response = TestResponse.new + @request = build_request + @response = build_response @response.request = @request + @controller = nil unless defined? @controller + if klass = self.class.controller_class - @controller ||= klass.new rescue nil + unless @controller + begin + @controller = klass.new + rescue + warn "could not construct controller #{klass}" if $VERBOSE + end + end end - if defined?(@controller) && @controller + if @controller @controller.request = @request @controller.params = {} end end + def build_request + TestRequest.new + end + + def build_response + TestResponse.new + end + included do include ActionController::TemplateAssertions include ActionDispatch::Assertions @@ -574,7 +581,7 @@ module ActionController :only_path => true, :action => action, :relative_url_root => nil, - :_path_segments => @request.symbolized_path_parameters) + :_recall => @request.symbolized_path_parameters) url, query_string = @routes.url_for(options).split("?", 2) diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb index 6b269e7a31..6b4ececda2 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb @@ -1,6 +1,5 @@ require 'set' require 'cgi' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' module HTML diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 1e4ac70f3d..cc81970ddc 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -22,7 +22,7 @@ #++ require 'active_support' -require 'active_support/dependencies/autoload' +require 'active_support/rails' require 'active_support/core_ext/module/attribute_accessors' require 'action_pack' @@ -36,6 +36,9 @@ end module ActionDispatch extend ActiveSupport::Autoload + class IllegalStateError < StandardError + end + autoload_under 'http' do autoload :Request autoload :Response diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 0b895e7860..a7f93b780e 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' module ActionDispatch module Http @@ -86,21 +85,29 @@ module ActionDispatch CACHE_CONTROL = "Cache-Control".freeze SPESHUL_KEYS = %w[extras no-cache max-age public must-revalidate] + def cache_control_segments + if cache_control = self[CACHE_CONTROL] + cache_control.delete(' ').split(',') + else + [] + end + end + def cache_control_headers cache_control = {} - if cc = self[CACHE_CONTROL] - cc.delete(' ').split(',').each do |segment| - directive, argument = segment.split('=', 2) - case directive - when *SPESHUL_KEYS - key = directive.tr('-', '_') - cache_control[key.to_sym] = argument || true - else - cache_control[:extras] ||= [] - cache_control[:extras] << segment - end + + cache_control_segments.each do |segment| + directive, argument = segment.split('=', 2) + + if SPESHUL_KEYS.include? directive + key = directive.tr('-', '_') + cache_control[key.to_sym] = argument || true + else + cache_control[:extras] ||= [] + cache_control[:extras] << segment end end + cache_control end diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 6413929be3..47cf41cfa3 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/object/duplicable' diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index fe39c220a5..fd86966c50 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -1,6 +1,5 @@ require 'set' require 'active_support/core_ext/class/attribute_accessors' -require 'active_support/core_ext/object/blank' module Mime class Mimes < Array diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index cc46f9983c..d336808e7c 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -1,7 +1,6 @@ require 'digest/md5' -require 'active_support/core_ext/module/delegation' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/class/attribute_accessors' +require 'monitor' module ActionDispatch # :nodoc: # Represents an HTTP response generated by a controller action. Use it to @@ -41,7 +40,7 @@ module ActionDispatch # :nodoc: alias_method :headers, :header delegate :[], :[]=, :to => :@header - delegate :each, :to => :@body + delegate :each, :to => :@stream # Sets the HTTP response's content MIME type. For example, in the controller # you could write this: @@ -62,12 +61,49 @@ module ActionDispatch # :nodoc: include Rack::Response::Helpers include ActionDispatch::Http::Cache::Response + include MonitorMixin + + class Buffer # :nodoc: + def initialize(response, buf) + @response = response + @buf = buf + @closed = false + end + + def write(string) + raise IOError, "closed stream" if closed? + + @response.commit! + @buf.push string + end + + def each(&block) + @buf.each(&block) + end + + def close + @response.commit! + @closed = true + end + + def closed? + @closed + end + end + + attr_reader :stream def initialize(status = 200, header = {}, body = []) + super() + self.body, self.header, self.status = body, header, status @sending_file = false - @blank = false + @blank = false + @cv = new_cond + @committed = false + @content_type = nil + @charset = nil if content_type = self[CONTENT_TYPE] type, charset = content_type.split(/;\s*charset=/) @@ -80,6 +116,23 @@ module ActionDispatch # :nodoc: yield self if block_given? end + def await_commit + synchronize do + @cv.wait_until { @committed } + end + end + + def commit! + synchronize do + @committed = true + @cv.broadcast + end + end + + def committed? + @committed + end + def status=(status) @status = Rack::Utils.status_code(status) end @@ -105,14 +158,14 @@ module ActionDispatch # :nodoc: def respond_to?(method) if method.to_sym == :to_path - @body.respond_to?(:to_path) + stream.respond_to?(:to_path) else super end end def to_path - @body.to_path + stream.to_path end def body @@ -126,11 +179,17 @@ module ActionDispatch # :nodoc: def body=(body) @blank = true if body == EMPTY - @body = body.respond_to?(:each) ? body : [body] + if body.respond_to?(:to_path) + @stream = body + else + @stream = build_buffer self, munge_body_object(body) + end end def body_parts - @body + parts = [] + @stream.each { |x| parts << x } + parts end def set_cookie(key, value) @@ -151,21 +210,11 @@ module ActionDispatch # :nodoc: end def close - @body.close if @body.respond_to?(:close) + stream.close if stream.respond_to?(:close) end def to_a - assign_default_content_type_and_charset! - handle_conditional_get! - - @header[SET_COOKIE] = @header[SET_COOKIE].join("\n") if @header[SET_COOKIE].respond_to?(:join) - - if [204, 304].include?(@status) - @header.delete CONTENT_TYPE - [@status, @header, []] - else - [@status, @header, self] - end + rack_response @status, @header.to_hash end alias prepare! to_a alias to_ary to_a # For implicit splat on 1.9.2 @@ -189,7 +238,15 @@ module ActionDispatch # :nodoc: private - def assign_default_content_type_and_charset! + def build_buffer(response, body) + Buffer.new response, body + end + + def munge_body_object(body) + body.respond_to?(:each) ? body : [body] + end + + def assign_default_content_type_and_charset!(headers) return if headers[CONTENT_TYPE].present? @content_type ||= Mime::HTML @@ -200,5 +257,19 @@ module ActionDispatch # :nodoc: headers[CONTENT_TYPE] = type end + + def rack_response(status, header) + assign_default_content_type_and_charset!(header) + handle_conditional_get! + + header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join) + + if [204, 304].include?(@status) + header.delete CONTENT_TYPE + [status, header, []] + else + [status, header, self] + end + end end end diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index 338b116940..852f1cf6f5 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/module/delegation' module ActionDispatch # Provide callbacks to be executed before and after the request dispatch. diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 771f075275..ba5d332d49 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -1,5 +1,5 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/keys' +require 'active_support/core_ext/module/attribute_accessors' module ActionDispatch class Request < Rack::Request diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb index 6fff94707c..44290445d4 100644 --- a/actionpack/lib/action_dispatch/middleware/request_id.rb +++ b/actionpack/lib/action_dispatch/middleware/request_id.rb @@ -1,6 +1,5 @@ require 'securerandom' require 'active_support/core_ext/string/access' -require 'active_support/core_ext/object/blank' module ActionDispatch # Makes a unique request id available to the action_dispatch.request_id env variable (which is then accessible through diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 64159fa8e7..7c12590c49 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -3,7 +3,6 @@ require 'rack/request' require 'rack/session/abstract/id' require 'action_dispatch/middleware/cookies' require 'action_dispatch/request/session' -require 'active_support/core_ext/object/blank' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 7efc094f98..9b159b2caf 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/hash/keys' -require 'active_support/core_ext/object/blank' require 'action_dispatch/middleware/session/abstract_store' require 'rack/session/cookie' diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0a65b4dbcc..5e2f1ff1e0 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,7 +1,6 @@ require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/reverse_merge' require 'active_support/core_ext/hash/slice' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/enumerable' require 'active_support/inflector' require 'action_dispatch/routing/redirection' @@ -404,6 +403,10 @@ module ActionDispatch # # # Matches any request starting with 'path' # match 'path' => 'c#a', :anchor => false + # + # [:format] + # Allows you to specify the default value for optional +format+ + # segment or disable it by supplying +false+. def match(path, options=nil) end @@ -1186,6 +1189,10 @@ module ActionDispatch # sekret_comment PATCH/PUT /comments/:id(.:format) # sekret_comment DELETE /comments/:id(.:format) # + # [:format] + # Allows you to specify the default value for optional +format+ + # segment or disable it by supplying +false+. + # # === Examples # # # routes call <tt>Admin::PostsController</tt> diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0bbed6cbea..62c921ff97 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -1,6 +1,5 @@ require 'journey' require 'forwardable' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/to_query' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/module/remove_method' @@ -162,19 +161,12 @@ module ActionDispatch end private - def url_helper_name(name, only_path) - if only_path - :"#{name}_path" - else - :"#{name}_url" - end - end def define_named_route_methods(name, route) - [true, false].each do |only_path| - hash = route.defaults.merge(:use_route => name, :only_path => only_path) - define_url_helper route, name, hash - end + define_url_helper route, :"#{name}_path", + route.defaults.merge(:use_route => name, :only_path => true) + define_url_helper route, :"#{name}_url", + route.defaults.merge(:use_route => name, :only_path => false) end # Create a url helper allowing ordered parameters to be associated @@ -191,11 +183,9 @@ module ActionDispatch # foo_url(bar, baz, bang, :sort_by => 'baz') # def define_url_helper(route, name, options) - selector = url_helper_name(name, options[:only_path]) - @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 - remove_possible_method :#{selector} - def #{selector}(*args) + remove_possible_method :#{name} + def #{name}(*args) if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation? options = #{options.inspect} options.merge!(url_options) if respond_to?(:url_options) @@ -207,7 +197,7 @@ module ActionDispatch end END_EVAL - helpers << selector + helpers << name end # Clause check about when we need to generate an optimized helper. @@ -477,10 +467,8 @@ module ActionDispatch def use_recall_for(key) if @recall[key] && (!@options.key?(key) || @options[key] == @recall[key]) - if named_route_exists? - @options[key] = @recall.delete(key) if segment_keys.include?(key) - else - @options[key] = @recall.delete(key) + if !named_route_exists? || segment_keys.include?(key) + @options[key] = @recall.delete(key) end end end @@ -608,13 +596,13 @@ module ActionDispatch options = default_url_options.merge(options || {}) user, password = extract_authentication(options) - path_segments = options.delete(:_path_segments) + recall = options.delete(:_recall) script_name = options.delete(:script_name).presence || _generate_prefix(options) path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? - path, params = generate(path_options, path_segments || {}) + path, params = generate(path_options, recall || {}) params.merge!(options[:params] || {}) ActionDispatch::Http::URL.url_for(options.merge!({ diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index fd3bed7e8f..f4c708ea33 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -102,7 +102,7 @@ module ActionDispatch super end - # Hook overriden in controller to add request information + # Hook overridden in controller to add request information # with `default_url_options`. Application logic should not # go into url_options. def url_options diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index b4c8f839ac..b15e0446de 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/inclusion' module ActionDispatch module Assertions diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index 5f9c3bbf48..d19d116a1f 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -1,5 +1,4 @@ require 'action_controller/vendor/html-scanner' -require 'active_support/core_ext/object/inclusion' #-- # Copyright (c) 2006 Assaf Arkin (http://labnotes.org) diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 50ca28395b..ab584abf68 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -1,7 +1,6 @@ require 'stringio' require 'uri' require 'active_support/core_ext/kernel/singleton_class' -require 'active_support/core_ext/object/inclusion' require 'active_support/core_ext/object/try' require 'rack/test' @@ -346,7 +345,7 @@ module ActionDispatch define_method(method) do |*args| reset! unless integration_session # reset the html_document variable, but only for new get/post calls - @html_document = nil unless method.in?(["cookies", "assigns"]) + @html_document = nil unless method == 'cookies' || method == 'assigns' integration_session.__send__(method, *args).tap do copy_session_variables! end diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index 639ae6f398..c63778f870 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/indifferent_access' require 'rack/utils' diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 03dfa110e3..4bd72c5520 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -22,6 +22,7 @@ #++ require 'active_support' +require 'active_support/rails' require 'action_pack' module ActionView diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 7bfbc1f0aa..749332eca7 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,6 +1,4 @@ require 'active_support/core_ext/module/attr_internal' -require 'active_support/core_ext/module/delegation' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/ordered_options' require 'action_view/log_subscriber' diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index e27111012d..901f433c70 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/enumerable' -require 'active_support/core_ext/object/blank' module ActionView # = Active Model Helpers diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb index 1a54ca2399..e42e49fb04 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/file' require 'action_view/helpers/tag_helper' diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb index e0dbfe62c6..14d62af67b 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb @@ -1,4 +1,3 @@ -require 'active_support/concern' require 'active_support/core_ext/file' require 'action_view/helpers/asset_tag_helpers/asset_include_tag' diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb index 91318b2812..e3a86a8889 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb @@ -1,4 +1,3 @@ -require 'active_support/concern' require 'active_support/core_ext/file' require 'action_view/helpers/asset_tag_helpers/asset_include_tag' diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 397738dd98..c98101a195 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' module ActionView @@ -134,7 +133,7 @@ module ActionView # # <%# Add some other content, or use a different template: %> # - # <% content_for :navigation, true do %> + # <% content_for :navigation, flush: true do %> # <li><%= link_to 'Login', :action => 'login' %></li> # <% end %> # @@ -148,14 +147,14 @@ module ActionView # # WARNING: content_for is ignored in caches. So you shouldn't use it # for elements that will be fragment cached. - def content_for(name, content = nil, flush = false, &block) + def content_for(name, content = nil, options = {}, &block) if content || block_given? if block_given? - flush = content if content + options = content if content content = capture(&block) end if content - flush ? @view_flow.set(name, content) : @view_flow.append(name, content) + options[:flush] ? @view_flow.set(name, content) : @view_flow.append(name, content) end nil else @@ -213,7 +212,7 @@ module ActionView # Add the output buffer to the response body and start a new one. def flush_output_buffer #:nodoc: if output_buffer && !output_buffer.empty? - response.body_parts << output_buffer + response.stream.write output_buffer self.output_buffer = output_buffer.respond_to?(:clone_empty) ? output_buffer.clone_empty : output_buffer[0, 0] nil end diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb index 878a8734a4..d8b92c5cab 100644 --- a/actionpack/lib/action_view/helpers/debug_helper.rb +++ b/actionpack/lib/action_view/helpers/debug_helper.rb @@ -4,6 +4,9 @@ module ActionView # Provides a set of methods for making it easier to debug Rails objects. module Helpers module DebugHelper + + include TagHelper + # Returns a YAML representation of +object+ wrapped with <pre> and </pre>. # If the object cannot be converted to YAML using +to_yaml+, +inspect+ will be called instead. # Useful for inspecting an object at the time of rendering. @@ -26,10 +29,11 @@ module ActionView def debug(object) begin Marshal::dump(object) - "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>".html_safe + object = ERB::Util.html_escape(object.to_yaml).gsub(" ", " ").html_safe + content_tag(:pre, object, :class => "debug_dump") rescue Exception # errors from Marshal or YAML # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback - "<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe + content_tag(:code, object.to_yaml, :class => "debug_dump") end end end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b34f6c8650..13a5671a17 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -4,13 +4,10 @@ require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' require 'action_view/helpers/active_model_helper' require 'action_view/helpers/tags' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/hash/slice' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/array/extract_options' -require 'active_support/deprecation' require 'active_support/core_ext/string/inflections' require 'action_controller/model_naming' diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index c88af0355f..f3237f82d5 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -1,7 +1,6 @@ require 'cgi' require 'erb' require 'action_view/helpers/form_helper' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' module ActionView diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index d7d9c45120..46ee196a2a 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -1,6 +1,5 @@ require 'cgi' require 'action_view/helpers/tag_helper' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/module/attribute_accessors' diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 9572f1c192..3327c69d61 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' require 'set' diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 0cc0d069ea..0f599d5f41 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/filters' require 'active_support/core_ext/array/extract_options' diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 47dd932c71..f0ea92b018 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/module/remove_method' module ActionView diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index a08a566b35..edefeac184 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' module ActionView # = Action View Partials @@ -337,17 +336,16 @@ module ActionView end end + if as = options[:as] + raise_invalid_identifier(as) unless as.to_s =~ /\A[a-z_]\w*\z/ + as = as.to_sym + end + if @path - @variable, @variable_counter = retrieve_variable(@path) + @variable, @variable_counter = retrieve_variable(@path, as) @template_keys = retrieve_template_keys else - paths.map! { |path| retrieve_variable(path).unshift(path) } - end - - if String === partial && @variable.to_s !~ /^[a-z_][a-zA-Z_0-9]*$/ - raise ArgumentError.new("The partial name (#{partial}) is not a valid Ruby identifier; " + - "make sure your partial name starts with a lowercase letter or underscore, " + - "and is followed by any combination of letters, numbers and underscores.") + paths.map! { |path| retrieve_variable(path, as).unshift(path) } end self @@ -456,10 +454,22 @@ module ActionView keys end - def retrieve_variable(path) - variable = @options.fetch(:as) { path[%r'_?(\w+)(\.\w+)*$', 1] }.try(:to_sym) + def retrieve_variable(path, as) + variable = as || begin + base = path[-1] == "/" ? "" : File.basename(path) + raise_invalid_identifier(path) unless base =~ /\A_?([a-z]\w*)(\.\w+)*\z/ + $1.to_sym + end variable_counter = :"#{variable}_counter" if @collection [variable, variable_counter] end + + IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores." + + def raise_invalid_identifier(path) + raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path)) + end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index cd79468502..a04eac1d3f 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/core_ext/kernel/singleton_class' require 'thread' diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 19b9112afd..aa8eac7846 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -1,5 +1,4 @@ require 'action_dispatch/http/mime_type' -require 'active_support/core_ext/class/attribute' require 'erubis' module ActionView diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 53bde48e4d..55f79bf761 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/remove_method' require 'action_controller' require 'action_controller/test_case' diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 8c7f6474e5..56cebee678 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -356,6 +356,6 @@ end module RoutingTestHelpers def url_for(set, options, recall = nil) - set.send(:url_for, options.merge(:only_path => true, :_path_segments => recall)) + set.send(:url_for, options.merge(:only_path => true, :_recall => recall)) end end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 828ea5b0fb..b11ad633bd 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -139,11 +139,12 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with request-uri that doesn't match credentials digest-uri" do @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') - @request.env['ORIGINAL_FULLPATH'] = "/http_digest_authentication_test/dummy_digest/altered/uri" + @request.env['PATH_INFO'] = "/proxied/uri" get :display - assert_response :unauthorized - assert_equal "Authentication Failed", @response.body + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body end test "authentication request with absolute request uri (as in webrick)" do diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index c73b36f05e..94a8d2f180 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -200,7 +200,7 @@ class SetsNonExistentLayoutFile < LayoutTest layout "nofile" end -class LayoutExceptionRaised < ActionController::TestCase +class LayoutExceptionRaisedTest < ActionController::TestCase def test_exception_raised_when_layout_file_not_found @controller = SetsNonExistentLayoutFile.new assert_raise(ActionView::MissingTemplate) { get :hello } diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb new file mode 100644 index 0000000000..20e433d1ec --- /dev/null +++ b/actionpack/test/controller/live_stream_test.rb @@ -0,0 +1,121 @@ +require 'abstract_unit' +require 'active_support/concurrency/latch' + +module ActionController + class LiveStreamTest < ActionController::TestCase + class TestController < ActionController::Base + include ActionController::Live + + attr_accessor :latch, :tc + + def self.controller_path + 'test' + end + + def render_text + render :text => 'zomg' + end + + def default_header + response.stream.write "<html><body>hi</body></html>" + response.stream.close + end + + def basic_stream + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + end + response.stream.close + end + + def blocking_stream + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + latch.await + end + response.stream.close + end + + def thread_locals + tc.assert_equal 'aaron', Thread.current[:setting] + tc.refute_equal Thread.current.object_id, Thread.current[:originating_thread] + + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + end + response.stream.close + end + end + + tests TestController + + class TestResponse < Live::Response + def recycle! + initialize + end + end + + def build_response + TestResponse.new + end + + def test_set_response! + @controller.set_response!(@request) + assert_kind_of(Live::Response, @controller.response) + assert_equal @request, @controller.response.request + end + + def test_write_to_stream + @controller = TestController.new + get :basic_stream + assert_equal "helloworld", @response.body + assert_equal 'text/event-stream', @response.headers['Content-Type'] + end + + def test_async_stream + @controller.latch = ActiveSupport::Concurrency::Latch.new + parts = ['hello', 'world'] + + @controller.request = @request + @controller.response = @response + + t = Thread.new(@response) { |resp| + resp.stream.each do |part| + assert_equal parts.shift, part + ol = @controller.latch + @controller.latch = ActiveSupport::Concurrency::Latch.new + ol.release + end + } + + @controller.process :blocking_stream + + assert t.join + end + + def test_thread_locals_get_copied + @controller.tc = self + Thread.current[:originating_thread] = Thread.current.object_id + Thread.current[:setting] = 'aaron' + + get :thread_locals + end + + def test_live_stream_default_header + @controller.request = @request + @controller.response = @response + @controller.process :default_header + _, headers, _ = @response.prepare! + assert headers['Content-Type'] + end + + def test_render_text + get :render_text + assert_equal 'zomg', response.body + assert response.stream.closed?, 'stream should be closed' + end + end +end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index c8e036b116..b21d35c846 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' require 'controller/fake_models' require 'active_support/core_ext/hash/conversions' -require 'active_support/core_ext/object/inclusion' class StarStarMimeController < ActionController::Base layout nil @@ -152,10 +151,11 @@ class RespondToController < ActionController::Base protected def set_layout - if action_name.in?(["all_types_with_layout", "iphone_with_html_response_type"]) - "respond_to/layouts/standard" - elsif action_name == "iphone_with_html_response_type_without_layout" - "respond_to/layouts/missing" + case action_name + when "all_types_with_layout", "iphone_with_html_response_type" + "respond_to/layouts/standard" + when "iphone_with_html_response_type_without_layout" + "respond_to/layouts/missing" end end end @@ -851,7 +851,7 @@ class RespondWithControllerTest < ActionController::TestCase put :using_resource assert_equal "application/xml", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_put_with_json_yields_no_content_on_success @@ -860,7 +860,7 @@ class RespondWithControllerTest < ActionController::TestCase put :using_resource assert_equal "application/json", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure @@ -902,7 +902,7 @@ class RespondWithControllerTest < ActionController::TestCase delete :using_resource assert_equal "application/xml", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_delete_with_json_yields_no_content_on_success @@ -912,7 +912,7 @@ class RespondWithControllerTest < ActionController::TestCase delete :using_resource assert_equal "application/json", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_delete_with_html_redirects_on_failure diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 5bcd79ebec..7396c850ad 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -110,6 +110,36 @@ module BareMetalTest assert_nil headers['Content-Type'] assert_nil headers['Content-Length'] end + + test "head :no_content (204) does not return any content" do + content = HeadController.action(:no_content).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :reset_content (205) does not return any content" do + content = HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :not_modified (304) does not return any content" do + content = HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :continue (100) does not return any content" do + content = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :switching_protocols (101) does not return any content" do + content = HeadController.action(:switching_protocols).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :processing (102) does not return any content" do + content = HeadController.action(:processing).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end end class BareControllerTest < ActionController::TestCase diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 156d87c321..d0be4f66d1 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -126,7 +126,7 @@ module RenderTemplate test "rendering a template with error properly excerts the code" do get :with_error assert_status 500 - assert_match "undefined local variable or method `idontexist'", response.body + assert_match "undefined local variable or method `idontexist", response.body end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 6bebe7e1ed..3f047fc9b5 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -186,7 +186,7 @@ class TestController < ActionController::Base # :ported: def render_text_hello_world_with_layout - @variable_for_layout = ", I'm here!" + @variable_for_layout = ", I am here!" render :text => "hello world", :layout => true end @@ -844,7 +844,7 @@ class RenderTest < ActionController::TestCase # :ported: def test_do_with_render_text_and_layout get :render_text_hello_world_with_layout - assert_equal "<html>hello world, I'm here!</html>", @response.body + assert_equal "<html>hello world, I am here!</html>", @response.body end # :ported: diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index de1bff17eb..236e16c68e 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/with_options' -require 'active_support/core_ext/object/inclusion' class ResourcesController < ActionController::Base def index() render :nothing => true end @@ -1308,7 +1307,7 @@ class ResourcesTest < ActionController::TestCase def assert_resource_methods(expected, resource, action_method, method) assert_equal expected.length, resource.send("#{action_method}_methods")[method].size, "#{resource.send("#{action_method}_methods")[method].inspect}" expected.each do |action| - assert action.in?(resource.send("#{action_method}_methods")[method]) + assert resource.send("#{action_method}_methods")[method].include?(action) "#{method} not in #{action_method} methods: #{resource.send("#{action_method}_methods")[method].inspect}" end end @@ -1345,9 +1344,9 @@ class ResourcesTest < ActionController::TestCase options = options.merge(:action => action.to_s) path_options = { :path => path, :method => method } - if action.in?(Array(allowed)) + if Array(allowed).include?(action) assert_recognizes options, path_options - elsif action.in?(Array(not_allowed)) + elsif Array(not_allowed).include?(action) assert_not_recognizes options, path_options end end diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 6fc3556e31..97ede35317 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -51,14 +51,14 @@ class SendFileTest < ActionController::TestCase response = nil assert_nothing_raised { response = process('file') } assert_not_nil response - assert_respond_to response.body_parts, :each - assert_respond_to response.body_parts, :to_path + assert_respond_to response.stream, :each + assert_respond_to response.stream, :to_path require 'stringio' output = StringIO.new output.binmode output.string.force_encoding(file_data.encoding) - assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } } + response.body_parts.each { |part| output << part.to_s } assert_equal file_data, output.string end diff --git a/actionpack/test/controller/streaming_test.rb b/actionpack/test/controller/streaming_test.rb new file mode 100644 index 0000000000..6ee6444065 --- /dev/null +++ b/actionpack/test/controller/streaming_test.rb @@ -0,0 +1,26 @@ +require 'abstract_unit' + +module ActionController + class StreamingResponseTest < ActionController::TestCase + class TestController < ActionController::Base + def self.controller_path + 'test' + end + + def basic_stream + %w{ hello world }.each do |word| + response.stream.write word + response.stream.write "\n" + end + response.stream.close + end + end + + tests TestController + + def test_write_to_stream + get :basic_stream + assert_equal "hello\nworld\n", @response.body + end + end +end diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index b2cb5f80d5..d3fc7128e9 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module AbstractController module Testing - class UrlForTests < ActionController::TestCase + class UrlForTest < ActionController::TestCase class W include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { get ':controller(/:action(/:id(.:format)))' } }.url_helpers end diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index cc3706aeee..d9a1ae7d4f 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_controllers' -class UrlRewriterTests < ActionController::TestCase +class UrlRewriterTests < ActiveSupport::TestCase class Rewriter def initialize(request) @options = { diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb new file mode 100644 index 0000000000..87a6b1383d --- /dev/null +++ b/actionpack/test/dispatch/live_response_test.rb @@ -0,0 +1,66 @@ +require 'abstract_unit' +require 'active_support/concurrency/latch' + +module ActionController + module Live + class ResponseTest < ActiveSupport::TestCase + def setup + @response = Live::Response.new + end + + def test_parallel + latch = ActiveSupport::Concurrency::Latch.new + + t = Thread.new { + @response.stream.write 'foo' + latch.await + @response.stream.close + } + + @response.each do |part| + assert_equal 'foo', part + latch.release + end + assert t.join + end + + def test_setting_body_populates_buffer + @response.body = 'omg' + @response.close + assert_equal ['omg'], @response.body_parts + end + + def test_cache_control_is_set + @response.stream.write 'omg' + assert_equal 'no-cache', @response.headers['Cache-Control'] + end + + def test_content_length_is_removed + @response.headers['Content-Length'] = "1234" + @response.stream.write 'omg' + assert_nil @response.headers['Content-Length'] + end + + def test_headers_cannot_be_written_after_write + @response.stream.write 'omg' + + assert @response.headers.frozen? + e = assert_raises(ActionDispatch::IllegalStateError) do + @response.headers['Content-Length'] = "zomg" + end + + assert_equal 'header already sent', e.message + end + + def test_headers_cannot_be_written_after_close + @response.stream.close + + assert @response.headers.frozen? + e = assert_raises(ActionDispatch::IllegalStateError) do + @response.headers['Content-Length'] = "zomg" + end + assert_equal 'header already sent', e.message + end + end + end +end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 82d1200f8e..e2903d4b36 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -5,6 +5,35 @@ class ResponseTest < ActiveSupport::TestCase @response = ActionDispatch::Response.new end + def test_can_wait_until_commit + t = Thread.new { + @response.await_commit + } + @response.commit! + assert @response.committed? + assert t.join(0.5) + end + + def test_stream_close + @response.stream.close + assert @response.stream.closed? + end + + def test_stream_write + @response.stream.write "foo" + @response.stream.close + assert_equal "foo", @response.body + end + + def test_write_after_close + @response.stream.close + + e = assert_raises(IOError) do + @response.stream.write "omg" + end + assert_equal "closed stream", e.message + end + def test_response_body_encoding body = ["hello".encode('utf-8')] response = ActionDispatch::Response.new 200, {}, body diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 205238990e..b029131ad8 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -2,7 +2,6 @@ require 'erb' require 'abstract_unit' require 'controller/fake_controllers' -require 'active_support/core_ext/object/inclusion' class TestRoutingMapper < ActionDispatch::IntegrationTest SprocketsApp = lambda { |env| @@ -512,7 +511,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :todos, :id => /\d+/ end - scope '/countries/:country', :constraints => lambda { |params, req| params[:country].in?(["all", "France"]) } do + scope '/countries/:country', :constraints => lambda { |params, req| %w(all France).include?(params[:country]) } do get '/', :to => 'countries#index' get '/cities', :to => 'countries#cities' end diff --git a/actionpack/test/fixtures/reply.rb b/actionpack/test/fixtures/reply.rb index 16b53be18a..047522c55b 100644 --- a/actionpack/test/fixtures/reply.rb +++ b/actionpack/test/fixtures/reply.rb @@ -1,5 +1,5 @@ class Reply < ActiveRecord::Base - scope :base, -> { scoped } + scope :base, -> { all } belongs_to :topic, -> { includes(:replies) } belongs_to :developer diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index 17469f8c3e..234ac3252d 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -56,7 +56,7 @@ class CaptureHelperTest < ActionView::TestCase def test_content_for_with_multiple_calls_and_flush assert ! content_for?(:title) content_for :title, 'foo' - content_for :title, 'bar', true + content_for :title, 'bar', flush: true assert_equal 'bar', content_for(:title) end @@ -75,7 +75,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, true do + content_for :title, flush: true do 'bar' end assert_equal 'bar', content_for(:title) @@ -86,7 +86,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, nil, true do + content_for :title, nil, flush: true do 'bar' end assert_equal 'bar', content_for(:title) @@ -97,7 +97,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, false do + content_for :title, flush: false do 'bar' end assert_equal 'foobar', content_for(:title) @@ -117,11 +117,11 @@ class CaptureHelperTest < ActionView::TestCase def test_content_for_with_whitespace_block_and_flush assert ! content_for?(:title) content_for :title, 'foo' - content_for :title, true do + content_for :title, flush: true do output_buffer << " \n " nil end - content_for :title, 'bar', true + content_for :title, 'bar', flush: true assert_equal 'bar', content_for(:title) end @@ -131,9 +131,9 @@ class CaptureHelperTest < ActionView::TestCase assert_equal nil, content_for(:title) { output_buffer << 'bar'; nil } assert_equal nil, content_for(:title) { output_buffer << " \n "; nil } assert_equal 'foobar', content_for(:title) - assert_equal nil, content_for(:title, 'foo', true) - assert_equal nil, content_for(:title, true) { output_buffer << 'bar'; nil } - assert_equal nil, content_for(:title, true) { output_buffer << " \n "; nil } + assert_equal nil, content_for(:title, 'foo', flush: true) + assert_equal nil, content_for(:title, flush: true) { output_buffer << 'bar'; nil } + assert_equal nil, content_for(:title, flush: true) { output_buffer << " \n "; nil } assert_equal 'bar', content_for(:title) end diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index ca2710e9b3..f1cb920963 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/object/inclusion' class ErbUtilTest < ActiveSupport::TestCase include ERB::Util @@ -8,11 +7,11 @@ class ErbUtilTest < ActiveSupport::TestCase define_method "test_html_escape_#{expected.gsub(/\W/, '')}" do assert_equal expected, html_escape(given) end + end - unless given == '"' - define_method "test_json_escape_#{expected.gsub(/\W/, '')}" do - assert_equal ERB::Util::JSON_ESCAPE[given], json_escape(given) - end + ERB::Util::JSON_ESCAPE.each do |given, expected| + define_method "test_json_escape_#{expected.gsub(/\W/, '')}" do + assert_equal ERB::Util::JSON_ESCAPE[given], json_escape(given) end end @@ -40,13 +39,13 @@ class ErbUtilTest < ActiveSupport::TestCase def test_rest_in_ascii (0..127).to_a.map {|int| int.chr }.each do |chr| - next if chr.in?('&"<>') + next if %('"&<>).include?(chr) assert_equal chr, html_escape(chr) end end def test_html_escape_once - assert_equal '1 < 2 & 3', html_escape_once('1 < 2 & 3') + assert_equal '1 <>&"' 2 & 3', html_escape_once('1 <>&"\' 2 & 3') end def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 7da293ce23..a20a68c1b2 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'controller/fake_models' -require 'active_support/core_ext/object/inclusion' class FormHelperTest < ActionView::TestCase include RenderERBUtils @@ -2660,7 +2659,7 @@ class FormHelperTest < ActionView::TestCase def hidden_fields(method = nil) txt = %{<div style="margin:0;padding:0;display:inline">} txt << %{<input name="utf8" type="hidden" value="✓" />} - if method && !method.to_s.in?(['get', 'post']) + if method && !%w(get post).include?(method.to_s) txt << %{<input name="_method" type="hidden" value="#{method}" />} end txt << %{</div>} diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index bfc73172eb..682ffdcc18 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'tzinfo' -require 'active_support/core_ext/object/inclusion' class Map < Hash def category @@ -83,7 +82,7 @@ class FormOptionsHelperTest < ActionView::TestCase def test_collection_options_with_proc_for_disabled assert_dom_equal( "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe went home</option>", - options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => lambda{|p| p.author_name.in?(["Babe", "Cabe"]) }) + options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => lambda {|p| %w(Babe Cabe).include?(p.author_name)}) ) end @@ -1125,7 +1124,7 @@ class FormOptionsHelperTest < ActionView::TestCase def test_options_for_select_with_element_attributes assert_dom_equal( - "<option value=\"<Denmark>\" class=\"bold\"><Denmark></option>\n<option value=\"USA\" onclick=\"alert('Hello World');\">USA</option>\n<option value=\"Sweden\">Sweden</option>\n<option value=\"Germany\">Germany</option>", + "<option value=\"<Denmark>\" class=\"bold\"><Denmark></option>\n<option value=\"USA\" onclick=\"" + ERB::Util.html_escape("alert('Hello World');") + "\">USA</option>\n<option value=\"Sweden\">Sweden</option>\n<option value=\"Germany\">Germany</option>", options_for_select([ [ "<Denmark>", { :class => 'bold' } ], [ "USA", { :onclick => "alert('Hello World');" } ], [ "Sweden" ], "Germany" ]) ) end diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 9afa4a2927..9a85b1b553 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/object/inclusion' class FormTagHelperTest < ActionView::TestCase include RenderERBUtils @@ -16,7 +15,7 @@ class FormTagHelperTest < ActionView::TestCase txt = %{<div style="margin:0;padding:0;display:inline">} txt << %{<input name="utf8" type="hidden" value="✓" />} - if method && !method.to_s.in?(['get','post']) + if method && !%w(get post).include?(method.to_s) txt << %{<input name="_method" type="hidden" value="#{method}" />} end txt << %{</div>} @@ -214,6 +213,12 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end + def test_select_tag_escapes_prompt + actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :prompt => "<script>alert(1337)</script>" + expected = %(<select id="places" name="places"><option value=""><script>alert(1337)</script></option><option>Home</option><option>Work</option><option>Pub</option></select>) + assert_dom_equal expected, actual + end + def test_select_tag_with_prompt_and_include_blank actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :prompt => "string", :include_blank => true expected = %(<select name="places" id="places"><option value="">string</option><option value=""></option><option>Home</option><option>Work</option><option>Pub</option></select>) @@ -374,7 +379,7 @@ class FormTagHelperTest < ActionView::TestCase def test_submit_tag assert_dom_equal( - %(<input name='commit' data-disable-with="Saving..." onclick="alert('hello!')" type="submit" value="Save" />), + %(<input name='commit' data-disable-with="Saving..." onclick=") + ERB::Util.html_escape("alert('hello!')") + %(" type="submit" value="Save" />), submit_tag("Save", :onclick => "alert('hello!')", :data => { :disable_with => "Saving..." }) ) end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 3ce1d20bd9..164b8b9fa1 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -187,6 +187,13 @@ module RenderTestCases assert_equal "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.", e.message end + def test_render_partial_with_hyphen + e = assert_raises(ArgumentError) { @view.render(:partial => "test/a-in") } + assert_equal "The partial name (test/a-in) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message + end + def test_render_partial_with_errors e = assert_raises(ActionView::Template::Error) { @view.render(:partial => "test/raise") } assert_match %r!method.*doesnt_exist!, e.message diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 322bea3fb0..061f5bb53f 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -84,7 +84,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_locals @template = new_template("<%= my_local %>") @template.locals = [:my_local] - assert_equal "I'm a local", render(:my_local => "I'm a local") + assert_equal "I am a local", render(:my_local => "I am a local") end def test_restores_buffer diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index a3ab091c6c..75ec1d8f16 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -107,8 +107,8 @@ class TextHelperTest < ActionView::TestCase end def test_truncate_with_link_options - assert_equal "Here's a long test and I...<a href=\"#\">Continue</a>", - truncate("Here's a long test and I need a continue to read link", :length => 27) { link_to 'Continue', '#' } + assert_equal "Here is a long test and ...<a href=\"#\">Continue</a>", + truncate("Here is a long test and I need a continue to read link", :length => 27) { link_to 'Continue', '#' } end def test_truncate_should_be_html_safe @@ -149,8 +149,8 @@ class TextHelperTest < ActionView::TestCase end def test_truncate_with_block_should_escape_the_block - assert_equal "Here's a long test and I...<script>alert('foo');</script>", - truncate("Here's a long test and I need a continue to read link", :length => 27) { "<script>alert('foo');</script>" } + assert_equal "Here is a long test and ...<script>" + ERB::Util.html_escape("alert('foo');") + "</script>", + truncate("Here is a long test and I need a continue to read link", :length => 27) { "<script>alert('foo');</script>" } end def test_highlight_should_be_html_safe diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index cb6f378ecb..2c67b2210b 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -244,7 +244,7 @@ class UrlHelperTest < ActiveSupport::TestCase def test_link_tag_with_custom_onclick link = link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')") - expected = %{<a href="http://www.example.com" onclick="alert('yay!')">Hello</a>} + expected = %{<a href="http://www.example.com" onclick="} + ERB::Util.html_escape("alert('yay!')") + %{">Hello</a>} assert_dom_equal expected, link end @@ -254,12 +254,12 @@ class UrlHelperTest < ActiveSupport::TestCase link_to("Hello", "http://www.example.com", :data => { :confirm => "Are you sure?" }) ) assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure, can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :data => { :confirm => "You can't possibly be sure, can you?" }) + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure, can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :data => { :confirm => "You cant possibly be sure, can you?" }) ) assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure,\n can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :data => { :confirm => "You can't possibly be sure,\n can you?" }) + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure,\n can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :data => { :confirm => "You cant possibly be sure,\n can you?" }) ) end @@ -272,14 +272,14 @@ class UrlHelperTest < ActiveSupport::TestCase end assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure, can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure, can you?") + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure, can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You cant possibly be sure, can you?") ) end assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure,\n can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure,\n can you?") + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure,\n can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You cant possibly be sure,\n can you?") ) end end |