From 72ca7c591c9eace150c0ebab1633d691a1ef12cf Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Tue, 12 May 2009 10:53:00 -0700 Subject: [PATCH 01/45] Fixed new callbacks to not call the action when a callback sets the response body --- .../action_controller/abstract/callbacks.rb | 2 +- .../abstract_controller/callbacks_test.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb index 6e15b3e81b..3aff83a209 100644 --- a/actionpack/lib/action_controller/abstract/callbacks.rb +++ b/actionpack/lib/action_controller/abstract/callbacks.rb @@ -5,7 +5,7 @@ module AbstractController depends_on ActiveSupport::NewCallbacks included do - define_callbacks :process_action + define_callbacks :process_action, "response_body" end def process_action diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract_controller/callbacks_test.rb index 410b1e57a6..1de60868c3 100644 --- a/actionpack/test/abstract_controller/callbacks_test.rb +++ b/actionpack/test/abstract_controller/callbacks_test.rb @@ -193,5 +193,24 @@ module AbstractController end end + class SetsResponseBody < ControllerWithCallbacks + before_filter :set_body + + def index + self.response_body = "Fail" + end + + def set_body + self.response_body = "Success" + end + end + + class TestHalting < ActiveSupport::TestCase + test "when a callback sets the response body, the action should not be invoked" do + result = SetsResponseBody.process(:index) + assert_equal "Success", result.response_body + end + end + end end \ No newline at end of file From 216309c16519d94a9e0aebf758029a78696ab8d6 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Tue, 12 May 2009 16:21:34 -0700 Subject: [PATCH 02/45] Implemented redirects and partial rendering in new base. --- .../lib/action_controller/abstract/base.rb | 10 +++ .../lib/action_controller/abstract/layouts.rb | 2 +- .../action_controller/abstract/renderer.rb | 29 +++---- .../lib/action_controller/base/redirect.rb | 4 +- actionpack/lib/action_controller/new_base.rb | 1 + .../lib/action_controller/new_base/base.rb | 79 +++++++++++++++++-- .../new_base/compatibility.rb | 42 +++++++--- .../lib/action_controller/new_base/http.rb | 6 ++ .../lib/action_controller/new_base/layouts.rb | 2 +- .../action_controller/new_base/redirector.rb | 19 +++++ .../action_controller/new_base/renderer.rb | 27 +++++-- .../lib/action_controller/testing/process.rb | 10 ++- .../lib/action_controller/testing/process2.rb | 1 + .../lib/action_dispatch/http/response.rb | 6 -- actionpack/lib/action_view/render/partials.rb | 32 +++++--- .../lib/action_view/render/rendering.rb | 5 ++ actionpack/test/abstract_unit.rb | 4 + actionpack/test/abstract_unit2.rb | 69 ++++++++-------- actionpack/test/controller/render_test.rb | 4 +- actionpack/test/new_base/redirect_test.rb | 1 + 20 files changed, 251 insertions(+), 102 deletions(-) create mode 100644 actionpack/lib/action_controller/new_base/redirector.rb create mode 100644 actionpack/test/new_base/redirect_test.rb diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index ab9aed0b26..c9e1081b23 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -1,4 +1,14 @@ module AbstractController + class Error < StandardError; end + + class DoubleRenderError < Error + DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"." + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + class Base attr_internal :response_body diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb index e48b8b2b4b..35d5e85ed9 100644 --- a/actionpack/lib/action_controller/abstract/layouts.rb +++ b/actionpack/lib/action_controller/abstract/layouts.rb @@ -51,7 +51,7 @@ module AbstractController end def _render_template(template, options) - _action_view._render_template_with_layout(template, options[:_layout], options) + _action_view._render_template_from_controller(template, options[:_layout], options, options[:_partial]) end private diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb index b58688c9da..f2044a35ec 100644 --- a/actionpack/lib/action_controller/abstract/renderer.rb +++ b/actionpack/lib/action_controller/abstract/renderer.rb @@ -1,15 +1,6 @@ require "action_controller/abstract/logger" module AbstractController - class AbstractControllerError < StandardError; end - class DoubleRenderError < AbstractControllerError - DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"." - - def initialize(message = nil) - super(message || DEFAULT_MESSAGE) - end - end - module Renderer extend ActiveSupport::DependencyModule @@ -27,12 +18,12 @@ module AbstractController @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self) end - def render(options = {}) + def render(*args) if response_body raise AbstractController::DoubleRenderError, "OMG" end - self.response_body = render_to_body(options) + self.response_body = render_to_body(*args) end # Raw rendering of a template to a Rack-compatible body. @@ -43,10 +34,16 @@ module AbstractController # :api: plugin def render_to_body(options = {}) name = options[:_template_name] || action_name - - options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix]) - - _render_template(options[:_template], options) + + # TODO: Refactor so we can just use the normal template logic for this + if options[:_partial_object] + _action_view._render_partial_from_controller(options) + else + options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, + options[:_prefix], options[:_partial]) + + _render_template(options[:_template], options) + end end # Raw rendering of a template to a string. @@ -60,7 +57,7 @@ module AbstractController end def _render_template(template, options) - _action_view._render_template_with_layout(template) + _action_view._render_template_from_controller(template, nil, options, options[:_partial]) end def view_paths() _view_paths end diff --git a/actionpack/lib/action_controller/base/redirect.rb b/actionpack/lib/action_controller/base/redirect.rb index 4849caac0a..7e10f614e2 100644 --- a/actionpack/lib/action_controller/base/redirect.rb +++ b/actionpack/lib/action_controller/base/redirect.rb @@ -70,7 +70,9 @@ module ActionController def redirect_to_full_url(url, status) raise DoubleRenderError if performed? logger.info("Redirected to #{url}") if logger && logger.info? - response.redirect(url, interpret_status(status)) + response.status = interpret_status(status) + response.location = url.gsub(/[\r\n]/, '') + response.body = "You are being redirected." @performed_redirect = true end diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb index 8a7de1476c..1f215bb6f1 100644 --- a/actionpack/lib/action_controller/new_base.rb +++ b/actionpack/lib/action_controller/new_base.rb @@ -5,6 +5,7 @@ module ActionController autoload :Http, "action_controller/new_base/http" autoload :Layouts, "action_controller/new_base/layouts" autoload :Rails2Compatibility, "action_controller/new_base/compatibility" + autoload :Redirector, "action_controller/new_base/redirector" autoload :Renderer, "action_controller/new_base/renderer" autoload :Testing, "action_controller/new_base/testing" autoload :UrlFor, "action_controller/new_base/url_for" diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 4892886341..1adcc9c71f 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -8,6 +8,7 @@ module ActionController include ActionController::HideActions include ActionController::UrlFor + include ActionController::Redirector include ActionController::Renderer include ActionController::Layouts include ActionController::ConditionalGet @@ -34,19 +35,83 @@ module ActionController end end - def render(action = action_name, options = {}) + def render_to_body(action = nil, options = {}) if action.is_a?(Hash) options, action = action, nil - else - options.merge! :action => action + elsif action.is_a?(String) || action.is_a?(Symbol) + key = case action = action.to_s + when %r{^/} then :file + when %r{/} then :template + else :action + end + options.merge! key => action + elsif action + options.merge! :partial => action end - super(options) + if options.key?(:action) && options[:action].to_s.index("/") + options[:template] = options.delete(:action) + end + + # options = {:template => options.to_s} if options.is_a?(String) || options.is_a?(Symbol) + super(options) || " " end - def render_to_body(options = {}) - options = {:template => options} if options.is_a?(String) - super + # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: + # + # * Hash - The URL will be generated by calling url_for with the +options+. + # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. + # * String starting with protocol:// (like http://) - Is passed straight through as the target for redirection. + # * String not containing a protocol - The current protocol and host is prepended to the string. + # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. + # Short-hand for redirect_to(request.env["HTTP_REFERER"]) + # + # Examples: + # redirect_to :action => "show", :id => 5 + # redirect_to post + # redirect_to "http://www.rubyonrails.org" + # redirect_to "/images/screenshot.jpg" + # redirect_to articles_url + # redirect_to :back + # + # The redirection happens as a "302 Moved" header unless otherwise specified. + # + # Examples: + # redirect_to post_url(@post), :status=>:found + # redirect_to :action=>'atom', :status=>:moved_permanently + # redirect_to post_url(@post), :status=>301 + # redirect_to :action=>'atom', :status=>302 + # + # When using redirect_to :back, if there is no referrer, + # RedirectBackError will be raised. You may specify some fallback + # behavior for this case by rescuing RedirectBackError. + def redirect_to(options = {}, response_status = {}) #:doc: + raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? + + status = if options.is_a?(Hash) && options.key?(:status) + interpret_status(options.delete(:status)) + elsif response_status.key?(:status) + interpret_status(response_status[:status]) + else + 302 + end + + url = case options + # The scheme name consist of a letter followed by any combination of + # letters, digits, and the plus ("+"), period ("."), or hyphen ("-") + # characters; and is terminated by a colon (":"). + when %r{^\w[\w\d+.-]*:.*} + options + when String + request.protocol + request.host_with_port + options + when :back + raise RedirectBackError unless refer = request.headers["Referer"] + refer + else + url_for(options) + end + + super(url, status) end def process_action diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb index 4655a94923..d17f498b60 100644 --- a/actionpack/lib/action_controller/new_base/compatibility.rb +++ b/actionpack/lib/action_controller/new_base/compatibility.rb @@ -8,27 +8,40 @@ module ActionController ::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError cattr_accessor :session_options - self.send(:class_variable_set, "@@session_options", {}) + self.session_options = {} cattr_accessor :allow_concurrency - self.send(:class_variable_set, "@@allow_concurrency", false) + self.allow_concurrency = false cattr_accessor :param_parsers - self.send(:class_variable_set, "@@param_parsers", { Mime::MULTIPART_FORM => :multipart_form, - Mime::URL_ENCODED_FORM => :url_encoded_form, - Mime::XML => :xml_simple, - Mime::JSON => :json }) + self.param_parsers = { Mime::MULTIPART_FORM => :multipart_form, + Mime::URL_ENCODED_FORM => :url_encoded_form, + Mime::XML => :xml_simple, + Mime::JSON => :json } cattr_accessor :relative_url_root - self.send(:class_variable_set, "@@relative_url_root", ENV['RAILS_RELATIVE_URL_ROOT']) + self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT'] cattr_accessor :default_charset - self.send(:class_variable_set, "@@default_charset", "utf-8") + self.default_charset = "utf-8" - cattr_reader :protected_instance_variables - self.send(:class_variable_set, "@@protected_instance_variables", %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller + # cattr_reader :protected_instance_variables + cattr_accessor :protected_instance_variables + self.protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller @action_name @before_filter_chain_aborted @action_cache_path @_headers @_params - @_flash @_response)) + @_flash @_response) + + # Indicates whether or not optimise the generated named + # route helper methods + cattr_accessor :optimise_named_routes + self.optimise_named_routes = true + + cattr_accessor :resources_path_names + self.resources_path_names = { :new => 'new', :edit => 'edit' } + + # Controls the resource action separator + cattr_accessor :resource_action_separator + self.resource_action_separator = "/" end module ClassMethods @@ -38,7 +51,12 @@ module ActionController raise env["action_dispatch.rescue.exception"] end end - + + def initialize(*) + super + @template = _action_view + end + def render_to_body(options) if options.is_a?(Hash) && options.key?(:template) options[:template].sub!(/^\//, '') diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb index f269fe70db..fb6041a04e 100644 --- a/actionpack/lib/action_controller/new_base/http.rb +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -38,6 +38,12 @@ module ActionController controller.call(env).to_rack end + delegate :headers, :to => "@_response" + + def params + @_params ||= @_request.parameters + end + # :api: private def call(name, env) @_request = ActionDispatch::Request.new(env) diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb index e851eb5f9a..bf5b14c4e1 100644 --- a/actionpack/lib/action_controller/new_base/layouts.rb +++ b/actionpack/lib/action_controller/new_base/layouts.rb @@ -15,7 +15,7 @@ module ActionController # render :text => ..., :layout => ... # or # render :anything_else - if (!options.key?(:text) && !options.key?(:inline)) || options.key?(:layout) + if (!options.key?(:text) && !options.key?(:inline) && !options.key?(:partial)) || options.key?(:layout) options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout end diff --git a/actionpack/lib/action_controller/new_base/redirector.rb b/actionpack/lib/action_controller/new_base/redirector.rb new file mode 100644 index 0000000000..ff7b74341c --- /dev/null +++ b/actionpack/lib/action_controller/new_base/redirector.rb @@ -0,0 +1,19 @@ +module ActionController + class RedirectBackError < AbstractController::Error #:nodoc: + DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + + module Redirector + def redirect_to(url, status) #:doc: + raise AbstractController::DoubleRenderError if response_body + logger.info("Redirected to #{url}") if logger && logger.info? + response.status = status + response.location = url.gsub(/[\r\n]/, '') + self.response_body = "You are being redirected." + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb index 41e3dfbe23..8a9f230603 100644 --- a/actionpack/lib/action_controller/new_base/renderer.rb +++ b/actionpack/lib/action_controller/new_base/renderer.rb @@ -9,13 +9,9 @@ module ActionController super end - def render(options = {}) + def render_to_body(options) _process_options(options) - super(options) - end - - def render_to_body(options) if options.key?(:text) options[:_template] = ActionView::TextTemplate.new(_text(options)) template = nil @@ -25,12 +21,18 @@ module ActionController options[:_template] = template elsif options.key?(:template) options[:_template_name] = options[:template] + elsif options.key?(:file) + options[:_template_name] = options[:file] + elsif options.key?(:partial) + _render_partial(options[:partial], options) else options[:_template_name] = (options[:action] || action_name).to_s options[:_prefix] = _prefix end ret = super(options) + + options[:_template] ||= _action_view._partial response.content_type ||= options[:_template].mime_type ret end @@ -49,6 +51,21 @@ module ActionController else text.to_s end end + + def _render_partial(partial, options) + case partial + when true + options[:_prefix] = _prefix + when String + options[:_prefix] = _prefix unless partial.index('/') + options[:_template_name] = partial + else + options[:_partial_object] = true + return + end + + options[:_partial] = options[:object] || true + end def _process_options(options) status, content_type = options.values_at(:status, :content_type) diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 21023ac101..936f97ecb5 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -161,11 +161,13 @@ module ActionController #:nodoc: alias xhr :xml_http_request def assigns(key = nil) - if key.nil? - @controller.template.assigns - else - @controller.template.assigns[key.to_s] + assigns = {} + @controller.instance_variable_names.each do |ivar| + next if ActionController::Base.protected_instance_variables.include?(ivar) + assigns[ivar[1..-1]] = @controller.instance_variable_get(ivar) end + + key.nil? ? assigns : assigns[key.to_s] end def session diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb index 18b7335450..e9a79369b9 100644 --- a/actionpack/lib/action_controller/testing/process2.rb +++ b/actionpack/lib/action_controller/testing/process2.rb @@ -50,6 +50,7 @@ module ActionController @request.session = ActionController::TestSession.new(session) unless session.nil? @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash build_request_uri(action, parameters) + @controller.request = @request @controller.params.merge!(parameters) # Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest @controller.process_with_test(@request, @response) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 133b4f7335..c3b5a68f40 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -156,12 +156,6 @@ module ActionDispatch # :nodoc: end end - def redirect(url, status) - self.status = status - self.location = url.gsub(/[\r\n]/, '') - self.body = "You are being redirected." - end - def sending_file? headers["Content-Transfer-Encoding"] == "binary" end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 43f8a1edf8..f2429e8cef 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -171,11 +171,21 @@ module ActionView # <% end %> module Partials extend ActiveSupport::Memoizable + extend ActiveSupport::DependencyModule + + included do + attr_accessor :_partial + end + + def _render_partial_from_controller(*args) + @assigns_added = false + _render_partial(*args) + end def _render_partial(options = {}) #:nodoc: options[:locals] ||= {} - case path = partial = options[:partial] + case path = partial = options[:partial] when *_array_like_objects return _render_partial_collection(partial, options) else @@ -222,16 +232,7 @@ module ActionView ensure @_proc_for_layout = nil end - - def _render_partial_with_layout(layout, options) - if layout - prefix = controller && !layout.include?("/") ? controller.controller_path : nil - layout = find_by_parts(layout, {:formats => formats}, prefix, true) - end - content = _render_partial(options) - return _render_content_with_layout(content, layout, options[:locals]) - end - + def _deprecated_ivar_assign(template) if respond_to?(:controller) ivar = :"@#{template.variable_name}" @@ -287,13 +288,17 @@ module ActionView locals = (options[:locals] ||= {}) object ||= locals[:object] || locals[template.variable_name] - _set_locals(object, locals, template, options) + _set_locals(object, locals, template, options) + + self._partial = template + _render_template(template, locals) end end def _set_locals(object, locals, template, options) object ||= _deprecated_ivar_assign(template) + locals[:object] = locals[template.variable_name] = object locals[options[:as]] = object if options[:as] end @@ -316,6 +321,9 @@ module ActionView locals[template.counter_name] = index index += 1 + + self._partial = template + _render_template(template, locals) end.join(spacer) end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 6e368f27eb..fe785e7b20 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -95,6 +95,11 @@ module ActionView layout ? _render_content_with_layout(text, layout, options[:locals]) : text end + def _render_template_from_controller(*args) + @assigns_added = nil + _render_template_with_layout(*args) + end + def _render_template_with_layout(template, layout = nil, options = {}, partial = false) if controller && logger logger.info("Rendering #{template.identifier}" + diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index b07e6e5f3a..825ac9a46c 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,3 +1,6 @@ +if ENV["new_base"] + require "abstract_unit2" +else $:.unshift(File.dirname(__FILE__) + '/../lib') $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') @@ -38,3 +41,4 @@ ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') ActionController::Base.view_paths = FIXTURE_LOAD_PATH +end \ No newline at end of file diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb index 95e7b2e273..2fdaba7342 100644 --- a/actionpack/test/abstract_unit2.rb +++ b/actionpack/test/abstract_unit2.rb @@ -75,7 +75,7 @@ module ActionController end class Base - use ActionController::Testing + include ActionController::Testing end Base.view_paths = FIXTURE_LOAD_PATH @@ -89,44 +89,43 @@ module ActionController end def assert_template(options = {}, message = nil) - validate_response! + validate_request! - clean_backtrace do - case options - when NilClass, String - hax = @controller._action_view.instance_variable_get(:@_rendered) - rendered = (hax[:template] || []).map { |t| t.identifier } - msg = build_message(message, - "expecting but rendering with ", - options, rendered.join(', ')) - assert_block(msg) do - if options.nil? - hax[:template].blank? - else - rendered.any? { |t| t.match(options) } - end - end - when Hash - if expected_partial = options[:partial] - partials = hax[:partials] - if expected_count = options[:count] - found = partials.detect { |p, _| p.identifier.match(expected_partial) } - actual_count = found.nil? ? 0 : found.second - msg = build_message(message, - "expecting ? to be rendered ? time(s) but rendered ? time(s)", - expected_partial, expected_count, actual_count) - assert(actual_count == expected_count.to_i, msg) - else - msg = build_message(message, - "expecting partial but action rendered ", - options[:partial], partials.keys) - assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg) - end + hax = @controller._action_view.instance_variable_get(:@_rendered) + + case options + when NilClass, String + rendered = (hax[:template] || []).map { |t| t.identifier } + msg = build_message(message, + "expecting but rendering with ", + options, rendered.join(', ')) + assert_block(msg) do + if options.nil? + hax[:template].blank? else - assert hax[:partials].empty?, - "Expected no partials to be rendered" + rendered.any? { |t| t.match(options) } end end + when Hash + if expected_partial = options[:partial] + partials = hax[:partials] + if expected_count = options[:count] + found = partials.detect { |p, _| p.identifier.match(expected_partial) } + actual_count = found.nil? ? 0 : found.second + msg = build_message(message, + "expecting ? to be rendered ? time(s) but rendered ? time(s)", + expected_partial, expected_count, actual_count) + assert(actual_count == expected_count.to_i, msg) + else + msg = build_message(message, + "expecting partial but action rendered ", + options[:partial], partials.keys) + assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg) + end + else + assert hax[:partials].empty?, + "Expected no partials to be rendered" + end end end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index a58d9b08b5..4cea050a1e 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -1,4 +1,4 @@ -require ENV['new_base'] ? 'abstract_unit2' : 'abstract_unit' +require 'abstract_unit' require 'controller/fake_models' require 'pathname' @@ -1647,7 +1647,7 @@ class EtagRenderTest < ActionController::TestCase def test_render_against_etag_request_should_304_when_match @request.if_none_match = etag_for("hello david") get :render_hello_world_from_variable - assert_equal 304, @response.status + assert_equal 304, @response.status.to_i assert @response.body.empty? end diff --git a/actionpack/test/new_base/redirect_test.rb b/actionpack/test/new_base/redirect_test.rb new file mode 100644 index 0000000000..e591ebd05f --- /dev/null +++ b/actionpack/test/new_base/redirect_test.rb @@ -0,0 +1 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") \ No newline at end of file From 4c963972fd0fb696e857540351f7558f027ec962 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 12 May 2009 14:21:29 -0700 Subject: [PATCH 03/45] Defer rake/contrib requires so we can use the stdlib rake instead of the full gem --- Rakefile | 2 +- railties/Rakefile | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 8f4c891074..b3f7c8b642 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,5 @@ require 'rake' require 'rake/rdoctask' -require 'rake/contrib/sshpublisher' env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD'] @@ -74,6 +73,7 @@ end desc "Publish API docs for Rails as a whole and for each component" task :pdoc => :rdoc do + require 'rake/contrib/sshpublisher' Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/api", "doc/rdoc").upload PROJECTS.each do |project| system %(cd #{project} && #{env} #{$0} pdoc) diff --git a/railties/Rakefile b/railties/Rakefile index 4247742664..7637293007 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -2,7 +2,6 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' -require 'rake/contrib/rubyforgepublisher' require 'date' require 'rbconfig' @@ -344,12 +343,14 @@ end # Publishing ------------------------------------------------------- desc "Publish the rails gem" task :pgem => [:gem] do + require 'rake/contrib/sshpublisher' Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` end desc "Publish the guides" task :pguides => :guides do + require 'rake/contrib/sshpublisher' mkdir_p 'pkg' `tar -czf pkg/guides.gz guides/output` Rake::SshFilePublisher.new("web.rubyonrails.org", "/u/sites/guides.rubyonrails.org/public", "pkg", "guides.gz").upload @@ -358,6 +359,7 @@ end desc "Publish the release files to RubyForge." task :release => [ :package ] do + require 'rake/contrib/rubyforgepublisher' require 'rubyforge' packages = %w( gem ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } From e9c5750bd1bb15b2d551ee014f06bd5019f2357d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 12 May 2009 17:55:45 -0700 Subject: [PATCH 04/45] Preserve ordering --- tools/{profile_requires.rb => profile_requires} | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) rename tools/{profile_requires.rb => profile_requires} (84%) mode change 100644 => 100755 diff --git a/tools/profile_requires.rb b/tools/profile_requires old mode 100644 new mode 100755 similarity index 84% rename from tools/profile_requires.rb rename to tools/profile_requires index 68d0de3d80..be7770b3e5 --- a/tools/profile_requires.rb +++ b/tools/profile_requires @@ -18,12 +18,14 @@ module TrackHeapGrowth self.stats = [] def track_growth(file) + TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent] TrackHeapGrowth.indent += 1 heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects result = nil elapsed = Benchmark.realtime { result = yield } heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects TrackHeapGrowth.indent -= 1 + TrackHeapGrowth.stats.pop if TrackHeapGrowth.stats.last.first == file TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent, elapsed, heap_after - heap_before, objects_after - objects_before] if result result end @@ -69,7 +71,11 @@ if mode end end -TrackHeapGrowth.stats.reverse_each do |file, indent, sec, bytes, objects| - puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file] +TrackHeapGrowth.stats.each do |file, indent, sec, bytes, objects| + if sec + puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file] + else + puts "#{' ' * (42 + indent)}#{file}" + end end puts "%10.2f KB %10d obj %8.1f ms %d KB RSS" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss] From a7ccc7c79fa69cea3b7d19bcaa4df3c2932238d8 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 12 May 2009 17:58:37 -0700 Subject: [PATCH 05/45] Remove support for deprecated validation message interpolation format --- activerecord/lib/active_record.rb | 1 - .../i18n_interpolation_deprecation.rb | 26 -------------- .../test/cases/validations_i18n_test.rb | 34 +++++-------------- 3 files changed, 8 insertions(+), 53 deletions(-) delete mode 100644 activerecord/lib/active_record/i18n_interpolation_deprecation.rb diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 06d6c87090..c9e9a84ce7 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -75,5 +75,4 @@ module ActiveRecord end end -require 'active_record/i18n_interpolation_deprecation' I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml' diff --git a/activerecord/lib/active_record/i18n_interpolation_deprecation.rb b/activerecord/lib/active_record/i18n_interpolation_deprecation.rb deleted file mode 100644 index cd634e1b8d..0000000000 --- a/activerecord/lib/active_record/i18n_interpolation_deprecation.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Deprecates the use of the former message interpolation syntax in activerecord -# as in "must have %d characters". The new syntax uses explicit variable names -# as in "{{value}} must have {{count}} characters". - -require 'i18n/backend/simple' -module I18n - module Backend - class Simple - DEPRECATED_INTERPOLATORS = { '%d' => '{{count}}', '%s' => '{{value}}' } - - protected - def interpolate_with_deprecated_syntax(locale, string, values = {}) - return string unless string.is_a?(String) - - string = string.gsub(/%d|%s/) do |s| - instead = DEPRECATED_INTERPOLATORS[s] - ActiveSupport::Deprecation.warn "using #{s} in messages is deprecated; use #{instead} instead." - instead - end - - interpolate_without_deprecated_syntax(locale, string, values) - end - alias_method_chain :interpolate, :deprecated_syntax - end - end -end \ No newline at end of file diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb index 66982346e9..20d1369a64 100644 --- a/activerecord/test/cases/validations_i18n_test.rb +++ b/activerecord/test/cases/validations_i18n_test.rb @@ -38,35 +38,17 @@ class ActiveRecordValidationsI18nTests < ActiveSupport::TestCase end end - def test_default_error_messages_is_deprecated - assert_deprecated('ActiveRecord::Errors.default_error_messages') do - ActiveRecord::Errors.default_error_messages + def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated + assert_not_deprecated do + default = "%s interpolation syntax was deprecated" + assert_equal default, I18n.t(:does_not_exist, :default => default, :value => 'this') end end - def test_percent_s_interpolation_syntax_in_error_messages_still_works - ActiveSupport::Deprecation.silence do - result = I18n.t :does_not_exist, :default => "%s interpolation syntax is deprecated", :value => 'this' - assert_equal result, "this interpolation syntax is deprecated" - end - end - - def test_percent_s_interpolation_syntax_in_error_messages_is_deprecated - assert_deprecated('using %s in messages') do - I18n.t :does_not_exist, :default => "%s interpolation syntax is deprected", :value => 'this' - end - end - - def test_percent_d_interpolation_syntax_in_error_messages_still_works - ActiveSupport::Deprecation.silence do - result = I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprecated", :count => 2 - assert_equal result, "2 interpolation syntaxes are deprecated" - end - end - - def test_percent_d_interpolation_syntax_in_error_messages_is_deprecated - assert_deprecated('using %d in messages') do - I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprected", :count => 2 + def test_percent_d_interpolation_syntax_in_error_messages_was_deprecated + assert_not_deprecated do + default = "%d interpolation syntaxes are deprecated" + assert_equal default, I18n.t(:does_not_exist, :default => default, :count => 2) end end From fa5da8ad54d68ea0484825845eb6f6a8e8bca361 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 May 2009 01:06:53 -0700 Subject: [PATCH 06/45] isolated_test task --- actionpack/Rakefile | 6 ++++++ activerecord/Rakefile | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/actionpack/Rakefile b/actionpack/Rakefile index ef76eedfd7..6ce8179646 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -34,6 +34,12 @@ Rake::TestTask.new(:test_action_pack) do |t| t.verbose = true #t.warning = true end +task :isolated_test do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file| + system(ruby, '-Ilib:test', file) + end or raise "Failures" +end desc 'ActiveRecord Integration Tests' Rake::TestTask.new(:test_active_record_integration) do |t| diff --git a/activerecord/Rakefile b/activerecord/Rakefile index 5905c67e29..892d52f30d 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -33,20 +33,28 @@ task :test => defined?(JRUBY_VERSION) ? %w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) : %w(test_mysql test_sqlite3 test_postgresql) -for adapter in %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ) +%w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter| Rake::TestTask.new("test_#{adapter}") { |t| - if adapter =~ /jdbc/ - t.libs << "test" << "test/connections/jdbc_#{adapter}" - else - t.libs << "test" << "test/connections/native_#{adapter}" - end + connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}" adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/] + t.libs << "test" << connection_path t.test_files=Dir.glob( "test/cases/**/*_test{,_#{adapter_short}}.rb" ).sort t.verbose = true } + task "isolated_test_#{adapter}" do + connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}" + adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/] + puts [adapter, adapter_short, connection_path].inspect + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir["test/cases/**/*_test{,_#{adapter_short}}.rb"].all? do |file| + system(ruby, "-Ilib:test:#{connection_path}", file) + end or raise "Failures" + end + namespace adapter do task :test => "test_#{adapter}" + task :isolated_test => "isolated_test_#{adapter}" end end From e8550ee0329586b32de425e905c7af7e65bc78a8 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 May 2009 01:10:37 -0700 Subject: [PATCH 07/45] Cherry-pick core extensions --- Rakefile | 2 +- actionmailer/Rakefile | 6 ++++++ .../lib/action_mailer/vendor/tmail.rb | 1 + actionpack/lib/action_controller.rb | 13 +++--------- actionpack/lib/action_controller/base/base.rb | 2 ++ .../base/chained/benchmarking.rb | 2 +- .../base/http_authentication.rb | 6 ++++-- .../lib/action_controller/base/layout.rb | 4 ++++ .../action_controller/record_identifier.rb | 2 ++ .../lib/action_controller/routing/builder.rb | 2 ++ .../lib/action_controller/routing/route.rb | 8 ++++--- .../lib/action_controller/testing/process.rb | 1 + actionpack/lib/action_dispatch.rb | 13 +++--------- .../lib/action_dispatch/http/mime_type.rb | 1 + .../lib/action_dispatch/http/request.rb | 1 + .../lib/action_dispatch/http/response.rb | 1 + actionpack/lib/action_view.rb | 13 +++--------- actionpack/lib/action_view/base.rb | 3 +++ .../lib/action_view/helpers/form_helper.rb | 9 ++++---- .../lib/action_view/template/handlers/erb.rb | 1 + .../test/abstract_controller/test_helper.rb | 4 ++-- actionpack/test/abstract_unit2.rb | 3 +-- .../test/controller/addresses_render_test.rb | 1 + actionpack/test/controller/base_test.rb | 1 + actionpack/test/controller/capture_test.rb | 1 + actionpack/test/controller/helper_test.rb | 1 + activemodel/Rakefile | 6 ++++++ activemodel/test/state_machine/event_test.rb | 1 + .../state_machine/state_transition_test.rb | 1 + activerecord/Rakefile | 3 +++ activerecord/lib/active_record.rb | 1 - .../lib/active_record/associations.rb | 2 ++ .../lib/active_record/attribute_methods.rb | 2 ++ activerecord/lib/active_record/base.rb | 21 +++++++++++++------ .../abstract/connection_pool.rb | 1 + .../connection_adapters/abstract/quoting.rb | 2 ++ .../connection_adapters/abstract_adapter.rb | 2 ++ .../connection_adapters/mysql_adapter.rb | 1 + .../connection_adapters/postgresql_adapter.rb | 1 + .../connection_adapters/sqlite3_adapter.rb | 6 +++--- .../connection_adapters/sqlite_adapter.rb | 1 + activerecord/lib/active_record/dirty.rb | 4 +++- activerecord/lib/active_record/fixtures.rb | 1 + activerecord/lib/active_record/migration.rb | 10 ++++----- activerecord/lib/active_record/named_scope.rb | 3 +++ .../lib/active_record/nested_attributes.rb | 3 +++ .../lib/active_record/schema_dumper.rb | 4 ++-- .../lib/active_record/serialization.rb | 17 ++++++++------- .../serializers/xml_serializer.rb | 5 ++++- activerecord/lib/active_record/validations.rb | 5 ++--- activerecord/test/cases/aggregations_test.rb | 1 + .../eager_load_nested_include_test.rb | 1 + ...s_and_belongs_to_many_associations_test.rb | 1 + activerecord/test/cases/base_test.rb | 1 + activerecord/test/cases/finder_test.rb | 5 +++-- activerecord/test/cases/helper.rb | 5 +++++ activerecord/test/cases/named_scope_test.rb | 3 ++- .../test/cases/nested_attributes_test.rb | 1 + activerecord/test/models/company_in_module.rb | 2 ++ activeresource/Rakefile | 7 +++++++ activeresource/lib/active_resource/base.rb | 4 +++- .../test/base/custom_methods_test.rb | 1 + activeresource/test/base/load_test.rb | 1 + activeresource/test/base_test.rb | 1 + activesupport/Rakefile | 2 +- .../core_ext/object/conversions.rb | 3 +++ railties/Rakefile | 1 + railties/lib/initializer.rb | 2 +- railties/lib/rails/plugin.rb | 2 ++ railties/test/abstract_unit.rb | 1 - railties/test/plugin_test_helper.rb | 1 - 71 files changed, 168 insertions(+), 83 deletions(-) diff --git a/Rakefile b/Rakefile index b3f7c8b642..58e1247600 100644 --- a/Rakefile +++ b/Rakefile @@ -12,7 +12,7 @@ end desc 'Run all tests by default' task :default => :test -%w(test rdoc pgem package release).each do |task_name| +%w(test isolated_test rdoc pgem package release).each do |task_name| desc "Run #{task_name} task for all projects" task task_name do PROJECTS.each do |project| diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index f06f18ff76..24c25abc8b 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -28,6 +28,12 @@ Rake::TestTask.new { |t| t.warning = false } +task :isolated_test do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/*_test.rb").all? do |file| + system(ruby, '-Ilib:test', file) + end or raise "Failures" +end # Generate the RDoc documentation Rake::RDocTask.new { |rdoc| diff --git a/actionmailer/lib/action_mailer/vendor/tmail.rb b/actionmailer/lib/action_mailer/vendor/tmail.rb index 51d36cdd0d..60555605f6 100644 --- a/actionmailer/lib/action_mailer/vendor/tmail.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail.rb @@ -12,6 +12,7 @@ end require 'tmail' +require 'active_support/core_ext/kernel/reporting' silence_warnings do TMail::Encoder.const_set("MAX_LINE_LEN", 200) end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index ab78bc9222..39083a84e9 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -21,16 +21,9 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -begin - require 'active_support' -rescue LoadError - activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" - if File.directory?(activesupport_path) - $:.unshift activesupport_path - require 'active_support' - end -end -require 'active_support/core/all' +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift activesupport_path if File.directory?(activesupport_path) +require 'active_support' require File.join(File.dirname(__FILE__), "action_pack") diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index d25801b17b..2813e71d12 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -1,5 +1,7 @@ require 'action_controller/deprecated' require 'set' +require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/module/attr_internal' module ActionController #:nodoc: class ActionControllerError < StandardError #:nodoc: diff --git a/actionpack/lib/action_controller/base/chained/benchmarking.rb b/actionpack/lib/action_controller/base/chained/benchmarking.rb index 066150f58a..66e9e9c31d 100644 --- a/actionpack/lib/action_controller/base/chained/benchmarking.rb +++ b/actionpack/lib/action_controller/base/chained/benchmarking.rb @@ -1,4 +1,4 @@ -require 'benchmark' +require 'active_support/core_ext/benchmark' module ActionController #:nodoc: # The benchmarking module times the performance of actions and reports to the logger. If the Active Record diff --git a/actionpack/lib/action_controller/base/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb index b6b5267c66..fa8ecea408 100644 --- a/actionpack/lib/action_controller/base/http_authentication.rb +++ b/actionpack/lib/action_controller/base/http_authentication.rb @@ -1,3 +1,5 @@ +require 'active_support/base64' + module ActionController module HttpAuthentication # Makes it dead easy to do HTTP Basic authentication. @@ -276,7 +278,7 @@ module ActionController t = time.to_i hashed = [t, secret_key] digest = ::Digest::MD5.hexdigest(hashed.join(":")) - Base64.encode64("#{t}:#{digest}").gsub("\n", '') + ActiveSupport::Base64.encode64("#{t}:#{digest}").gsub("\n", '') end # Might want a shorter timeout depending on whether the request @@ -285,7 +287,7 @@ module ActionController # allow a user to use new nonce without prompting user again for their # username and password. def validate_nonce(request, value, seconds_to_timeout=5*60) - t = Base64.decode64(value).split(":").first.to_i + t = ActiveSupport::Base64.decode64(value).split(":").first.to_i nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout end diff --git a/actionpack/lib/action_controller/base/layout.rb b/actionpack/lib/action_controller/base/layout.rb index 1ad5191c73..cf5f46a32b 100644 --- a/actionpack/lib/action_controller/base/layout.rb +++ b/actionpack/lib/action_controller/base/layout.rb @@ -1,3 +1,7 @@ +require 'active_support/core_ext/enumerable' +require 'active_support/core_ext/class/delegating_attributes' +require 'active_support/core_ext/class/inheritable_attributes' + module ActionController #:nodoc: module Layout #:nodoc: def self.included(base) diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb index 6bda27e23a..b4408e4e1d 100644 --- a/actionpack/lib/action_controller/record_identifier.rb +++ b/actionpack/lib/action_controller/record_identifier.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module' + module ActionController # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or # Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index d9590c88b8..42ad12e1ea 100644 --- a/actionpack/lib/action_controller/routing/builder.rb +++ b/actionpack/lib/action_controller/routing/builder.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/hash/except' + module ActionController module Routing class RouteBuilder #:nodoc: diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb index e2077edad8..eba05a3c5a 100644 --- a/actionpack/lib/action_controller/routing/route.rb +++ b/actionpack/lib/action_controller/routing/route.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/misc' + module ActionController module Routing class Route #:nodoc: @@ -65,7 +67,7 @@ module ActionController # map.connect '/page/:id', :controller => 'pages', :action => 'show', :id => /\d+/ # def parameter_shell - @parameter_shell ||= returning({}) do |shell| + @parameter_shell ||= {}.tap do |shell| requirements.each do |key, requirement| shell[key] = requirement unless requirement.is_a? Regexp end @@ -76,7 +78,7 @@ module ActionController # includes keys that appear inside the path, and keys that have requirements # placed upon them. def significant_keys - @significant_keys ||= returning([]) do |sk| + @significant_keys ||= [].tap do |sk| segments.each { |segment| sk << segment.key if segment.respond_to? :key } sk.concat requirements.keys sk.uniq! @@ -86,7 +88,7 @@ module ActionController # Return a hash of key/value pairs representing the keys in the route that # have defaults, or which are specified by non-regexp requirements. def defaults - @defaults ||= returning({}) do |hash| + @defaults ||= {}.tap do |hash| segments.each do |segment| next unless segment.respond_to? :default hash[segment.key] = segment.default unless segment.default.nil? diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 936f97ecb5..8f4358c33e 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -1,4 +1,5 @@ require 'rack/session/abstract/id' +require 'active_support/core_ext/object/conversions' module ActionController #:nodoc: class TestRequest < ActionDispatch::TestRequest #:nodoc: diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index c882930e64..27d229835a 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,16 +21,9 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -begin - require 'active_support' -rescue LoadError - activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" - if File.directory?(activesupport_path) - $:.unshift activesupport_path - require 'active_support' - end -end -require 'active_support/core/all' +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift activesupport_path if File.directory?(activesupport_path) +require 'active_support' begin gem 'rack', '~> 1.1.pre' diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 02ad7f7d94..dfcf3a558f 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -1,4 +1,5 @@ require 'set' +require 'active_support/core_ext/class/attribute_accessors' module Mime SET = [] diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index e4f3a8f125..13ff049a97 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -3,6 +3,7 @@ require 'stringio' require 'strscan' require 'active_support/memoizable' +require 'active_support/core_ext/hash/indifferent_access' module ActionDispatch class Request < Rack::Request diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index c3b5a68f40..edb522ff49 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -1,4 +1,5 @@ require 'digest/md5' +require 'active_support/core_ext/module/delegation' module ActionDispatch # :nodoc: # Represents an HTTP response generated by a controller action. One can use diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index dd352f9ce0..c3786af439 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -21,16 +21,9 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -begin - require 'active_support' -rescue LoadError - activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" - if File.directory?(activesupport_path) - $:.unshift activesupport_path - require 'active_support' - end -end -require 'active_support/core/all' +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift activesupport_path if File.directory?(activesupport_path) +require 'active_support' require File.join(File.dirname(__FILE__), "action_pack") diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 44bd401631..56f0b5ef4f 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/module/attr_internal' +require 'active_support/core_ext/module/delegation' + module ActionView #:nodoc: class ActionViewError < StandardError #:nodoc: end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index a59829b23f..beef661a37 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -2,6 +2,7 @@ require 'cgi' require 'action_view/helpers/date_helper' require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' +require 'active_support/core_ext/class/inheritable_attributes' module ActionView module Helpers @@ -1039,8 +1040,8 @@ module ActionView end end - class Base - cattr_accessor :default_form_builder - self.default_form_builder = ::ActionView::Helpers::FormBuilder + class << Base + attr_accessor :default_form_builder end -end \ No newline at end of file + Base.default_form_builder = ::ActionView::Helpers::FormBuilder +end diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index a20b1b0cd3..fdcb108ffc 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -1,4 +1,5 @@ require 'erb' +require 'active_support/core_ext/class/attribute_accessors' module ActionView module TemplateHandlers diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb index a08ab5a6d7..915054f7fb 100644 --- a/actionpack/test/abstract_controller/test_helper.rb +++ b/actionpack/test/abstract_controller/test_helper.rb @@ -4,7 +4,7 @@ $:.unshift(File.dirname(__FILE__) + '/../lib') require 'rubygems' require 'test/unit' -require 'active_support/core/all' +require 'active_support' require 'active_support/test_case' require 'action_controller/abstract' require 'action_view' @@ -18,4 +18,4 @@ begin Debugger.start rescue LoadError # Debugging disabled. `gem install ruby-debug` to enable. -end \ No newline at end of file +end diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb index 2fdaba7342..932f594ad2 100644 --- a/actionpack/test/abstract_unit2.rb +++ b/actionpack/test/abstract_unit2.rb @@ -5,7 +5,6 @@ $:.unshift(File.dirname(__FILE__) + '/lib') require 'test/unit' require 'active_support' -require 'active_support/core/all' require 'active_support/test_case' require 'action_controller/abstract' require 'action_controller/new_base' @@ -129,4 +128,4 @@ module ActionController end end end -end \ No newline at end of file +end diff --git a/actionpack/test/controller/addresses_render_test.rb b/actionpack/test/controller/addresses_render_test.rb index 2f092b6731..2d2a2745b0 100644 --- a/actionpack/test/controller/addresses_render_test.rb +++ b/actionpack/test/controller/addresses_render_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'logger' class Address def Address.count(conditions = nil, join = nil) diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index 0c54d61426..a09db95d7d 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'logger' require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late # Provide some controller to run the tests on. diff --git a/actionpack/test/controller/capture_test.rb b/actionpack/test/controller/capture_test.rb index 9a0976ca9f..06a5af6b32 100644 --- a/actionpack/test/controller/capture_test.rb +++ b/actionpack/test/controller/capture_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'logger' class CaptureController < ActionController::Base def self.controller_name; "test"; end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 19cd5f4db2..7b8096fccc 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/core_ext/kernel/reporting' ActionController::Base.helpers_dir = File.dirname(__FILE__) + '/../fixtures/helpers' diff --git a/activemodel/Rakefile b/activemodel/Rakefile index 4b60f8d682..544f49310a 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -11,6 +11,12 @@ Rake::TestTask.new do |t| t.verbose = true t.warning = true end +task :isolated_test do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/**/*_test.rb").all? do |file| + system(ruby, '-Ilib:test', file) + end or raise "Failures" +end # Generate the RDoc documentation Rake::RDocTask.new do |rdoc| diff --git a/activemodel/test/state_machine/event_test.rb b/activemodel/test/state_machine/event_test.rb index 64dc8c4875..05e7c78e8a 100644 --- a/activemodel/test/state_machine/event_test.rb +++ b/activemodel/test/state_machine/event_test.rb @@ -1,4 +1,5 @@ require 'test_helper' +require 'active_model/state_machine/event' class EventTest < ActiveModel::TestCase def setup diff --git a/activemodel/test/state_machine/state_transition_test.rb b/activemodel/test/state_machine/state_transition_test.rb index b59ff5a6a7..966396fab1 100644 --- a/activemodel/test/state_machine/state_transition_test.rb +++ b/activemodel/test/state_machine/state_transition_test.rb @@ -1,4 +1,5 @@ require 'test_helper' +require 'active_model/state_machine/state_transition' class StateTransitionTest < ActiveModel::TestCase test 'should set from, to, and opts attr readers' do diff --git a/activerecord/Rakefile b/activerecord/Rakefile index 892d52f30d..0b3f50d17e 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -32,6 +32,9 @@ desc 'Run mysql, sqlite, and postgresql tests' task :test => defined?(JRUBY_VERSION) ? %w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) : %w(test_mysql test_sqlite3 test_postgresql) +task :isolated_test => defined?(JRUBY_VERSION) ? + %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) : + %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql) %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter| Rake::TestTask.new("test_#{adapter}") { |t| diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index c9e9a84ce7..2d98239052 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -24,7 +24,6 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' -require 'active_support/core/all' module ActiveRecord # TODO: Review explicit loads to see if they will automatically be handled by the initilizer. diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index e2dd36158f..c5e4df4950 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module/delegation' + module ActiveRecord class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc: def initialize(reflection) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 8d68d77eac..55d9a4d15d 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/enumerable' + module ActiveRecord module AttributeMethods #:nodoc: extend ActiveSupport::DependencyModule diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 97c36a675d..b9ba727a3f 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1,6 +1,15 @@ require 'yaml' require 'set' require 'active_support/dependencies' +require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/class/delegating_attributes' +require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/hash/deep_merge' +require 'active_support/core_ext/hash/indifferent_access' +require 'active_support/core_ext/hash/slice' +require 'active_support/core_ext/string/behavior' +require 'active_support/core/time' module ActiveRecord #:nodoc: # Generic Active Record exception class. @@ -1888,7 +1897,7 @@ module ActiveRecord #:nodoc: else find(:#{finder}, options.merge(finder_options)) end - #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(\', \')}")' if bang} + #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect { |pair| pair.join(\' = \') }.join(\', \')}")' if bang} end }, __FILE__, __LINE__ send(method_id, *arguments) @@ -2610,11 +2619,11 @@ module ActiveRecord #:nodoc: # Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either # instance will affect the other. def becomes(klass) - returning klass.new do |became| - became.instance_variable_set("@attributes", @attributes) - became.instance_variable_set("@attributes_cache", @attributes_cache) - became.instance_variable_set("@new_record", new_record?) - end + became = klass.new + became.instance_variable_set("@attributes", @attributes) + became.instance_variable_set("@attributes_cache", @attributes_cache) + became.instance_variable_set("@new_record", new_record?) + became end # Updates a single attribute and saves the record without going through the normal validation procedure. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index e8e736bf38..500dafdc2e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -1,5 +1,6 @@ require 'monitor' require 'set' +require 'active_support/core_ext/module/synchronization' module ActiveRecord # Raised when a connection could not be obtained within the connection diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 3a7bf35248..720fba29e9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/big_decimal/conversions' + module ActiveRecord module ConnectionAdapters # :nodoc: module Quoting diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index a8cd9f033b..91b111ab55 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -12,6 +12,8 @@ require 'active_record/connection_adapters/abstract/connection_pool' require 'active_record/connection_adapters/abstract/connection_specification' require 'active_record/connection_adapters/abstract/query_cache' +require 'active_support/core_ext/benchmark' + module ActiveRecord module ConnectionAdapters # :nodoc: # ActiveRecord supports multiple database systems. AbstractAdapter and diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 9300df28ee..d5536e4d67 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_support/core_ext/kernel/requires' require 'set' module MysqlCompat #:nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 4961793866..002696d2c4 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_support/core_ext/kernel/requires' begin require_library_or_gem 'pg' diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 75420f69aa..5eef692d05 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -25,9 +25,9 @@ module ActiveRecord module ConnectionAdapters #:nodoc: class SQLite3Adapter < SQLiteAdapter # :nodoc: def table_structure(table_name) - returning structure = @connection.table_info(quote_table_name(table_name)) do - raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty? - end + structure = @connection.table_info(quote_table_name(table_name)) + raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty? + structure end end end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 05334a830a..c9d0c9574f 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_support/core_ext/kernel/requires' module ActiveRecord class Base diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb index fac6ca40d3..ac84f6b209 100644 --- a/activerecord/lib/active_record/dirty.rb +++ b/activerecord/lib/active_record/dirty.rb @@ -168,7 +168,9 @@ module ActiveRecord module ClassMethods def self.extended(base) - base.metaclass.alias_method_chain(:alias_attribute, :dirty) + class << base + alias_method_chain :alias_attribute, :dirty + end end def alias_attribute_with_dirty(new_name, old_name) diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 91b4b4e182..e30fcf9a4f 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -3,6 +3,7 @@ require 'yaml' require 'csv' require 'active_support/dependencies' require 'active_support/test_case' +require 'active_support/core_ext/logger' if RUBY_VERSION < '1.9' module YAML #:nodoc: diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 657acd6dc0..a7be3539d5 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -511,11 +511,11 @@ module ActiveRecord raise DuplicateMigrationNameError.new(name.camelize) end - klasses << returning(MigrationProxy.new) do |migration| - migration.name = name.camelize - migration.version = version - migration.filename = file - end + migration = MigrationProxy.new + migration.name = name.camelize + migration.version = version + migration.filename = file + klasses << migration end migrations = migrations.sort_by(&:version) diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 32bb36c07c..07f98dc743 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/array' +require 'active_support/core_ext/hash/except' + module ActiveRecord module NamedScope extend ActiveSupport::DependencyModule diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 1ea2f53fd8..c532d3dfa3 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/object/try' + module ActiveRecord module NestedAttributes #:nodoc: extend ActiveSupport::DependencyModule diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 557a554966..de530a3456 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -1,5 +1,5 @@ require 'stringio' -require 'bigdecimal' +require 'active_support/core_ext/big_decimal' module ActiveRecord # This class is used to dump the database schema for some connection to some @@ -176,4 +176,4 @@ HEADER end end end -end \ No newline at end of file +end diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index 78f66c3a73..7959f2b510 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -1,5 +1,3 @@ -require 'active_support/json' - module ActiveRecord #:nodoc: module Serialization class Serializer #:nodoc: @@ -73,16 +71,19 @@ module ActiveRecord #:nodoc: end def serializable_record - returning(serializable_record = {}) do - serializable_names.each { |name| serializable_record[name] = @record.send(name) } - add_includes do |association, records, opts| + record = {} + serializable_names.each { |name| record[name] = @record.send(name) } + + add_includes do |association, records, opts| + record[association] = if records.is_a?(Enumerable) - serializable_record[association] = records.collect { |r| self.class.new(r, opts).serializable_record } + records.collect { |r| self.class.new(r, opts).serializable_record } else - serializable_record[association] = self.class.new(records, opts).serializable_record + self.class.new(records, opts).serializable_record end - end end + + record end def serialize diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index fa75874603..4eaf9531e2 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/hash/conversions' + module ActiveRecord #:nodoc: module Serialization # Builds an XML document to represent the model. Some configuration is @@ -165,8 +167,9 @@ module ActiveRecord #:nodoc: class XmlSerializer < ActiveRecord::Serialization::Serializer #:nodoc: def builder @builder ||= begin + require 'builder' unless defined? ::Builder options[:indent] ||= 2 - builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) + builder = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent]) unless options[:skip_instruct] builder.instruct! diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 9907a3c9b7..b6e848fa79 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -1,5 +1,3 @@ -require 'builder' - module ActiveRecord # Raised by save! and create! when the record is invalid. Use the # +record+ method to retrieve the record which did not validate. @@ -247,9 +245,10 @@ module ActiveRecord # # Address can't be blank # # def to_xml(options={}) + require 'builder' unless defined? ::Builder options[:root] ||= "errors" options[:indent] ||= 2 - options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) + options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent]) options[:builder].instruct! unless options.delete(:skip_instruct) options[:builder].errors do |e| diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb index 4e0e1c7f15..8b6ec04018 100644 --- a/activerecord/test/cases/aggregations_test.rb +++ b/activerecord/test/cases/aggregations_test.rb @@ -1,5 +1,6 @@ require "cases/helper" require 'models/customer' +require 'active_support/core_ext/exception' class AggregationsTest < ActiveRecord::TestCase fixtures :customers diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb index 5f824f9c74..cb7fe9698b 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -4,6 +4,7 @@ require 'models/author' require 'models/comment' require 'models/category' require 'models/categorization' +require 'active_support/core_ext/array/random_access' module Remembered extend ActiveSupport::DependencyModule diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 5e8b2cadfc..8dc95806b9 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -24,6 +24,7 @@ require 'models/club' require 'models/member' require 'models/membership' require 'models/sponsor' +require 'active_support/core_ext/string/conversions' class ProjectWithAfterCreateHook < ActiveRecord::Base set_table_name 'projects' diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 7ca2807f7e..59aa6953e3 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -18,6 +18,7 @@ require 'models/minimalistic' require 'models/warehouse_thing' require 'models/parrot' require 'rexml/document' +require 'active_support/core_ext/exception' class Category < ActiveRecord::Base; end class Categorization < ActiveRecord::Base; end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 28eb311618..ad4588db69 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -485,8 +485,9 @@ class FinderTest < ActiveRecord::TestCase assert_equal "foo in (#{quoted_nil})", bind('foo in (?)', []) end - def test_bind_string - assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '') + def test_bind_empty_string + quoted_empty = ActiveRecord::Base.connection.quote('') + assert_equal quoted_empty, bind('?', '') end def test_bind_chars diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 1ec52ac24d..05e92433cd 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -15,6 +15,11 @@ require 'connection' require 'cases/repair_helper' +begin + require 'ruby-debug' +rescue LoadError +end + # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index ae6a54a5bd..7dcea6d42e 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'active_support/core_ext/array/random_access' require 'models/post' require 'models/topic' require 'models/comment' @@ -265,7 +266,7 @@ class NamedScopeTest < ActiveRecord::TestCase end def test_rand_should_select_a_random_object_from_proxy - assert Topic.approved.rand.is_a?(Topic) + assert_kind_of Topic, Topic.approved.rand end def test_should_use_where_in_query_for_named_scope diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index f1741ed54d..f31275163d 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -4,6 +4,7 @@ require "models/ship" require "models/bird" require "models/parrot" require "models/treasure" +require 'active_support/hash_with_indifferent_access' module AssertRaiseWithMessage def assert_raise_with_message(expected_exception, expected_message) diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index 7f02403d5a..3c34efbe16 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/misc' + module MyApplication module Business class Company < ActiveRecord::Base diff --git a/activeresource/Rakefile b/activeresource/Rakefile index c3cde26b6c..eb5b1dd1ac 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -34,6 +34,13 @@ Rake::TestTask.new { |t| t.verbose = true t.warning = true } +task :isolated_test do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib" + Dir.glob("test/**/*_test.rb").all? do |file| + system(ruby, "-Ilib:test:#{activesupport_path}", file) + end or raise "Failures" +end # Generate the RDoc documentation diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 8a1236c9a8..dc24e713ff 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -1,8 +1,10 @@ +require 'active_support' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/inheritable_attributes' require 'active_support/core_ext/module/attr_accessor_with_default' require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/aliasing' +require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/misc' require 'set' @@ -1027,7 +1029,7 @@ module ActiveResource private # Tries to find a resource for a given collection name; if it fails, then the resource is created def find_or_create_resource_for_collection(name) - find_or_create_resource_for(name.to_s.singularize) + find_or_create_resource_for(ActiveSupport::Inflector.singularize(name.to_s)) end # Tries to find a resource in a non empty list of nested modules diff --git a/activeresource/test/base/custom_methods_test.rb b/activeresource/test/base/custom_methods_test.rb index 61887f4ec7..2d81549a65 100644 --- a/activeresource/test/base/custom_methods_test.rb +++ b/activeresource/test/base/custom_methods_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'fixtures/person' require 'fixtures/street_address' +require 'active_support/core_ext/hash/conversions' class CustomMethodsTest < Test::Unit::TestCase def setup diff --git a/activeresource/test/base/load_test.rb b/activeresource/test/base/load_test.rb index cd2103acb7..035bd965c2 100644 --- a/activeresource/test/base/load_test.rb +++ b/activeresource/test/base/load_test.rb @@ -2,6 +2,7 @@ require 'abstract_unit' require "fixtures/person" require "fixtures/street_address" require 'active_support/core_ext/symbol' +require 'active_support/core_ext/hash/conversions' module Highrise class Note < ActiveResource::Base diff --git a/activeresource/test/base_test.rb b/activeresource/test/base_test.rb index a6cef6b2ae..82d3b2ae96 100644 --- a/activeresource/test/base_test.rb +++ b/activeresource/test/base_test.rb @@ -3,6 +3,7 @@ require "fixtures/person" require "fixtures/customer" require "fixtures/street_address" require "fixtures/beast" +require 'active_support/core_ext/hash/conversions' class BaseTest < Test::Unit::TestCase def setup diff --git a/activesupport/Rakefile b/activesupport/Rakefile index a4e8200a43..c3ea09d424 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -22,8 +22,8 @@ Rake::TestTask.new { |t| t.warning = true } task :isolated_test do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir['test/**/*_test.rb'].all? do |file| - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) system(ruby, '-Ilib:test', file) end or raise "Failures" end diff --git a/activesupport/lib/active_support/core_ext/object/conversions.rb b/activesupport/lib/active_support/core_ext/object/conversions.rb index 278b856c45..638f0decc1 100644 --- a/activesupport/lib/active_support/core_ext/object/conversions.rb +++ b/activesupport/lib/active_support/core_ext/object/conversions.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/array/conversions' +require 'active_support/core_ext/hash/conversions' + class Object # Alias of to_s. def to_param diff --git a/railties/Rakefile b/railties/Rakefile index 7637293007..133a603ed6 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -31,6 +31,7 @@ task :test do system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file) end or raise "Failures" end +task :isolated_test => :test Rake::TestTask.new("regular_test") do |t| t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib" diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 9d27488e8a..40000f0dfd 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -264,8 +264,8 @@ module Rails # Action Pack, Action Mailer, and Active Resource) are loaded. def require_frameworks require 'active_support' - require 'active_support/core/all' configuration.frameworks.each { |framework| require(framework.to_s) } + require 'active_support/core/all' rescue LoadError => e # Re-raise as RuntimeError because Mongrel would swallow LoadError. raise e.to_s diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 0f924724cd..e66166306a 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/kernel/reporting' + module Rails # The Plugin class should be an object which provides the following methods: # diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index ffd60ee662..0addcb8bf3 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -13,7 +13,6 @@ gem 'mocha', '>= 0.9.5' require 'mocha' require 'active_support' -require 'active_support/core/all' require 'active_support/test_case' if defined?(RAILS_ROOT) diff --git a/railties/test/plugin_test_helper.rb b/railties/test/plugin_test_helper.rb index adb62de665..55d1a1fa96 100644 --- a/railties/test/plugin_test_helper.rb +++ b/railties/test/plugin_test_helper.rb @@ -3,7 +3,6 @@ $:.unshift File.dirname(__FILE__) + "/../../activesupport/lib" require 'test/unit' require 'active_support' -require 'active_support/core/all' require 'initializer' require File.join(File.dirname(__FILE__), 'abstract_unit') From 4f291fa528e5faad03def69ae7ac98224ab859db Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 May 2009 11:55:19 -0700 Subject: [PATCH 08/45] Simple examples for require profiling --- activerecord/examples/simple.rb | 14 ++++++++++++++ activeresource/examples/simple.rb | 16 ++++++++++++++++ tools/profile_requires | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 activerecord/examples/simple.rb create mode 100644 activeresource/examples/simple.rb diff --git a/activerecord/examples/simple.rb b/activerecord/examples/simple.rb new file mode 100644 index 0000000000..c12f746992 --- /dev/null +++ b/activerecord/examples/simple.rb @@ -0,0 +1,14 @@ +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" +require 'active_record' + +class Person < ActiveRecord::Base + establish_connection :adapter => 'sqlite3', :database => 'foobar.db' + connection.create_table table_name, :force => true do |t| + t.string :name + end +end + +bob = Person.create!(:name => 'bob') +puts Person.all.inspect +bob.destroy +puts Person.all.inspect diff --git a/activeresource/examples/simple.rb b/activeresource/examples/simple.rb new file mode 100644 index 0000000000..b20ef61670 --- /dev/null +++ b/activeresource/examples/simple.rb @@ -0,0 +1,16 @@ +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" +require 'active_resource' +require 'active_resource/http_mock' +require 'active_support/core_ext/hash/conversions' + +ActiveSupport::XmlMini.backend = ENV['XMLMINI'] || 'REXML' +ActiveResource::HttpMock.respond_to do |mock| + mock.get '/people/1.xml', {}, { :id => 1, :name => 'bob' }.to_xml(:root => 'person') +end + +class Person < ActiveResource::Base + self.site = 'http://localhost/' +end + +bob = Person.find(1) +puts bob.inspect diff --git a/tools/profile_requires b/tools/profile_requires index be7770b3e5..0fd11c7d41 100755 --- a/tools/profile_requires +++ b/tools/profile_requires @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # Example: -# ruby -Iactivesupport/lib tools/profile_requires.rb active_support -# ruby -Iactionpack/lib tools/profile_requires.rb action_controller +# tools/profile_requires activesupport/lib/active_support.rb +# tools/profile_requires activeresource/examples/simple.rb abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats) GC.enable_stats From 49a84ff69ca4fc4db821ca3b5a5926d07832c845 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Wed, 13 May 2009 17:00:36 -0700 Subject: [PATCH 09/45] Ported over render :file tests. --- actionpack/test/controller/render_js_test.rb | 37 ++ .../test/controller/render_json_test.rb | 80 +++++ .../test/controller/render_other_test.rb | 222 ++++++++++++ actionpack/test/controller/render_test.rb | 334 +----------------- actionpack/test/controller/render_xml_test.rb | 81 +++++ actionpack/test/new_base/render_file_test.rb | 110 ++++++ .../test/new_base/render_layout_test.rb | 18 +- actionpack/test/new_base/test_helper.rb | 24 ++ 8 files changed, 585 insertions(+), 321 deletions(-) create mode 100644 actionpack/test/controller/render_js_test.rb create mode 100644 actionpack/test/controller/render_json_test.rb create mode 100644 actionpack/test/controller/render_other_test.rb create mode 100644 actionpack/test/controller/render_xml_test.rb create mode 100644 actionpack/test/new_base/render_file_test.rb diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb new file mode 100644 index 0000000000..7b50242910 --- /dev/null +++ b/actionpack/test/controller/render_js_test.rb @@ -0,0 +1,37 @@ +require 'abstract_unit' +require 'controller/fake_models' +require 'pathname' + +class TestController < ActionController::Base + protect_from_forgery + + def render_vanilla_js_hello + render :js => "alert('hello')" + end + + def greeting + # let's just rely on the template + end + + def partial + render :partial => 'partial' + end +end + +class RenderTest < ActionController::TestCase + def test_render_vanilla_js + get :render_vanilla_js_hello + assert_equal "alert('hello')", @response.body + assert_equal "text/javascript", @response.content_type + end + + def test_render_with_default_from_accept_header + xhr :get, :greeting + assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body + end + + def test_should_render_js_partial + xhr :get, :partial, :format => 'js' + assert_equal 'partial js', @response.body + end +end \ No newline at end of file diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb new file mode 100644 index 0000000000..233b2dfd89 --- /dev/null +++ b/actionpack/test/controller/render_json_test.rb @@ -0,0 +1,80 @@ +require 'abstract_unit' +require 'controller/fake_models' +require 'pathname' + +class TestController < ActionController::Base + protect_from_forgery + + def render_json_nil + render :json => nil + end + + def render_json_hello_world + render :json => ActiveSupport::JSON.encode(:hello => 'world') + end + + def render_json_hello_world_with_callback + render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert' + end + + def render_json_with_custom_content_type + render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript' + end + + def render_symbol_json + render :json => ActiveSupport::JSON.encode(:hello => 'world') + end + + def render_json_with_render_to_string + render :json => {:hello => render_to_string(:partial => 'partial')} + end +end + +class RenderTest < ActionController::TestCase + tests TestController + + def setup + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + super + @controller.logger = Logger.new(nil) + + @request.host = "www.nextangle.com" + end + + def test_render_json_nil + get :render_json_nil + assert_equal 'null', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json + get :render_json_hello_world + assert_equal '{"hello":"world"}', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json_with_callback + get :render_json_hello_world_with_callback + assert_equal 'alert({"hello":"world"})', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json_with_custom_content_type + get :render_json_with_custom_content_type + assert_equal '{"hello":"world"}', @response.body + assert_equal 'text/javascript', @response.content_type + end + + def test_render_symbol_json + get :render_symbol_json + assert_equal '{"hello":"world"}', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json_with_render_to_string + get :render_json_with_render_to_string + assert_equal '{"hello":"partial html"}', @response.body + assert_equal 'application/json', @response.content_type + end +end \ No newline at end of file diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb new file mode 100644 index 0000000000..ddbdd2d213 --- /dev/null +++ b/actionpack/test/controller/render_other_test.rb @@ -0,0 +1,222 @@ +require 'abstract_unit' +require 'controller/fake_models' +require 'pathname' + +class TestController < ActionController::Base + protect_from_forgery + + module RenderTestHelper + def rjs_helper_method_from_module + page.visual_effect :highlight + end + end + + helper RenderTestHelper + helper do + def rjs_helper_method(value) + page.visual_effect :highlight, value + end + end + + def enum_rjs_test + render :update do |page| + page.select('.product').each do |value| + page.rjs_helper_method_from_module + page.rjs_helper_method(value) + page.sortable(value, :url => { :action => "order" }) + page.draggable(value) + end + end + end + + def render_explicit_html_template + end + + def render_custom_code_rjs + render :update, :status => 404 do |page| + page.replace :foo, :partial => 'partial' + end + end + + def render_implicit_html_template + end + + def render_js_with_explicit_template + @project_id = 4 + render :template => 'test/delete_with_js' + end + + def render_js_with_explicit_action_template + @project_id = 4 + render :action => 'delete_with_js' + end + + def delete_with_js + @project_id = 4 + end + + def update_page + render :update do |page| + page.replace_html 'balance', '$37,000,000.00' + page.visual_effect :highlight, 'balance' + end + end + + def update_page_with_instance_variables + @money = '$37,000,000.00' + @div_id = 'balance' + render :update do |page| + page.replace_html @div_id, @money + page.visual_effect :highlight, @div_id + end + end + + def update_page_with_view_method + render :update do |page| + page.replace_html 'person', pluralize(2, 'person') + end + end + + def partial_as_rjs + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + + def respond_to_partial_as_rjs + respond_to do |format| + format.js do + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + end + end + + def render_alternate_default + # For this test, the method "default_render" is overridden: + @alternate_default_render = lambda do + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + end + +private + def determine_layout + case action_name + when "render_js_with_explicit_template", + "render_js_with_explicit_action_template", + "delete_with_js", "update_page", "update_page_with_instance_variables" + + "layouts/standard" + when "action_talk_to_layout", "layout_overriding_layout" + "layouts/talk_from_action" + when "render_implicit_html_template_from_xhr_request" + (request.xhr? ? 'layouts/xhr' : 'layouts/standard') + end + end +end + +class RenderTest < ActionController::TestCase + tests TestController + + def setup + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + super + @controller.logger = Logger.new(nil) + + @request.host = "www.nextangle.com" + end + + def test_enum_rjs_test + ActiveSupport::SecureRandom.stubs(:base64).returns("asdf") + get :enum_rjs_test + body = %{ + $$(".product").each(function(value, index) { + new Effect.Highlight(element,{}); + new Effect.Highlight(value,{}); + Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}}); + new Draggable(value, {}); + }); + }.gsub(/^ /, '').strip + assert_equal body, @response.body + end + + def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template + [:js, "js"].each do |format| + assert_nothing_raised do + get :render_explicit_html_template, :format => format + assert_equal %(document.write("Hello world\\n");), @response.body + end + end + end + + def test_render_custom_code_rjs + get :render_custom_code_rjs + assert_response 404 + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_render_in_an_rjs_template_should_pick_html_templates_when_available + [:js, "js"].each do |format| + assert_nothing_raised do + get :render_implicit_html_template, :format => format + assert_equal %(document.write("Hello world\\n");), @response.body + end + end + end + + def test_render_rjs_template_explicitly + get :render_js_with_explicit_template + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_rendering_rjs_action_explicitly + get :render_js_with_explicit_action_template + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_render_rjs_with_default + get :delete_with_js + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_update_page + get :update_page + assert_template nil + assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type'] + assert_equal 2, @response.body.split($/).length + end + + def test_update_page_with_instance_variables + get :update_page_with_instance_variables + assert_template nil + assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"] + assert_match /balance/, @response.body + assert_match /\$37/, @response.body + end + + def test_update_page_with_view_method + get :update_page_with_view_method + assert_template nil + assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"] + assert_match /2 people/, @response.body + end + + def test_should_render_html_formatted_partial_with_rjs + xhr :get, :partial_as_rjs + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_should_render_html_formatted_partial_with_rjs_and_js_format + xhr :get, :respond_to_partial_as_rjs + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_should_render_with_alternate_default_render + xhr :get, :render_alternate_default + assert_equal %(Element.replace("foo", "partial html");), @response.body + end +end \ No newline at end of file diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 4cea050a1e..469e8601d0 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -145,18 +145,21 @@ class TestController < ActionController::Base render :layout => false end + # :ported: def render_file_with_instance_variables @secret = 'in the sauce' path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb') render :file => path end + # :ported: def render_file_as_string_with_instance_variables @secret = 'in the sauce' path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')) render path end + # :ported: def render_file_not_using_full_path @secret = 'in the sauce' render :file => 'test/render_file_with_ivar' @@ -203,41 +206,11 @@ class TestController < ActionController::Base render :inline => "<%= controller_name %>" end - def render_json_nil - render :json => nil - end - - def render_json_hello_world - render :json => ActiveSupport::JSON.encode(:hello => 'world') - end - - def render_json_hello_world_with_callback - render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert' - end - - def render_json_with_custom_content_type - render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript' - end - - def render_symbol_json - render :json => ActiveSupport::JSON.encode(:hello => 'world') - end - - def render_json_with_render_to_string - render :json => {:hello => render_to_string(:partial => 'partial')} - end - # :ported: def render_custom_code render :text => "hello world", :status => 404 end - def render_custom_code_rjs - render :update, :status => 404 do |page| - page.replace :foo, :partial => 'partial' - end - end - # :ported: def render_text_with_nil render :text => nil @@ -253,10 +226,6 @@ class TestController < ActionController::Base render :text => "appended" end - def render_vanilla_js_hello - render :js => "alert('hello')" - end - # This test is testing 3 things: # render :file in AV :ported: # render :template in AC :ported: @@ -271,10 +240,6 @@ class TestController < ActionController::Base render "test/hello" end - def render_xml_with_custom_content_type - render :xml => "", :content_type => "application/atomsvc+xml" - end - def render_line_offset render :inline => '<% raise %>', :locals => {:foo => 'bar'} end @@ -331,12 +296,6 @@ class TestController < ActionController::Base :locals => { :local_name => name } end - def render_implicit_html_template - end - - def render_explicit_html_template - end - def render_implicit_html_template_from_xhr_request end @@ -470,66 +429,6 @@ class TestController < ActionController::Base render :template => "test/hello_world_from_rxml.builder" end - module RenderTestHelper - def rjs_helper_method_from_module - page.visual_effect :highlight - end - end - - helper RenderTestHelper - helper do - def rjs_helper_method(value) - page.visual_effect :highlight, value - end - end - - def enum_rjs_test - render :update do |page| - page.select('.product').each do |value| - page.rjs_helper_method_from_module - page.rjs_helper_method(value) - page.sortable(value, :url => { :action => "order" }) - page.draggable(value) - end - end - end - - def delete_with_js - @project_id = 4 - end - - def render_js_with_explicit_template - @project_id = 4 - render :template => 'test/delete_with_js' - end - - def render_js_with_explicit_action_template - @project_id = 4 - render :action => 'delete_with_js' - end - - def update_page - render :update do |page| - page.replace_html 'balance', '$37,000,000.00' - page.visual_effect :highlight, 'balance' - end - end - - def update_page_with_instance_variables - @money = '$37,000,000.00' - @div_id = 'balance' - render :update do |page| - page.replace_html @div_id, @money - page.visual_effect :highlight, @div_id - end - end - - def update_page_with_view_method - render :update do |page| - page.replace_html 'person', pluralize(2, 'person') - end - end - def action_talk_to_layout # Action template sets variable that's picked up by layout end @@ -573,25 +472,6 @@ class TestController < ActionController::Base head :forbidden, :x_custom_header => "something" end - def render_with_location - render :xml => "", :location => "http://example.com", :status => 201 - end - - def render_with_object_location - customer = Customer.new("Some guy", 1) - render :xml => "", :location => customer_url(customer), :status => :created - end - - def render_with_to_xml - to_xmlable = Class.new do - def to_xml - "" - end - end.new - - render :xml => to_xmlable - end - def render_using_layout_around_block render :action => "using_layout_around_block" end @@ -608,22 +488,6 @@ class TestController < ActionController::Base render :partial => 'partial.html.erb' end - def partial_as_rjs - render :update do |page| - page.replace :foo, :partial => 'partial' - end - end - - def respond_to_partial_as_rjs - respond_to do |format| - format.js do - render :update do |page| - page.replace :foo, :partial => 'partial' - end - end - end - end - def partial render :partial => 'partial' end @@ -880,82 +744,54 @@ class RenderTest < ActionController::TestCase assert_equal 'Hello world!', @response.body end + # :ported: def test_render_file_with_instance_variables get :render_file_with_instance_variables assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_as_string_with_instance_variables get :render_file_as_string_with_instance_variables assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_not_using_full_path get :render_file_not_using_full_path assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_not_using_full_path_with_dot_in_path get :render_file_not_using_full_path_with_dot_in_path assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_using_pathname get :render_file_using_pathname assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_with_locals get :render_file_with_locals assert_equal "The secret is in the sauce\n", @response.body end + # :ported: def test_render_file_as_string_with_locals get :render_file_as_string_with_locals assert_equal "The secret is in the sauce\n", @response.body end + # :assessed: def test_render_file_from_template get :render_file_from_template assert_equal "The secret is in the sauce\n", @response.body end - def test_render_json_nil - get :render_json_nil - assert_equal 'null', @response.body - assert_equal 'application/json', @response.content_type - end - - def test_render_json - get :render_json_hello_world - assert_equal '{"hello":"world"}', @response.body - assert_equal 'application/json', @response.content_type - end - - def test_render_json_with_callback - get :render_json_hello_world_with_callback - assert_equal 'alert({"hello":"world"})', @response.body - assert_equal 'application/json', @response.content_type - end - - def test_render_json_with_custom_content_type - get :render_json_with_custom_content_type - assert_equal '{"hello":"world"}', @response.body - assert_equal 'text/javascript', @response.content_type - end - - def test_render_symbol_json - get :render_symbol_json - assert_equal '{"hello":"world"}', @response.body - assert_equal 'application/json', @response.content_type - end - - def test_render_json_with_render_to_string - get :render_json_with_render_to_string - assert_equal '{"hello":"partial html"}', @response.body - assert_equal 'application/json', @response.content_type - end - # :ported: def test_render_custom_code get :render_custom_code @@ -964,12 +800,6 @@ class RenderTest < ActionController::TestCase assert_equal 'hello world', @response.body end - def test_render_custom_code_rjs - get :render_custom_code_rjs - assert_response 404 - assert_equal %(Element.replace("foo", "partial html");), @response.body - end - # :ported: def test_render_text_with_nil get :render_text_with_nil @@ -1023,12 +853,6 @@ class RenderTest < ActionController::TestCase assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller. end - def test_render_vanilla_js - get :render_vanilla_js_hello - assert_equal "alert('hello')", @response.body - assert_equal "text/javascript", @response.content_type - end - # :ported: def test_render_xml get :render_xml_hello @@ -1053,20 +877,6 @@ class RenderTest < ActionController::TestCase assert_equal "\n \n\n", @response.body end - def test_enum_rjs_test - ActiveSupport::SecureRandom.stubs(:base64).returns("asdf") - get :enum_rjs_test - body = %{ - $$(".product").each(function(value, index) { - new Effect.Highlight(element,{}); - new Effect.Highlight(value,{}); - Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}}); - new Draggable(value, {}); - }); - }.gsub(/^ /, '').strip - assert_equal body, @response.body - end - def test_layout_rendering get :layout_test assert_equal "Hello world!", @response.body @@ -1114,29 +924,10 @@ class RenderTest < ActionController::TestCase assert_equal "Goodbye, Local David", @response.body end - def test_render_in_an_rjs_template_should_pick_html_templates_when_available - [:js, "js"].each do |format| - assert_nothing_raised do - get :render_implicit_html_template, :format => format - assert_equal %(document.write("Hello world\\n");), @response.body - end - end - end - - def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template - [:js, "js"].each do |format| - assert_nothing_raised do - get :render_explicit_html_template, :format => format - assert_equal %(document.write("Hello world\\n");), @response.body - end - end - end - def test_should_implicitly_render_html_template_from_xhr_request - pending do - xhr :get, :render_implicit_html_template_from_xhr_request - assert_equal "XHR!\nHello HTML!", @response.body - end + pending + # xhr :get, :render_implicit_html_template_from_xhr_request + # assert_equal "XHR!\nHello HTML!", @response.body end def test_should_implicitly_render_js_template_without_layout @@ -1151,11 +942,6 @@ class RenderTest < ActionController::TestCase assert_equal 'formatted html erb', @response.body end - def test_should_render_formatted_xml_erb_template - get :formatted_xml_erb, :format => :xml - assert_equal 'passed formatted xml erb', @response.body - end - def test_should_render_formatted_html_erb_template get :formatted_xml_erb assert_equal 'passed formatted html erb', @response.body @@ -1167,31 +953,6 @@ class RenderTest < ActionController::TestCase assert_equal 'passed formatted html erb', @response.body end - def test_should_render_xml_but_keep_custom_content_type - get :render_xml_with_custom_content_type - assert_equal "application/atomsvc+xml", @response.content_type - end - - def test_render_with_default_from_accept_header - xhr :get, :greeting - assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body - end - - def test_render_rjs_with_default - get :delete_with_js - assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body - end - - def test_render_rjs_template_explicitly - get :render_js_with_explicit_template - assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body - end - - def test_rendering_rjs_action_explicitly - get :render_js_with_explicit_action_template - assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body - end - def test_layout_test_with_different_layout get :layout_test_with_different_layout assert_equal "Hello world!", @response.body @@ -1299,28 +1060,6 @@ class RenderTest < ActionController::TestCase assert_equal "The secret is area51\n", @response.body end - def test_update_page - get :update_page - assert_template nil - assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type'] - assert_equal 2, @response.body.split($/).length - end - - def test_update_page_with_instance_variables - get :update_page_with_instance_variables - assert_template nil - assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"] - assert_match /balance/, @response.body - assert_match /\$37/, @response.body - end - - def test_update_page_with_view_method - get :update_page_with_view_method - assert_template nil - assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"] - assert_match /2 people/, @response.body - end - def test_yield_content_for assert_not_deprecated { get :yield_content_for } assert_equal "Putting stuff in the title!\n\nGreat stuff!\n", @response.body @@ -1391,31 +1130,6 @@ class RenderTest < ActionController::TestCase assert_response :forbidden end - def test_rendering_with_location_should_set_header - get :render_with_location - assert_equal "http://example.com", @response.headers["Location"] - end - - def test_rendering_xml_should_call_to_xml_if_possible - get :render_with_to_xml - assert_equal "", @response.body - end - - def test_rendering_with_object_location_should_set_header_with_url_for - ActionController::Routing::Routes.draw do |map| - map.resources :customers - map.connect ':controller/:action/:id' - end - - get :render_with_object_location - assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"] - end - - def test_should_use_implicit_content_type - get :implicit_content_type, :format => 'atom' - assert_equal Mime::ATOM, @response.content_type - end - def test_using_layout_around_block get :render_using_layout_around_block assert_equal "Before (David)\nInside from block\nAfter", @response.body @@ -1446,26 +1160,6 @@ class RenderTest < ActionController::TestCase assert_equal 'partial html', @response.body end - def test_should_render_html_formatted_partial_with_rjs - xhr :get, :partial_as_rjs - assert_equal %(Element.replace("foo", "partial html");), @response.body - end - - def test_should_render_html_formatted_partial_with_rjs_and_js_format - xhr :get, :respond_to_partial_as_rjs - assert_equal %(Element.replace("foo", "partial html");), @response.body - end - - def test_should_render_js_partial - xhr :get, :partial, :format => 'js' - assert_equal 'partial js', @response.body - end - - def test_should_render_with_alternate_default_render - xhr :get, :render_alternate_default - assert_equal %(Element.replace("foo", "partial html");), @response.body - end - def test_partial_only_with_layout get :partial_only_with_layout assert_equal "only partial", @response.body diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb new file mode 100644 index 0000000000..052b4f0b52 --- /dev/null +++ b/actionpack/test/controller/render_xml_test.rb @@ -0,0 +1,81 @@ +require 'abstract_unit' +require 'controller/fake_models' +require 'pathname' + +class TestController < ActionController::Base + protect_from_forgery + + def render_with_location + render :xml => "", :location => "http://example.com", :status => 201 + end + + def render_with_object_location + customer = Customer.new("Some guy", 1) + render :xml => "", :location => customer_url(customer), :status => :created + end + + def render_with_to_xml + to_xmlable = Class.new do + def to_xml + "" + end + end.new + + render :xml => to_xmlable + end + + def formatted_xml_erb + end + + def render_xml_with_custom_content_type + render :xml => "", :content_type => "application/atomsvc+xml" + end +end + +class RenderTest < ActionController::TestCase + tests TestController + + def setup + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + super + @controller.logger = Logger.new(nil) + + @request.host = "www.nextangle.com" + end + + def test_rendering_with_location_should_set_header + get :render_with_location + assert_equal "http://example.com", @response.headers["Location"] + end + + def test_rendering_xml_should_call_to_xml_if_possible + get :render_with_to_xml + assert_equal "", @response.body + end + + def test_rendering_with_object_location_should_set_header_with_url_for + ActionController::Routing::Routes.draw do |map| + map.resources :customers + map.connect ':controller/:action/:id' + end + + get :render_with_object_location + assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"] + end + + def test_should_render_formatted_xml_erb_template + get :formatted_xml_erb, :format => :xml + assert_equal 'passed formatted xml erb', @response.body + end + + def test_should_render_xml_but_keep_custom_content_type + get :render_xml_with_custom_content_type + assert_equal "application/atomsvc+xml", @response.content_type + end + + def test_should_use_implicit_content_type + get :implicit_content_type, :format => 'atom' + assert_equal Mime::ATOM, @response.content_type + end +end \ No newline at end of file diff --git a/actionpack/test/new_base/render_file_test.rb b/actionpack/test/new_base/render_file_test.rb new file mode 100644 index 0000000000..769949be0c --- /dev/null +++ b/actionpack/test/new_base/render_file_test.rb @@ -0,0 +1,110 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") + +module RenderFile + + class BasicController < ActionController::Base + self.view_paths = "." + + def index + render :file => File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world]) + end + + def with_instance_variables + @secret = 'in the sauce' + render :file => File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb') + end + + def without_file_key + render File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world]) + end + + def without_file_key_with_instance_variable + @secret = 'in the sauce' + render File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb') + end + + def relative_path + @secret = 'in the sauce' + render :file => '../fixtures/test/render_file_with_ivar' + end + + def relative_path_with_dot + @secret = 'in the sauce' + render :file => '../fixtures/test/dot.directory/render_file_with_ivar' + end + + def pathname + @secret = 'in the sauce' + render :file => Pathname.new(File.dirname(__FILE__)).join(*%w[.. fixtures test dot.directory render_file_with_ivar.erb]) + end + + def with_locals + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb') + render :file => path, :locals => {:secret => 'in the sauce'} + end + + def without_file_key_with_locals + path = File.expand_path('../fixtures/test/render_file_with_locals.erb') + render path, :locals => {:secret => 'in the sauce'} + end + end + + class TestBasic < SimpleRouteCase + testing RenderFile::BasicController + + def setup + @old_pwd = Dir.pwd + Dir.chdir(File.dirname(__FILE__)) + end + + def teardown + Dir.chdir(@old_pwd) + end + + test "rendering simple template" do + get :index + assert_response "Hello world!" + end + + test "rendering template with ivar" do + get :with_instance_variables + assert_response "The secret is in the sauce\n" + end + + test "rendering path without specifying the :file key" do + get :without_file_key + assert_response "Hello world!" + end + + test "rendering path without specifying the :file key with ivar" do + get :without_file_key_with_instance_variable + assert_response "The secret is in the sauce\n" + end + + test "rendering a relative path" do + get :relative_path + assert_response "The secret is in the sauce\n" + end + + test "rendering a relative path with dot" do + get :relative_path_with_dot + assert_response "The secret is in the sauce\n" + end + + test "rendering a Pathname" do + get :pathname + assert_response "The secret is in the sauce\n" + end + + test "rendering file with locals" do + get :with_locals + assert_response "The secret is in the sauce\n" + end + + test "rendering path without specifying the :file key with locals" do + get :without_file_key_with_locals + assert_response "The secret is in the sauce\n" + end + end + +end \ No newline at end of file diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb index 5d28926cc6..7f627f86ec 100644 --- a/actionpack/test/new_base/render_layout_test.rb +++ b/actionpack/test/new_base/render_layout_test.rb @@ -6,7 +6,8 @@ module ControllerLayouts self.view_paths = [ActionView::Template::FixturePath.new( "layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI", "layouts/override.html.erb" => "Override! <%= yield %>", - "basic.html.erb" => "Hello world!" + "basic.html.erb" => "Hello world!", + "controller_layouts/implicit/layout_false.html.erb" => "hai(layout_false.html.erb)" )] def index @@ -17,6 +18,12 @@ module ControllerLayouts render :template => "basic", :layout => "override" end + def layout_false + render :layout => false + end + + + def builder_override end @@ -56,4 +63,13 @@ module ControllerLayouts get "/controller_layouts/implicit/override" assert_body "Override! Hello world!" end + + class TestLayoutOptions < SimpleRouteCase + testing ControllerLayouts::ImplicitController + + test "rendering with :layout => false leaves out the implicit layout" do + get :layout_false + assert_response "hai(layout_false.html.erb)" + end + end end \ No newline at end of file diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb index 78662dc989..a7302af060 100644 --- a/actionpack/test/new_base/test_helper.rb +++ b/actionpack/test/new_base/test_helper.rb @@ -59,12 +59,28 @@ class Rack::TestCase < ActiveSupport::TestCase @app ||= ActionController::Dispatcher.new end + def self.testing(klass = nil) + if klass + @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '') + else + @testing + end + end + def self.get(url) setup do |test| test.get url end end + def get(thing, *args) + if thing.is_a?(Symbol) + super("#{self.class.testing}/#{thing}") + else + super + end + end + def assert_body(body) assert_equal body, Array.wrap(last_response.body).join end @@ -85,6 +101,14 @@ class Rack::TestCase < ActiveSupport::TestCase end end + def assert_response(body, status = 200, headers = {}) + assert_body body + assert_status status + headers.each do |header, value| + assert_header header, value + end + end + def assert_content_type(type) assert_equal type, last_response.headers["Content-Type"] end From afcbdfc15f919a470e4cfca97fb0084eebd2ab1f Mon Sep 17 00:00:00 2001 From: Peter Marklund Date: Thu, 14 May 2009 09:30:16 +0200 Subject: [PATCH 10/45] Changed ActiveRecord::Base#exists? to invoke find_initial so that it is compatible with, and doesn't lose, :include scopes (references to eager loaded tables) Signed-off-by: Michael Koziarski [#2543 state:committed] --- activerecord/lib/active_record/base.rb | 11 +++-------- activerecord/test/cases/finder_test.rb | 6 ++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index b9ba727a3f..54ec0e841f 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -697,14 +697,9 @@ module ActiveRecord #:nodoc: # Person.exists?(['name LIKE ?', "%#{query}%"]) # Person.exists? def exists?(id_or_conditions = {}) - connection.select_all( - construct_finder_sql( - :select => "#{quoted_table_name}.#{primary_key}", - :conditions => expand_id_conditions(id_or_conditions), - :limit => 1 - ), - "#{name} Exists" - ).size > 0 + find_initial( + :select => "#{quoted_table_name}.#{primary_key}", + :conditions => expand_id_conditions(id_or_conditions)) ? true : false end # Creates an object (or multiple objects) and saves it to the database, if validations pass. diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index ad4588db69..d0d7094e30 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -119,6 +119,12 @@ class FinderTest < ActiveRecord::TestCase Address.new(existing_address.street + "1", existing_address.city, existing_address.country)) end + def test_exists_with_scoped_include + Developer.with_scope(:find => { :include => :projects, :order => "projects.name" }) do + assert Developer.exists? + end + end + def test_find_by_array_of_one_id assert_kind_of(Array, Topic.find([ 1 ])) assert_equal(1, Topic.find([ 1 ]).length) From 29bd8f7b8975bc0442f0b63e7da077f9a3f22dc6 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 May 2009 16:15:18 -0700 Subject: [PATCH 11/45] Simple example for require profiling --- actionpack/examples/simple.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 actionpack/examples/simple.rb diff --git a/actionpack/examples/simple.rb b/actionpack/examples/simple.rb new file mode 100644 index 0000000000..4ecb824688 --- /dev/null +++ b/actionpack/examples/simple.rb @@ -0,0 +1,17 @@ +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" +require 'action_controller' + +class PeopleController < ActionController::Base + def index + head :ok + end +end + +status, headers, body = PeopleController.action(:index).call({ 'rack.input' => StringIO.new('') }) + +puts status +puts headers.to_yaml +puts '---' +body.each do |part| + puts part +end From 5dd29c466c38a1bc395da579fd4b22c5e5a8e9fd Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 13 May 2009 16:15:37 -0700 Subject: [PATCH 12/45] Cherry-picking Active Support extensions --- actionpack/lib/action_dispatch/http/status_codes.rb | 6 ++++-- activesupport/lib/active_support/memoizable.rb | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb index 830de2a6db..5bac842ec1 100644 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ b/actionpack/lib/action_dispatch/http/status_codes.rb @@ -1,3 +1,5 @@ +require 'active_support/inflector' + module ActionDispatch module StatusCodes #:nodoc: STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({ @@ -16,7 +18,7 @@ module ActionDispatch # :created or :not_implemented) into its corresponding HTTP status # code (like 200 or 501). SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) { |hash, (code, message)| - hash[message.gsub(/ /, "").underscore.to_sym] = code + hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code hash }.freeze @@ -37,4 +39,4 @@ module ActionDispatch end end end -end \ No newline at end of file +end diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index edf626802a..fa6db683d4 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/metaclass' +require 'active_support/core_ext/module/aliasing' module ActiveSupport module SafelyMemoizable From c286952050e8fe16b0f6d64ba0687b52cc8f2ae1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 14 May 2009 01:56:07 -0700 Subject: [PATCH 13/45] Minimal base/new_base comparison --- actionpack/examples/minimal.rb | 34 +++++++++++++++++++ actionpack/examples/simple.rb | 17 ---------- .../lib/action_controller/abstract/base.rb | 6 ++-- .../lib/action_controller/abstract/logger.rb | 4 ++- .../lib/action_controller/new_base/http.rb | 5 ++- actionpack/lib/action_controller/routing.rb | 5 +++ 6 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 actionpack/examples/minimal.rb delete mode 100644 actionpack/examples/simple.rb diff --git a/actionpack/examples/minimal.rb b/actionpack/examples/minimal.rb new file mode 100644 index 0000000000..84a8499daf --- /dev/null +++ b/actionpack/examples/minimal.rb @@ -0,0 +1,34 @@ +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" +require 'action_controller' +require 'action_controller/new_base' if ENV['NEW'] +require 'benchmark' + +class BaseController < ActionController::Base + def index + render :text => '' + end +end + +n = (ENV['N'] || 10000).to_i +input = StringIO.new('') + +def call_index(controller, input, n) + n.times do + controller.action(:index).call({ 'rack.input' => input }) + end + + puts controller.name + status, headers, body = controller.action(:index).call({ 'rack.input' => input }) + + puts status + puts headers.to_yaml + puts '---' + body.each do |part| + puts part + end + puts '---' +end + +elapsed = Benchmark.realtime { call_index BaseController, input, n } + +puts "%dms elapsed, %d requests/sec" % [1000 * elapsed, n / elapsed] diff --git a/actionpack/examples/simple.rb b/actionpack/examples/simple.rb deleted file mode 100644 index 4ecb824688..0000000000 --- a/actionpack/examples/simple.rb +++ /dev/null @@ -1,17 +0,0 @@ -$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" -require 'action_controller' - -class PeopleController < ActionController::Base - def index - head :ok - end -end - -status, headers, body = PeopleController.action(:index).call({ 'rack.input' => StringIO.new('') }) - -puts status -puts headers.to_yaml -puts '---' -body.each do |part| - puts part -end diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index c9e1081b23..4b8d953643 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module/attr_internal' + module AbstractController class Error < StandardError; end @@ -89,7 +91,7 @@ module AbstractController # you must handle it by also overriding process_action and # handling the case. def respond_to_action?(action_name) - action_methods.include?(action_name) || respond_to?(:action_missing, true) + action_methods.include?(action_name.to_s) || respond_to?(:action_missing, true) end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb index 5fb78f1755..b154be754b 100644 --- a/actionpack/lib/action_controller/abstract/logger.rb +++ b/actionpack/lib/action_controller/abstract/logger.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute_accessors' + module AbstractController module Logger extend ActiveSupport::DependencyModule @@ -6,4 +8,4 @@ module AbstractController cattr_accessor :logger end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb index fb6041a04e..6852eb200a 100644 --- a/actionpack/lib/action_controller/new_base/http.rb +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -1,3 +1,6 @@ +require 'action_controller/abstract' +require 'active_support/core_ext/module/delegation' + module ActionController class Http < AbstractController::Base abstract! @@ -57,7 +60,7 @@ module ActionController def self.action(name) @actions ||= {} - @actions[name] ||= proc do |env| + @actions[name.to_s] ||= proc do |env| new.call(name, env) end end diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index c0eb61340b..7edd379bc0 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -1,5 +1,10 @@ require 'cgi' require 'uri' +require 'set' + +require 'active_support/core_ext/module/aliasing' +require 'active_support/core_ext/module/attribute_accessors' + require 'action_controller/routing/optimisations' require 'action_controller/routing/routing_ext' require 'action_controller/routing/route' From 8fac2c88cae0f2fd42fad3c2c2c6c860df14d629 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 14 May 2009 15:30:35 -0700 Subject: [PATCH 14/45] Cleaning up more render tests --- actionpack/lib/action_controller/abstract.rb | 3 + .../lib/action_controller/abstract/base.rb | 9 +++ actionpack/lib/action_view.rb | 1 + .../lib/action_view/helpers/tag_helper.rb | 2 +- actionpack/test/controller/render_test.rb | 5 ++ .../test/new_base/render_action_test.rb | 17 ++++- .../test/new_base/render_layout_test.rb | 2 - .../test/new_base/render_partial_test.rb | 27 +++++++ .../test/new_base/render_template_test.rb | 76 ++++++++++++------- actionpack/test/new_base/render_xml_test.rb | 11 +++ actionpack/test/new_base/test_helper.rb | 2 +- 11 files changed, 122 insertions(+), 33 deletions(-) create mode 100644 actionpack/test/new_base/render_partial_test.rb create mode 100644 actionpack/test/new_base/render_xml_test.rb diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb index 3f5c4a185f..48e33282ec 100644 --- a/actionpack/lib/action_controller/abstract.rb +++ b/actionpack/lib/action_controller/abstract.rb @@ -1,3 +1,6 @@ +require "active_support/core_ext/module/attr_internal" +require "active_support/core_ext/module/delegation" + module AbstractController autoload :Base, "action_controller/abstract/base" autoload :Callbacks, "action_controller/abstract/callbacks" diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index c9e1081b23..8f2bfb5711 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -23,6 +23,15 @@ module AbstractController end alias_method :abstract?, :abstract + + def inherited(klass) + ::AbstractController::Base.subclasses << klass.to_s + super + end + + def subclasses + @subclasses ||= [] + end def internal_methods controller = self diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index c3786af439..94138097e3 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -24,6 +24,7 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" $:.unshift activesupport_path if File.directory?(activesupport_path) require 'active_support' +require 'active_support/core_ext/class/attribute_accessors' require File.join(File.dirname(__FILE__), "action_pack") diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index af8c4d5e21..66d7592874 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -9,7 +9,7 @@ module ActionView include ERB::Util BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked).to_set - BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym)) + BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attr| attr.to_sym }) # Returns an empty HTML tag of type +name+ which by default is XHTML # compliant. Set +open+ to true to create an open tag compatible diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 469e8601d0..a750f018b8 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -262,6 +262,7 @@ class TestController < ActionController::Base render :action => "hello_world" end + # :ported: def builder_layout_test render :action => "hello", :layout => "layouts/builder" end @@ -271,6 +272,7 @@ class TestController < ActionController::Base render :action => "hello_world_container" end + # :ported: def partials_list @test_unchanged = 'hello' @customers = [ Customer.new("david"), Customer.new("mary") ] @@ -860,6 +862,7 @@ class RenderTest < ActionController::TestCase assert_equal "application/xml", @response.content_type end + # :ported: def test_render_xml_as_string_template get :render_xml_hello_as_string_template assert_equal "\n

Hello David

\n

This is grand!

\n\n", @response.body @@ -872,11 +875,13 @@ class RenderTest < ActionController::TestCase assert_equal "

This is grand!

\n", @response.body end + # :move: test in AV def test_render_xml_with_partial get :builder_partial_test assert_equal "\n \n\n", @response.body end + # :ported: def test_layout_rendering get :layout_test assert_equal "Hello world!", @response.body diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb index 348d70381b..f25faee433 100644 --- a/actionpack/test/new_base/render_action_test.rb +++ b/actionpack/test/new_base/render_action_test.rb @@ -131,8 +131,10 @@ module RenderActionWithApplicationLayout # Set the view path to an application view structure with layouts self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new( "render_action_with_application_layout/basic/hello_world.html.erb" => "Hello World!", + "render_action_with_application_layout/basic/hello.html.builder" => "xml.p 'Omg'", "layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI", - "layouts/greetings.html.erb" => "Greetings <%= yield %> Bai" + "layouts/greetings.html.erb" => "Greetings <%= yield %> Bai", + "layouts/builder.html.builder" => "xml.html do\n xml << yield\nend" )] def hello_world @@ -154,6 +156,10 @@ module RenderActionWithApplicationLayout def hello_world_with_custom_layout render :action => "hello_world", :layout => "greetings" end + + def with_builder_and_layout + render :action => "hello", :layout => "builder" + end end class TestDefaultLayout < SimpleRouteCase @@ -199,6 +205,15 @@ module RenderActionWithApplicationLayout assert_status 200 end + class TestLayout < SimpleRouteCase + testing BasicController + + test "builder works with layouts" do + get :with_builder_and_layout + assert_response "\n

Omg

\n\n" + end + end + end module RenderActionWithControllerLayout diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb index 7f627f86ec..dc858b4f5c 100644 --- a/actionpack/test/new_base/render_layout_test.rb +++ b/actionpack/test/new_base/render_layout_test.rb @@ -22,8 +22,6 @@ module ControllerLayouts render :layout => false end - - def builder_override end diff --git a/actionpack/test/new_base/render_partial_test.rb b/actionpack/test/new_base/render_partial_test.rb new file mode 100644 index 0000000000..3a300afe5c --- /dev/null +++ b/actionpack/test/new_base/render_partial_test.rb @@ -0,0 +1,27 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") + +module RenderPartial + + class BasicController < ActionController::Base + + self.view_paths = [ActionView::Template::FixturePath.new( + "render_partial/basic/_basic.html.erb" => "OMG!", + "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>" + )] + + def changing + @test_unchanged = 'hello' + render :action => "basic" + end + end + + class TestPartial < SimpleRouteCase + testing BasicController + + test "rendering a partial in ActionView doesn't pull the ivars again from the controller" do + get :changing + assert_response("goodbyeOMG!goodbye") + end + end + +end \ No newline at end of file diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb index c09eeb1926..6c50ae4203 100644 --- a/actionpack/test/new_base/render_template_test.rb +++ b/actionpack/test/new_base/render_template_test.rb @@ -4,14 +4,19 @@ module RenderTemplate class WithoutLayoutController < ActionController::Base self.view_paths = [ActionView::Template::FixturePath.new( - "test/basic.html.erb" => "Hello from basic.html.erb", - "shared.html.erb" => "Elastica", - "locals.html.erb" => "The secret is <%= secret %>" + "test/basic.html.erb" => "Hello from basic.html.erb", + "shared.html.erb" => "Elastica", + "locals.html.erb" => "The secret is <%= secret %>", + "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend" )] def index render :template => "test/basic" end + + def index_without_key + render "test/basic" + end def in_top_directory render :template => 'shared' @@ -21,41 +26,56 @@ module RenderTemplate render :template => '/shared' end + def in_top_directory_with_slash_without_key + render '/shared' + end + def with_locals render :template => "locals", :locals => { :secret => 'area51' } end + + def builder_template + render :template => "xml_template" + end end class TestWithoutLayout < SimpleRouteCase - describe "rendering a normal template with full path without layout" + testing RenderTemplate::WithoutLayoutController - get "/render_template/without_layout" - assert_body "Hello from basic.html.erb" - assert_status 200 - end - - class TestTemplateRenderInTopDirectory < SimpleRouteCase - describe "rendering a template not in a subdirectory" + test "rendering a normal template with full path without layout" do + get :index + assert_response "Hello from basic.html.erb" + end - get "/render_template/without_layout/in_top_directory" - assert_body "Elastica" - assert_status 200 - end - - class TestTemplateRenderInTopDirectoryWithSlash < SimpleRouteCase - describe "rendering a template not in a subdirectory with a leading slash" + test "rendering a normal template with full path without layout without key" do + get :index_without_key + assert_response "Hello from basic.html.erb" + end - get "/render_template/without_layout/in_top_directory_with_slash" - assert_body "Elastica" - assert_status 200 - end - - class TestTemplateRenderWithLocals < SimpleRouteCase - describe "rendering a template with local variables" + test "rendering a template not in a subdirectory" do + get :in_top_directory + assert_response "Elastica" + end - get "/render_template/without_layout/with_locals" - assert_body "The secret is area51" - assert_status 200 + test "rendering a template not in a subdirectory with a leading slash" do + get :in_top_directory_with_slash + assert_response "Elastica" + end + + test "rendering a template not in a subdirectory with a leading slash without key" do + get :in_top_directory_with_slash_without_key + assert_response "Elastica" + end + + test "rendering a template with local variables" do + get :with_locals + assert_response "The secret is area51" + end + + test "rendering a builder template" do + get :builder_template + assert_response "\n

Hello

\n\n" + end end class WithLayoutController < ::ApplicationController diff --git a/actionpack/test/new_base/render_xml_test.rb b/actionpack/test/new_base/render_xml_test.rb new file mode 100644 index 0000000000..e6c40b1533 --- /dev/null +++ b/actionpack/test/new_base/render_xml_test.rb @@ -0,0 +1,11 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") + +module RenderXml + + # This has no layout and it works + class BasicController < ActionController::Base + self.view_paths = [ActionView::Template::FixturePath.new( + "render_xml/basic/with_render_erb" => "Hello world!" + )] + end +end \ No newline at end of file diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb index a7302af060..ec7dbffaae 100644 --- a/actionpack/test/new_base/test_helper.rb +++ b/actionpack/test/new_base/test_helper.rb @@ -46,7 +46,7 @@ class Rack::TestCase < ActiveSupport::TestCase ActionController::Routing.use_controllers!(controllers) # Move into a bootloader - AbstractController::Base.subclasses.each do |klass| + ActionController::Base.subclasses.each do |klass| klass = klass.constantize next unless klass < AbstractController::Layouts klass.class_eval do From da65320433088548bc4cff33758e5acd71fd137a Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 14 May 2009 17:25:10 -0700 Subject: [PATCH 15/45] Got new base to pass controller/base_test.rb, implemented method_missing action semantics in compatibility mode, and fixed a few action_missing bugs. --- .../lib/action_controller/abstract/base.rb | 10 ++++-- .../lib/action_controller/abstract/logger.rb | 33 +++++++++++++++++++ .../new_base/compatibility.rb | 15 +++++++++ .../new_base/hide_actions.rb | 4 +-- .../lib/action_controller/new_base/http.rb | 5 --- actionpack/lib/action_controller/routing.rb | 1 + actionpack/test/abstract_unit.rb | 2 +- actionpack/test/controller/base_test.rb | 2 +- 8 files changed, 61 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index 8f2bfb5711..483356a4be 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -67,6 +67,8 @@ module AbstractController end def process(action_name) + action_name = action_name.to_s + unless respond_to_action?(action_name) raise ActionNotFound, "The action '#{action_name}' could not be found" end @@ -82,13 +84,17 @@ module AbstractController self.class.action_methods end + def action_method?(action) + action_methods.include?(action) + end + # It is possible for respond_to?(action_name) to be false and # respond_to?(:action_missing) to be false if respond_to_action? # is overridden in a subclass. For instance, ActionController::Base # overrides it to include the case where a template matching the # action_name is found. def process_action - if respond_to?(action_name) then send(action_name) + if action_method?(action_name) then send(action_name) elsif respond_to?(:action_missing, true) then action_missing(action_name) end end @@ -98,7 +104,7 @@ module AbstractController # you must handle it by also overriding process_action and # handling the case. def respond_to_action?(action_name) - action_methods.include?(action_name) || respond_to?(:action_missing, true) + action_method?(action_name) || respond_to?(:action_missing, true) end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb index 5fb78f1755..d0603a4ad7 100644 --- a/actionpack/lib/action_controller/abstract/logger.rb +++ b/actionpack/lib/action_controller/abstract/logger.rb @@ -2,8 +2,41 @@ module AbstractController module Logger extend ActiveSupport::DependencyModule + class DelayedLog + def initialize(&blk) + @blk = blk + end + + def to_s + @blk.call + end + alias to_str to_s + end + included do cattr_accessor :logger end + + def process(action) + ret = super + + if logger + log = DelayedLog.new do + "\n\nProcessing #{self.class.name}\##{action_name} " \ + "to #{request.formats} " \ + "(for #{request_origin}) [#{request.method.to_s.upcase}]" + end + + logger.info(log) + end + + ret + end + + def request_origin + # this *needs* to be cached! + # otherwise you'd get different results if calling it more than once + @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}" + end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb index d17f498b60..993e571aba 100644 --- a/actionpack/lib/action_controller/new_base/compatibility.rb +++ b/actionpack/lib/action_controller/new_base/compatibility.rb @@ -42,6 +42,9 @@ module ActionController # Controls the resource action separator cattr_accessor :resource_action_separator self.resource_action_separator = "/" + + cattr_accessor :use_accept_header + self.use_accept_header = true end module ClassMethods @@ -66,6 +69,18 @@ module ActionController super end + + def respond_to_action?(action_name) + if respond_to?(:method_missing) && !respond_to?(:action_missing) + self.class.class_eval do + private + def action_missing(name, *args) + method_missing(name.to_sym, *args) + end + end + end + super + end def _layout_for_name(name) name &&= name.sub(%r{^/?layouts/}, '') diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb index d1857a9169..a29b09a893 100644 --- a/actionpack/lib/action_controller/new_base/hide_actions.rb +++ b/actionpack/lib/action_controller/new_base/hide_actions.rb @@ -12,8 +12,8 @@ module ActionController private - def respond_to_action?(action_name) - !hidden_actions.include?(action_name) && (super || respond_to?(:method_missing)) + def action_method?(action_name) + !hidden_actions.include?(action_name) && super end module ClassMethods diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb index fb6041a04e..f3a60b3bf8 100644 --- a/actionpack/lib/action_controller/new_base/http.rb +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -21,11 +21,6 @@ module ActionController # :api: public def controller_path() self.class.controller_path end - # :api: private - def self.internal_methods - ActionController::Http.public_instance_methods(true) - end - # :api: private def self.action_names() action_methods end diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index c0eb61340b..06a07a4d0a 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -1,5 +1,6 @@ require 'cgi' require 'uri' +require 'set' require 'action_controller/routing/optimisations' require 'action_controller/routing/routing_ext' require 'action_controller/routing/route' diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 825ac9a46c..7982f06545 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -37,7 +37,7 @@ ActionController::Base.session_store = nil # Register danish language for testing I18n.backend.store_translations 'da', {} I18n.backend.store_translations 'pt-BR', {} -ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort +ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') ActionController::Base.view_paths = FIXTURE_LOAD_PATH diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index a09db95d7d..3a4cdb81d9 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -117,7 +117,7 @@ class PerformActionTest < ActionController::TestCase end def method_missing(method, *args) - @logged << args.first + @logged << args.first.to_s end end From eb021707f53be46140b55a48e5ef03ed0577a45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 1 Apr 2009 12:44:56 +0200 Subject: [PATCH 16/45] Allow strings to be sent as collection to select. Signed-off-by: Michael Koziarski --- .../helpers/form_options_helper.rb | 2 ++ .../test/template/form_options_helper_test.rb | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 6b385ef77d..6adbab175f 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -230,6 +230,8 @@ module ActionView # # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. def options_for_select(container, selected = nil) + return container if String === container + container = container.to_a if Hash === container selected, disabled = extract_selected_and_disabled(selected) diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 78db87971b..73624406be 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -80,6 +80,14 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_string_options_for_select + options = "" + assert_dom_equal( + options, + options_for_select(options) + ) + end + def test_array_options_for_select assert_dom_equal( "\n\n", @@ -324,6 +332,20 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_under_fields_for_with_string_and_given_prompt + @post = Post.new + options = "" + + fields_for :post, @post do |f| + concat f.select(:category, options, :prompt => 'The prompt') + end + + assert_dom_equal( + "", + output_buffer + ) + end + def test_select_with_blank @post = Post.new @post.category = "" From 7e10504bdeab14ea70a942110a1b1ef6d8467ed3 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 15 May 2009 15:57:12 -0700 Subject: [PATCH 17/45] Refactored AbstractController to provide better hook points for overriding aspects of action dispatching --- .../lib/action_controller/abstract/base.rb | 27 ++++++++++--------- .../action_controller/abstract/callbacks.rb | 4 +-- .../lib/action_controller/new_base/base.rb | 16 ++++++++--- .../new_base/compatibility.rb | 18 +++++-------- .../abstract_controller_test.rb | 7 +++-- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index f2db201063..1f2f096dae 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -69,14 +69,13 @@ module AbstractController end def process(action_name) - action_name = action_name.to_s + @_action_name = action_name = action_name.to_s - unless respond_to_action?(action_name) + unless action_name = method_for_action(action_name) raise ActionNotFound, "The action '#{action_name}' could not be found" end - - @_action_name = action_name - process_action + + process_action(action_name) self end @@ -95,18 +94,22 @@ module AbstractController # is overridden in a subclass. For instance, ActionController::Base # overrides it to include the case where a template matching the # action_name is found. - def process_action - if action_method?(action_name) then send(action_name) - elsif respond_to?(:action_missing, true) then action_missing(action_name) - end + def process_action(method_name) + send(method_name) end - + + def _handle_action_missing + action_missing(@_action_name) + end + # Override this to change the conditions that will raise an # ActionNotFound error. If you accept a difference case, # you must handle it by also overriding process_action and # handling the case. - def respond_to_action?(action_name) - action_method?(action_name) || respond_to?(:action_missing, true) + def method_for_action(action_name) + if action_method?(action_name) then action_name + elsif respond_to?(:action_missing, true) then "_handle_action_missing" + end end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb index 3aff83a209..51b968c694 100644 --- a/actionpack/lib/action_controller/abstract/callbacks.rb +++ b/actionpack/lib/action_controller/abstract/callbacks.rb @@ -8,8 +8,8 @@ module AbstractController define_callbacks :process_action, "response_body" end - def process_action - _run_process_action_callbacks(action_name) do + def process_action(method_name) + _run_process_action_callbacks(method_name) do super end end diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 1adcc9c71f..3ee17769a8 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -114,14 +114,22 @@ module ActionController super(url, status) end - def process_action + def process_action(method_name) ret = super render if response_body.nil? ret end - - def respond_to_action?(action_name) - super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) + + def _implicit_render + render + end + + def method_for_action(action_name) + super || begin + if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) + "_implicit_render" + end + end end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb index 993e571aba..9884ed12e5 100644 --- a/actionpack/lib/action_controller/new_base/compatibility.rb +++ b/actionpack/lib/action_controller/new_base/compatibility.rb @@ -69,17 +69,13 @@ module ActionController super end - - def respond_to_action?(action_name) - if respond_to?(:method_missing) && !respond_to?(:action_missing) - self.class.class_eval do - private - def action_missing(name, *args) - method_missing(name.to_sym, *args) - end - end - end - super + + def _handle_method_missing + method_missing(@_action_name.to_sym) + end + + def method_for_action(action_name) + super || (respond_to?(:method_missing) && "_handle_method_missing") end def _layout_for_name(name) diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb index 689aa99fd8..9c028e7d1e 100644 --- a/actionpack/test/abstract_controller/abstract_controller_test.rb +++ b/actionpack/test/abstract_controller/abstract_controller_test.rb @@ -201,11 +201,10 @@ module AbstractController def fail() self.response_body = "fail" end private - - def respond_to_action?(action_name) - action_name.to_s != "fail" + + def method_for_action(action_name) + action_name.to_s != "fail" && action_name end - end class TestRespondToAction < ActiveSupport::TestCase From 5a45446cff0daf4ca747257a8779dcd5d9cae1d7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Fri, 15 May 2009 17:49:11 -0700 Subject: [PATCH 18/45] Ported Rescuable to new base --- .../action_controller/base/chained/filters.rb | 2 +- .../action_controller/dispatch/middlewares.rb | 1 + actionpack/lib/action_controller/new_base.rb | 1 + .../lib/action_controller/new_base/base.rb | 50 +++++++++-------- .../new_base/compatibility.rb | 13 +++++ .../lib/action_controller/new_base/http.rb | 4 +- .../action_controller/new_base/rescuable.rb | 53 +++++++++++++++++++ .../lib/action_controller/new_base/testing.rb | 2 +- actionpack/test/abstract_unit2.rb | 12 ++++- 9 files changed, 111 insertions(+), 27 deletions(-) create mode 100644 actionpack/lib/action_controller/new_base/rescuable.rb diff --git a/actionpack/lib/action_controller/base/chained/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb index 9022b8b279..98fe306fd5 100644 --- a/actionpack/lib/action_controller/base/chained/filters.rb +++ b/actionpack/lib/action_controller/base/chained/filters.rb @@ -160,7 +160,7 @@ module ActionController #:nodoc: def convert_only_and_except_options_to_sets_of_strings(opts) [:only, :except].each do |key| if values = opts[key] - opts[key] = Array(values).map(&:to_s).to_set + opts[key] = Array(values).map {|val| val.to_s }.to_set end end end diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index f99637b109..0e4ab6fa39 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -6,6 +6,7 @@ use "ActionDispatch::Failsafe" use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local } use "ActionDispatch::Rescue", lambda { controller = (::ApplicationController rescue ActionController::Base) + # TODO: Replace with controller.action(:_rescue_action) controller.method(:rescue_action) } diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb index 1f215bb6f1..bc47713529 100644 --- a/actionpack/lib/action_controller/new_base.rb +++ b/actionpack/lib/action_controller/new_base.rb @@ -7,6 +7,7 @@ module ActionController autoload :Rails2Compatibility, "action_controller/new_base/compatibility" autoload :Redirector, "action_controller/new_base/redirector" autoload :Renderer, "action_controller/new_base/renderer" + autoload :Rescue, "action_controller/new_base/rescuable" autoload :Testing, "action_controller/new_base/testing" autoload :UrlFor, "action_controller/new_base/url_for" diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 3ee17769a8..c25ffd5c84 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -12,14 +12,40 @@ module ActionController include ActionController::Renderer include ActionController::Layouts include ActionController::ConditionalGet - + # Legacy modules include SessionManagement include ActionDispatch::StatusCodes - + # Rails 2.x compatibility include ActionController::Rails2Compatibility - + + # TODO: Extract into its own module + # This should be moved together with other normalizing behavior + module ImplicitRender + def process_action(method_name) + ret = super + render if response_body.nil? + ret + end + + def _implicit_render + render + end + + def method_for_action(action_name) + super || begin + if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) + "_implicit_render" + end + end + end + end + + include ImplicitRender + + include ActionController::Rescue + def self.inherited(klass) ::ActionController::Base.subclasses << klass.to_s super @@ -113,23 +139,5 @@ module ActionController super(url, status) end - - def process_action(method_name) - ret = super - render if response_body.nil? - ret - end - - def _implicit_render - render - end - - def method_for_action(action_name) - super || begin - if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) - "_implicit_render" - end - end - end end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb index 9884ed12e5..0a283887b6 100644 --- a/actionpack/lib/action_controller/new_base/compatibility.rb +++ b/actionpack/lib/action_controller/new_base/compatibility.rb @@ -45,6 +45,14 @@ module ActionController cattr_accessor :use_accept_header self.use_accept_header = true + + cattr_accessor :page_cache_directory + self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : "" + + cattr_reader :cache_store + + cattr_accessor :consider_all_requests_local + self.consider_all_requests_local = true end module ClassMethods @@ -53,6 +61,11 @@ module ActionController def rescue_action(env) raise env["action_dispatch.rescue.exception"] end + + # Defines the storage option for cached fragments + def cache_store=(store_option) + @@cache_store = ActiveSupport::Cache.lookup_store(store_option) + end end def initialize(*) diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb index e9a1d5b12f..8891a2a8c3 100644 --- a/actionpack/lib/action_controller/new_base/http.rb +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -48,8 +48,6 @@ module ActionController @_response = ActionDispatch::Response.new @_response.request = request process(name) - @_response.body = response_body - @_response.prepare! to_rack end @@ -62,6 +60,8 @@ module ActionController # :api: private def to_rack + @_response.body = response_body + @_response.prepare! @_response.to_a end end diff --git a/actionpack/lib/action_controller/new_base/rescuable.rb b/actionpack/lib/action_controller/new_base/rescuable.rb new file mode 100644 index 0000000000..29ffe19d5f --- /dev/null +++ b/actionpack/lib/action_controller/new_base/rescuable.rb @@ -0,0 +1,53 @@ +module ActionController #:nodoc: + # Actions that fail to perform as expected throw exceptions. These + # exceptions can either be rescued for the public view (with a nice + # user-friendly explanation) or for the developers view (with tons of + # debugging information). The developers view is already implemented by + # the Action Controller, but the public view should be tailored to your + # specific application. + # + # The default behavior for public exceptions is to render a static html + # file with the name of the error code thrown. If no such file exists, an + # empty response is sent with the correct status code. + # + # You can override what constitutes a local request by overriding the + # local_request? method in your own controller. Custom rescue + # behavior is achieved by overriding the rescue_action_in_public + # and rescue_action_locally methods. + module Rescue + extend ActiveSupport::DependencyModule + + included do + include ActiveSupport::Rescuable + end + + module ClassMethods + # This can be removed once we can move action(:_rescue_action) into middlewares.rb + # Currently, it does controller.method(:rescue_action), which is hiding the implementation + # difference between the old and new base. + def rescue_action(env) + action(:_rescue_action).call(env) + end + end + + attr_internal :rescued_exception + + private + + def method_for_action(action_name) + return action_name if self.rescued_exception = request.env.delete("action_dispatch.rescue.exception") + super + end + + def _rescue_action + rescue_with_handler(rescued_exception) || raise(rescued_exception) + end + + def process_action(*) + super + rescue Exception => exception + self.rescued_exception = exception + _rescue_action + end + end +end diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb index 106990b9ba..b39d8d539d 100644 --- a/actionpack/lib/action_controller/new_base/testing.rb +++ b/actionpack/lib/action_controller/new_base/testing.rb @@ -7,7 +7,7 @@ module ActionController @_response = response @_response.request = request ret = process(request.parameters[:action]) - @_response.body = self.response_body + @_response.body = self.response_body || " " @_response.prepare! set_test_assigns ret diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb index 932f594ad2..519e6bea36 100644 --- a/actionpack/test/abstract_unit2.rb +++ b/actionpack/test/abstract_unit2.rb @@ -11,11 +11,19 @@ require 'action_controller/new_base' require 'fixture_template' require 'action_controller/testing/process2' require 'action_view/test_case' +require 'action_controller/testing/integration' +require 'active_support/dependencies' + +ActiveSupport::Dependencies.hook! FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') module ActionController - + Base.session = { + :key => '_testing_session', + :secret => '8273f16463985e2b3747dc25e30f2528' +} + class ActionControllerError < StandardError #:nodoc: end @@ -126,6 +134,6 @@ module ActionController "Expected no partials to be rendered" end end - end + end end end From a6d8ca0f0e65ce509793713cb1efe4ab721b9eb4 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 16 May 2009 17:02:43 +0200 Subject: [PATCH 19/45] Include guides directory in the rails gem --- railties/Rakefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/railties/Rakefile b/railties/Rakefile index 133a603ed6..69c1ca762a 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -249,7 +249,7 @@ def copy_with_rewritten_ruby_path(src_file, dest_file) end desc 'Generate guides (for authors), use ONLY=foo to process just "foo.textile"' -task :guides do +task :generate_guides do ENV["WARN_BROKEN_LINKS"] = "1" # authors can't disable this ruby "guides/rails_guides.rb" end @@ -298,6 +298,7 @@ PKG_FILES = FileList[ 'doc/**/*', 'dispatches/**/*', 'environments/**/*', + 'guides/**/*', 'helpers/**/*', 'generators/**/*', 'html/**/*', @@ -324,7 +325,7 @@ spec = Gem::Specification.new do |s| s.rdoc_options << '--exclude' << '.' s.has_rdoc = false - s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')} + s.files = PKG_FILES.to_a.delete_if {|f| f =~ %r{\.svn|guides/output}} s.require_path = 'lib' s.bindir = "bin" # Use these for applications. s.executables = ["rails"] @@ -350,7 +351,7 @@ task :pgem => [:gem] do end desc "Publish the guides" -task :pguides => :guides do +task :pguides => :generate_guides do require 'rake/contrib/sshpublisher' mkdir_p 'pkg' `tar -czf pkg/guides.gz guides/output` From 7f318c3ec535afe53733c55cd0ecaccc16a8b944 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sat, 16 May 2009 14:15:26 -0400 Subject: [PATCH 20/45] Instead of checking Rails.env.test? in Failsafe middleware, check env["rails.raise_exceptions"] --- actionpack/lib/action_dispatch/middleware/failsafe.rb | 5 ++--- actionpack/test/new_base/render_action_test.rb | 6 ++++-- actionpack/test/new_base/render_test.rb | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb index 836098482c..389accbc36 100644 --- a/actionpack/lib/action_dispatch/middleware/failsafe.rb +++ b/actionpack/lib/action_dispatch/middleware/failsafe.rb @@ -10,9 +10,8 @@ module ActionDispatch def call(env) @app.call(env) rescue Exception => exception - # Reraise exception in test environment - if defined?(Rails) && Rails.env.test? - raise exception + if env["rails.raise_exceptions"] + raise else failsafe_response(exception) end diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb index f25faee433..96666077d2 100644 --- a/actionpack/test/new_base/render_action_test.rb +++ b/actionpack/test/new_base/render_action_test.rb @@ -92,7 +92,7 @@ module RenderAction test "raises an exception when requesting a layout and none exist" do assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do - get "/render_action/basic/hello_world_with_layout" + get "/render_action/basic/hello_world_with_layout", {}, "rails.raise_exceptions" => true end end end @@ -117,7 +117,9 @@ module RenderAction describe "rendering a normal template with full path with layout => 'greetings'" test "raises an exception when requesting a layout that does not exist" do - assert_raise(ActionView::MissingTemplate) { get "/render_action/basic/hello_world_with_custom_layout" } + assert_raise(ActionView::MissingTemplate) do + get "/render_action/basic/hello_world_with_custom_layout", {}, "rails.raise_exceptions" => true + end end end diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb index b1867fdcc2..16578fbc82 100644 --- a/actionpack/test/new_base/render_test.rb +++ b/actionpack/test/new_base/render_test.rb @@ -48,7 +48,7 @@ module Render test "raises an exception" do assert_raises(AbstractController::DoubleRenderError) do - get "/render/double_render" + get "/render/double_render", {}, "rails.raise_exceptions" => true end end end @@ -58,13 +58,13 @@ module Render test "raises an exception when a method of Object is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/clone" + get "/render/blank_render/clone", {}, "rails.raise_exceptions" => true end end test "raises an exception when a private method is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/secretz" + get "/render/blank_render/secretz", {}, "rails.raise_exceptions" => true end end end From 59c4d9a5b40dca45b095430d43c04d6c6541992d Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sat, 16 May 2009 14:18:10 -0400 Subject: [PATCH 21/45] Changelog --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 204f5ae272..c1dc6f2ab4 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Edge* +* Instead of checking Rails.env.test? in Failsafe middleware, check env["rails.raise_exceptions"] [Bryan Helmkamp] + * Fixed that TestResponse.cookies was returning cookies unescaped #1867 [Doug McInnes] From 8e6a18d8672f7efe6ef79b49185e4a6a23e4e547 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 16 May 2009 12:09:25 -0700 Subject: [PATCH 22/45] Get AR CI passing again by requiring the entire core_ext Note that this includes Time and Date; we should really figure out what parts of core_ext are really required for AR and require just those. --- activerecord/lib/active_record.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 2d98239052..b5c17cb23b 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -25,6 +25,9 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' +# TODO: Figure out what parts of AS are *actually* required and use those +require 'active_support/core_ext' + module ActiveRecord # TODO: Review explicit loads to see if they will automatically be handled by the initilizer. def self.load_all! From db1bf3650d7450811f5dfddc5c5163a70683e37a Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 16 May 2009 12:13:41 -0700 Subject: [PATCH 23/45] Fix ActionMailer Symbol#to_proc instance --- actionpack/lib/action_view/template/handlers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index 0590372d09..faf54b9fe5 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -33,7 +33,7 @@ module ActionView #:nodoc: end def template_handler_extensions - @@template_handlers.keys.map(&:to_s).sort + @@template_handlers.keys.map {|key| key.to_s }.sort end def registered_template_handler(extension) From 4fa871654dc6e591c08cbc53e7eac2e008056fee Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 16 May 2009 12:28:25 -0700 Subject: [PATCH 24/45] Get Railties passing again --- railties/builtin/rails_info/rails/info.rb | 10 +++++++--- railties/lib/initializer.rb | 2 +- railties/lib/rails/plugin/loader.rb | 12 ++++++------ railties/lib/rails/plugin/locator.rb | 2 +- .../generators/applications/app/template_runner.rb | 2 +- .../generators/components/model/templates/model.rb | 2 +- railties/lib/tasks/gems.rake | 8 ++++---- railties/test/rails_info_test.rb | 2 ++ 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/railties/builtin/rails_info/rails/info.rb b/railties/builtin/rails_info/rails/info.rb index 0dd1c090c1..fdacc469f5 100644 --- a/railties/builtin/rails_info/rails/info.rb +++ b/railties/builtin/rails_info/rails/info.rb @@ -1,9 +1,13 @@ +require "active_support/core_ext/object/misc" +require "cgi" +require "active_support/core_ext/cgi" + module Rails module Info mattr_accessor :properties class << (@@properties = []) def names - map &:first + map {|val| val.first } end def value_for(property_name) @@ -53,7 +57,7 @@ module Rails alias inspect to_s def to_html - returning table = '' do + (table = '
').tap do properties.each do |(name, value)| table << %() formatted_value = if value.kind_of?(Array) @@ -108,7 +112,7 @@ module Rails end property 'Middleware' do - ActionController::Dispatcher.middleware.active.map(&:inspect) + ActionController::Dispatcher.middleware.active.map {|middle| middle.inspect } end # The Rails Git revision, if it's checked out into vendor/rails. diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 40000f0dfd..e4d7589aba 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -311,7 +311,7 @@ module Rails end def check_for_unbuilt_gems - unbuilt_gems = @configuration.gems.select(&:frozen?).reject(&:built?) + unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? } if unbuilt_gems.size > 0 # don't print if the gems:build rake tasks are being run unless $gems_build_rake_task diff --git a/railties/lib/rails/plugin/loader.rb b/railties/lib/rails/plugin/loader.rb index 66e01d70da..bc22dfc591 100644 --- a/railties/lib/rails/plugin/loader.rb +++ b/railties/lib/rails/plugin/loader.rb @@ -24,7 +24,7 @@ module Rails # Returns the plugins that are in engine-form (have an app/ directory) def engines - @engines ||= plugins.select(&:engine?) + @engines ||= plugins.select {|plugin| plugin.engine? } end # Returns all the plugins that could be found by the current locators. @@ -66,7 +66,7 @@ module Rails end def engine_metal_paths - engines.collect(&:metal_path) + engines.collect {|engine| engine.metal_path } end protected @@ -79,18 +79,18 @@ module Rails end def add_engine_routing_configurations - engines.select(&:routed?).collect(&:routing_file).each do |routing_file| + engines.select {|engine| engine.routed? }.map {|engine| engine.routing_file }.each do |routing_file| ActionController::Routing::Routes.add_configuration_file(routing_file) end end def add_engine_controller_paths - ActionController::Routing.controller_paths += engines.collect(&:controller_path) + ActionController::Routing.controller_paths += engines.collect {|engine| engine.controller_path } end def add_engine_view_paths # reverse it such that the last engine can overwrite view paths from the first, like with routes - paths = ActionView::PathSet.new(engines.collect(&:view_path).reverse) + paths = ActionView::PathSet.new(engines.collect {|engine| engine.view_path }.reverse) ActionController::Base.view_paths.concat(paths) ActionMailer::Base.view_paths.concat(paths) if configuration.frameworks.include?(:action_mailer) end @@ -170,7 +170,7 @@ module Rails # so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is # non empty, we load the named plugins in the order specified. def registered_plugin_names - configuration.plugins ? configuration.plugins.map(&:to_s) : nil + configuration.plugins ? configuration.plugins.map {|plugin| plugin.to_s } : nil end def loaded?(plugin_name) diff --git a/railties/lib/rails/plugin/locator.rb b/railties/lib/rails/plugin/locator.rb index a6fc388a8e..1057c004e0 100644 --- a/railties/lib/rails/plugin/locator.rb +++ b/railties/lib/rails/plugin/locator.rb @@ -25,7 +25,7 @@ module Rails end def plugin_names - plugins.map(&:name) + plugins.map {|plugin| plugin.name } end end diff --git a/railties/lib/rails_generator/generators/applications/app/template_runner.rb b/railties/lib/rails_generator/generators/applications/app/template_runner.rb index 3b49b1fa92..0e24d11950 100644 --- a/railties/lib/rails_generator/generators/applications/app/template_runner.rb +++ b/railties/lib/rails_generator/generators/applications/app/template_runner.rb @@ -227,7 +227,7 @@ module Rails # def generate(what, *args) log 'generating', what - argument = args.map(&:to_s).flatten.join(" ") + argument = args.map {|arg| arg.to_s }.flatten.join(" ") in_root { run_ruby_script("script/generate #{what} #{argument}", false) } end diff --git a/railties/lib/rails_generator/generators/components/model/templates/model.rb b/railties/lib/rails_generator/generators/components/model/templates/model.rb index 6fcf393bdf..0656b06dfe 100644 --- a/railties/lib/rails_generator/generators/components/model/templates/model.rb +++ b/railties/lib/rails_generator/generators/components/model/templates/model.rb @@ -1,5 +1,5 @@ class <%= class_name %> < ActiveRecord::Base -<% attributes.select(&:reference?).each do |attribute| -%> +<% attributes.select {|attr| attr.reference? }.each do |attribute| -%> belongs_to :<%= attribute.name %> <% end -%> end diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake index 7cf7061f38..e496e1a04f 100644 --- a/railties/lib/tasks/gems.rake +++ b/railties/lib/tasks/gems.rake @@ -20,7 +20,7 @@ namespace :gems do desc "Build any native extensions for unpacked gems" task :build do $gems_build_rake_task = true - frozen_gems.each &:build + frozen_gems.each {|gem| gem.build } end namespace :build do @@ -33,12 +33,12 @@ namespace :gems do desc "Installs all required gems." task :install => :base do - current_gems.each &:install + current_gems.each {|gem| gem.install } end desc "Unpacks all required gems into vendor/gems." task :unpack => :install do - current_gems.each &:unpack + current_gems.each {|gem| gem.unpack } end namespace :unpack do @@ -50,7 +50,7 @@ namespace :gems do desc "Regenerate gem specifications in correct format." task :refresh_specs => :base do - current_gems.each &:refresh + current_gems.each {|gem| gem.refresh } end end diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb index 971cba89d0..fdcc7a1ef6 100644 --- a/railties/test/rails_info_test.rb +++ b/railties/test/rails_info_test.rb @@ -14,6 +14,8 @@ unless defined?(Rails) && defined?(Rails::Info) end end +require "active_support/core_ext/kernel/reporting" + class InfoTest < ActiveSupport::TestCase def setup Rails.send :remove_const, :Info From 842dab0c29bb05b98856aeb333bb0c2d14601a50 Mon Sep 17 00:00:00 2001 From: Jeffrey Chupp Date: Sat, 4 Apr 2009 09:36:32 -0500 Subject: [PATCH 25/45] Ensure WhiteListSanitizer allows dl tag [#2393 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_controller/vendor/html-scanner/html/sanitizer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ae20f9947c..a992f7d912 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb @@ -73,7 +73,7 @@ module HTML # Specifies the default Set of tags that the #sanitize helper will allow unscathed. self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var sub - sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dt dd abbr + sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbr acronym a img blockquote del ins)) # Specifies the default Set of html attributes that the #sanitize helper will leave From a9e8c4b37480564d27883dffe9134a9f95796a15 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 17 May 2009 14:31:54 +0200 Subject: [PATCH 26/45] Ensure rake test does not run new base tests as that requires rack/test --- actionpack/Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 6ce8179646..41b190130e 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -22,7 +22,7 @@ task :default => [ :test ] # Run the unit tests desc "Run all unit tests" -task :test => [:test_action_pack, :test_active_record_integration, :test_new_base] +task :test => [:test_action_pack, :test_active_record_integration] Rake::TestTask.new(:test_action_pack) do |t| t.libs << "test" From 25724eede9b5a62c74b3b78245944638f1cfcef4 Mon Sep 17 00:00:00 2001 From: Daniel Guettler Date: Sun, 17 May 2009 14:48:20 +0200 Subject: [PATCH 27/45] has_one :through should not create a new association when assigned nil [#698 state:resolved] Signed-off-by: Pratik Naik --- .../associations/has_one_through_association.rb | 16 ++++++++-------- .../has_one_through_associations_test.rb | 9 ++++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index 8073ebaf9f..d93c8e7852 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -1,31 +1,31 @@ module ActiveRecord module Associations class HasOneThroughAssociation < HasManyThroughAssociation - + def create_through_record(new_value) #nodoc: klass = @reflection.through_reflection.klass current_object = @owner.send(@reflection.through_reflection.name) - + if current_object - current_object.update_attributes(construct_join_attributes(new_value)) + new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy else - @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value))) + @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value))) if new_value end end - + private def find(*args) super(args.merge(:limit => 1)) end - + def find_target super.first end def reset_target! @target = nil - end - end + end + end end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 12c598751b..ab6e6d20fc 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -43,7 +43,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase @member.reload end end - + + def test_set_record_to_nil_should_delete_association + @member.club = nil + @member.reload + assert_equal nil, @member.current_membership + assert_nil @member.club + end + def test_has_one_through_polymorphic assert_equal clubs(:moustache_club), @member.sponsor_club end From d6645a5e52308a3270bf11f8c71cbf7c7f9d48f3 Mon Sep 17 00:00:00 2001 From: Jacob Kjeldahl Date: Tue, 27 Jan 2009 15:00:18 +0100 Subject: [PATCH 28/45] Supply valid ruby-prof parameters [#1804 state:resolved] Signed-off-by: Pratik Naik --- railties/lib/commands/performance/profiler.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/commands/performance/profiler.rb b/railties/lib/commands/performance/profiler.rb index fd111bae87..7df840f197 100644 --- a/railties/lib/commands/performance/profiler.rb +++ b/railties/lib/commands/performance/profiler.rb @@ -29,7 +29,7 @@ begin printer_class = RubyProf::FlatPrinter end printer = printer_class.new(results) - printer.print($stderr, 0) + printer.print($stderr) rescue LoadError require "prof" $stderr.puts 'Using the old ruby-prof extension.' From 34874b3bcdb42a710baecf8c6acfa3a30333d01a Mon Sep 17 00:00:00 2001 From: Paulo Schneider Date: Mon, 6 Apr 2009 21:38:24 +0100 Subject: [PATCH 29/45] Fix typo in the generated routes.rb [#2433 state:resolved] Signed-off-by: Pratik Naik --- railties/configs/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/configs/routes.rb b/railties/configs/routes.rb index 4f3d9d22dd..ea14ce1bfc 100644 --- a/railties/configs/routes.rb +++ b/railties/configs/routes.rb @@ -37,7 +37,7 @@ ActionController::Routing::Routes.draw do |map| # Install the default routes as the lowest priority. # Note: These default routes make all actions in every controller accessible via GET requests. You should - # consider removing the them or commenting them out if you're using named routes and resources. + # consider removing or commenting them out if you're using named routes and resources. map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end From 344ee681d6a89ea1da71c39e75c29e0cbda44914 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Wed, 18 Mar 2009 13:47:53 -0500 Subject: [PATCH 30/45] Remove obsolete wiki reference [#2291 state:resolved] Signed-off-by: Pratik Naik --- railties/lib/rails_generator/scripts.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails_generator/scripts.rb b/railties/lib/rails_generator/scripts.rb index 9b1a99838a..3763b75dba 100644 --- a/railties/lib/rails_generator/scripts.rb +++ b/railties/lib/rails_generator/scripts.rb @@ -57,7 +57,7 @@ module Rails usage << < Date: Sun, 17 May 2009 10:37:30 -0500 Subject: [PATCH 31/45] Add support for parsing XML and JSON from an IO as well as a string [#2659 state:resolved] Signed-off-by: Joshua Peek --- .../action_dispatch/middleware/params_parser.rb | 8 +++----- .../lib/active_support/json/backends/jsongem.rb | 5 ++++- .../lib/active_support/json/backends/yaml.rb | 5 ++++- .../lib/active_support/xml_mini/jdom.rb | 16 ++++++++++------ .../lib/active_support/xml_mini/libxml.rb | 16 ++++++++++------ .../lib/active_support/xml_mini/nokogiri.rb | 16 ++++++++++------ .../lib/active_support/xml_mini/rexml.rb | 14 +++++++++----- .../test/xml_mini/nokogiri_engine_test.rb | 13 +++++++++++++ activesupport/test/xml_mini/rexml_engine_test.rb | 14 ++++++++++++++ 9 files changed, 77 insertions(+), 30 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 58d527a6e7..a42c6598e0 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -32,16 +32,14 @@ module ActionDispatch when Proc strategy.call(request.raw_post) when :xml_simple, :xml_node - body = request.raw_post - body.blank? ? {} : Hash.from_xml(body).with_indifferent_access + request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access when :yaml YAML.load(request.raw_post) when :json - body = request.raw_post - if body.blank? + if request.body.size == 0 {} else - data = ActiveSupport::JSON.decode(body) + data = ActiveSupport::JSON.decode(request.body) data = {:_json => data} unless data.is_a?(Hash) data.with_indifferent_access end diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb index de847e30a3..d1a1cdd7d7 100644 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ b/activesupport/lib/active_support/json/backends/jsongem.rb @@ -6,8 +6,11 @@ module ActiveSupport module JSONGem extend self - # Converts a JSON string into a Ruby object. + # Parses a JSON string or IO and convert it into an object def decode(json) + if json.respond_to?(:read) + json = json.read + end data = ::JSON.parse(json) if ActiveSupport.parse_json_times convert_dates_from(data) diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb index c7db508c23..1c18fc4801 100644 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ b/activesupport/lib/active_support/json/backends/yaml.rb @@ -9,8 +9,11 @@ module ActiveSupport module Yaml extend self - # Converts a JSON string into a Ruby object. + # Parses a JSON string or IO and converts it into an object def decode(json) + if json.respond_to?(:read) + json = json.read + end YAML.load(convert_json_to_yaml(json)) rescue ArgumentError => e raise ParseError, "Invalid JSON string" diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index d795d55690..1cd714d864 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -24,15 +24,19 @@ module ActiveSupport node_type_map = {} NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type } - # Parse an XML Document string into a simple hash using Java's jdom. - # string:: - # XML Document string to parse - def parse(string) - if string.blank? + # Parse an XML Document string or IO into a simple hash using Java's jdom. + # data:: + # XML Document string or IO to parse + def parse(data) + if data.respond_to?(:read) + data = data.read + end + + if data.blank? {} else @dbf = DocumentBuilderFactory.new_instance - xml_string_reader = StringReader.new(string) + xml_string_reader = StringReader.new(data) xml_input_source = InputSource.new(xml_string_reader) doc = @dbf.new_document_builder.parse(xml_input_source) merge_element!({}, doc.document_element) diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb index 370205409a..d4c4dc7be5 100644 --- a/activesupport/lib/active_support/xml_mini/libxml.rb +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -5,16 +5,20 @@ module ActiveSupport module XmlMini_LibXML #:nodoc: extend self - # Parse an XML Document string into a simple hash using libxml. - # string:: - # XML Document string to parse - def parse(string) + # Parse an XML Document string or IO into a simple hash using libxml. + # data:: + # XML Document string or IO to parse + def parse(data) + if data.respond_to?(:read) + data = data.read + end + LibXML::XML.default_keep_blanks = false - if string.blank? + if data.blank? {} else - LibXML::XML::Parser.string(string.strip).parse.to_hash + LibXML::XML::Parser.string(data.strip).parse.to_hash end end diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb index 8f9676e4f6..7337c143c9 100644 --- a/activesupport/lib/active_support/xml_mini/nokogiri.rb +++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb @@ -5,14 +5,18 @@ module ActiveSupport module XmlMini_Nokogiri #:nodoc: extend self - # Parse an XML Document string into a simple hash using libxml / nokogiri. - # string:: - # XML Document string to parse - def parse(string) - if string.blank? + # Parse an XML Document string or IO into a simple hash using libxml / nokogiri. + # data:: + # XML Document string or IO to parse + def parse(data) + if data.respond_to?(:read) + data = data.read + end + + if data.blank? {} else - doc = Nokogiri::XML(string) + doc = Nokogiri::XML(data) raise doc.errors.first if doc.errors.length > 0 doc.to_hash end diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index 5033210aae..1184d2d6c9 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -7,16 +7,20 @@ module ActiveSupport CONTENT_KEY = '__content__'.freeze - # Parse an XML Document string into a simple hash + # Parse an XML Document string or IO into a simple hash # # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, # and uses the defaults from ActiveSupport # - # string:: - # XML Document string to parse - def parse(string) + # data:: + # XML Document string or IO to parse + def parse(data) + if data.respond_to?(:read) + data = data.read + end + require 'rexml/document' unless defined?(REXML::Document) - doc = REXML::Document.new(string) + doc = REXML::Document.new(data) merge_element!({}, doc.root) end diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb index 886a9d1aba..7c3a591e63 100644 --- a/activesupport/test/xml_mini/nokogiri_engine_test.rb +++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb @@ -148,6 +148,19 @@ class NokogiriEngineTest < Test::Unit::TestCase eoxml end + def test_parse_from_io + io = StringIO.new(<<-eoxml) + + good + + hello everyone + + morning + + eoxml + XmlMini.parse(io) + end + private def assert_equal_rexml(xml) hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) } diff --git a/activesupport/test/xml_mini/rexml_engine_test.rb b/activesupport/test/xml_mini/rexml_engine_test.rb index a412d8ca05..57bb35254a 100644 --- a/activesupport/test/xml_mini/rexml_engine_test.rb +++ b/activesupport/test/xml_mini/rexml_engine_test.rb @@ -12,4 +12,18 @@ class REXMLEngineTest < Test::Unit::TestCase XmlMini.backend = 'REXML' assert_equal XmlMini_REXML, XmlMini.backend end + + def test_parse_from_io + XmlMini.backend = 'REXML' + io = StringIO.new(<<-eoxml) + + good + + hello everyone + + morning + + eoxml + XmlMini.parse(io) + end end From 11bac700784efe232083f94e3d28d171957e667e Mon Sep 17 00:00:00 2001 From: Lance Ivy Date: Wed, 15 Apr 2009 16:46:30 -0700 Subject: [PATCH 32/45] Ensure auto_link does not ignore multiple trailing punctuations [#2504 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/text_helper.rb | 13 +++++++------ actionpack/test/template/text_helper_test.rb | 7 +++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 573b99b96e..8136a1cb13 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -535,7 +535,7 @@ module ActionView link_attributes = html_options.stringify_keys text.gsub(AUTO_LINK_RE) do href = $& - punctuation = '' + punctuation = [] left, right = $`, $' # detect already linked URLs and URLs in the middle of a tag if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ @@ -543,17 +543,18 @@ module ActionView href else # don't include trailing punctuation character as part of the URL - if href.sub!(/[^\w\/-]$/, '') and punctuation = $& and opening = BRACKETS[punctuation] - if href.scan(opening).size > href.scan(punctuation).size - href << punctuation - punctuation = '' + while href.sub!(/[^\w\/-]$/, '') + punctuation.push $& + if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size + href << punctuation.pop + break end end link_text = block_given?? yield(href) : href href = 'http://' + href unless href.index('http') == 0 - content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation + content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation.reverse.join('') end end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index be7163888e..a780bfc606 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -401,6 +401,13 @@ class TextHelperTest < ActionView::TestCase auto_link("Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com.", :link => :all, :html => { :class => "menu", :target => "_blank" }) end + + def test_auto_link_with_multiple_trailing_punctuations + url = "http://youtube.com" + url_result = generate_result(url) + assert_equal url_result, auto_link(url) + assert_equal "(link: #{url_result}).", auto_link("(link: #{url}).") + end def test_cycle_class value = Cycle.new("one", 2, "3") From 4e8c36a7417e5d447c9b15d5c61df0c014ee6d3b Mon Sep 17 00:00:00 2001 From: Chris Kampmeier Date: Mon, 16 Mar 2009 05:56:32 -0700 Subject: [PATCH 33/45] Implement #many? for NamedScope and AssociationCollection using #size [#1500 state:resolved] Signed-off-by: Pratik Naik --- activerecord/CHANGELOG | 2 + .../associations/association_collection.rb | 9 +++++ activerecord/lib/active_record/named_scope.rb | 11 +++++- .../has_many_associations_test.rb | 39 +++++++++++++++++++ activerecord/test/cases/named_scope_test.rb | 34 ++++++++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index d58b44144b..411b640c9e 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *Edge* +* Implement #many? for NamedScope and AssociationCollection using #size. #1500 [Chris Kampmeier] + * Added :touch option to belongs_to associations that will touch the parent record when the current record is saved or destroyed [DHH] * Added ActiveRecord::Base#touch to update the updated_at/on attributes (or another specified timestamp) with the current time [DHH] diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 26987dde97..e12f6be35d 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -302,6 +302,15 @@ module ActiveRecord end end + # Returns true if the collection has more than 1 record. Equivalent to collection.size > 1. + def many? + if block_given? + method_missing(:many?) { |*block_args| yield(*block_args) } + else + size > 1 + end + end + def uniq(collection = self) seen = Set.new collection.inject([]) do |kept, record| diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 07f98dc743..e7151a3d47 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -109,7 +109,7 @@ module ActiveRecord class Scope attr_reader :proxy_scope, :proxy_options, :current_scoped_methods_when_defined - NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? respond_to?).to_set + NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?).to_set [].methods.each do |m| unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s) delegate m, :to => :proxy_found @@ -168,6 +168,15 @@ module ActiveRecord end end + # Returns true if the named scope has more than 1 matching record. + def many? + if block_given? + proxy_found.many? { |*block_args| yield(*block_args) } + else + size > 1 + end + end + protected def proxy_found @found || load_found diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 5df74fcdcd..d99424f9cd 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1023,6 +1023,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert firm.clients.loaded? end + def test_calling_many_should_count_instead_of_loading_association + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.many? # use count query + end + assert !firm.clients.loaded? + end + + def test_calling_many_on_loaded_association_should_not_use_query + firm = companies(:first_firm) + firm.clients.collect # force load + assert_no_queries { assert firm.clients.many? } + end + + def test_calling_many_should_defer_to_collection_if_using_a_block + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.expects(:size).never + firm.clients.many? { true } + end + assert firm.clients.loaded? + end + + def test_calling_many_should_return_false_if_none_or_one + firm = companies(:another_firm) + assert !firm.clients_like_ms.many? + assert_equal 0, firm.clients_like_ms.size + + firm = companies(:first_firm) + assert !firm.limited_clients.many? + assert_equal 1, firm.limited_clients.size + end + + def test_calling_many_should_return_true_if_more_than_one + firm = companies(:first_firm) + assert firm.clients.many? + assert_equal 2, firm.clients.size + end + def test_joins_with_namespaced_model_should_use_correct_type old = ActiveRecord::Base.store_full_sti_class ActiveRecord::Base.store_full_sti_class = true diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 7dcea6d42e..69d01d5c2a 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -235,6 +235,40 @@ class NamedScopeTest < ActiveRecord::TestCase assert_no_queries { assert topics.any? } end + def test_many_should_not_load_results + topics = Topic.base + assert_queries(2) do + topics.many? # use count query + topics.collect # force load + topics.many? # use loaded (no query) + end + end + + def test_many_should_call_proxy_found_if_using_a_block + topics = Topic.base + assert_queries(1) do + topics.expects(:size).never + topics.many? { true } + end + end + + def test_many_should_not_fire_query_if_named_scope_loaded + topics = Topic.base + topics.collect # force load + assert_no_queries { assert topics.many? } + end + + def test_many_should_return_false_if_none_or_one + topics = Topic.base.scoped(:conditions => {:id => 0}) + assert !topics.many? + topics = Topic.base.scoped(:conditions => {:id => 1}) + assert !topics.many? + end + + def test_many_should_return_true_if_more_than_one + assert Topic.base.many? + end + def test_should_build_with_proxy_options topic = Topic.approved.build({}) assert topic.approved From e41984c5f7f38b62c05dfcb54940bf51f6961aeb Mon Sep 17 00:00:00 2001 From: "Thomas E. Glasgow" Date: Sun, 17 May 2009 18:54:34 +0200 Subject: [PATCH 34/45] Simplify filter_chain method implementation [#2327 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/base/chained/filters.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/actionpack/lib/action_controller/base/chained/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb index 98fe306fd5..e121c0129d 100644 --- a/actionpack/lib/action_controller/base/chained/filters.rb +++ b/actionpack/lib/action_controller/base/chained/filters.rb @@ -571,12 +571,7 @@ module ActionController #:nodoc: # Returns an array of Filter objects for this controller. def filter_chain - if chain = read_inheritable_attribute('filter_chain') - return chain - else - write_inheritable_attribute('filter_chain', FilterChain.new) - return filter_chain - end + read_inheritable_attribute('filter_chain') || write_inheritable_attribute('filter_chain', FilterChain.new) end # Returns all the before filters for this class and all its ancestors. From 98eaa2c6834e418959f2a1a18421e4811167e03b Mon Sep 17 00:00:00 2001 From: Travis Briggs Date: Wed, 18 Mar 2009 21:51:26 -0400 Subject: [PATCH 35/45] Ensure number_to_human_size does not strip zeros from the end [#1763 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/number_helper.rb | 7 ++++++- actionpack/test/template/number_helper_test.rb | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index c02692b09a..999d5b34fc 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -248,6 +248,11 @@ module ActionView # number_to_human_size(483989, :precision => 0) # => 473 KB # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,18 MB # + # Zeros after the decimal point are always stripped out, regardless of the + # specified precision: + # helper.number_to_human_size(1234567890123, :precision => 5) # => "1.12283 TB" + # helper.number_to_human_size(524288000, :precision=>5) # => "500 MB" + # # You can still use number_to_human_size with the old API that accepts the # +precision+ as its optional second parameter: # number_to_human_size(1234567, 2) # => 1.18 MB @@ -293,7 +298,7 @@ module ActionView :precision => precision, :separator => separator, :delimiter => delimiter - ).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '') + ).sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '') storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit) rescue number diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 29cb60fd73..b6542ef29d 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -118,6 +118,10 @@ class NumberHelperTest < ActionView::TestCase assert_equal '1.01 KB', number_to_human_size(1.0123.kilobytes, :precision => 2) assert_equal '1.01 KB', number_to_human_size(1.0100.kilobytes, :precision => 4) assert_equal '10 KB', number_to_human_size(10.000.kilobytes, :precision => 4) + assert_equal '1 TB', number_to_human_size(1234567890123, :precision => 0) + assert_equal '500 MB', number_to_human_size(524288000, :precision=>0) + assert_equal '40 KB', number_to_human_size(41010, :precision => 0) + assert_equal '40 KB', number_to_human_size(41100, :precision => 0) end def test_number_to_human_size_with_custom_delimiter_and_separator From c3319504f066c9362b4b30e1e15bbd1cadde8e25 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 17 May 2009 11:09:14 -0500 Subject: [PATCH 36/45] Rescue hack was supposed to be removed. Some how it crept back in. --- actionpack/lib/action_controller/base/base.rb | 5 ++--- actionpack/lib/action_controller/testing/process.rb | 3 --- actionpack/test/controller/filters_test.rb | 1 - actionpack/test/controller/helper_test.rb | 3 --- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index 2813e71d12..c59068c628 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -368,9 +368,8 @@ module ActionController #:nodoc: attr_reader :template def action(name, env) - # HACK: For global rescue to have access to the original request and response - request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env) - response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new + request = ActionDispatch::Request.new(env) + response = ActionDispatch::Response.new self.action_name = name && name.to_s process(request, response).to_a end diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 8f4358c33e..8831ff57e2 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -132,9 +132,6 @@ module ActionController #:nodoc: @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash build_request_uri(action, parameters) - @request.env["action_controller.rescue.request"] = @request - @request.env["action_controller.rescue.response"] = @response - Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest env = @request.env diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 9ad49e9282..afefc6a77e 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -607,7 +607,6 @@ class FilterTest < Test::Unit::TestCase def test_dynamic_dispatch %w(foo bar baz).each do |action| request = ActionController::TestRequest.new - request.env["action_controller.rescue.request"] = request request.query_parameters[:choose] = action response = DynamicDispatchController.action.call(request.env).last assert_equal action, response.body diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 7b8096fccc..3bbda9eb3a 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -104,7 +104,6 @@ class HelperTest < Test::Unit::TestCase def call_controller(klass, action) request = ActionController::TestRequest.new - request.env["action_controller.rescue.request"] = request klass.action(action).call(request.env) end @@ -112,7 +111,6 @@ class HelperTest < Test::Unit::TestCase assert_equal 'hello: Iz guuut!', call_controller(Fun::GamesController, "render_hello_world").last.body # request = ActionController::TestRequest.new - # request.env["action_controller.rescue.request"] = request # # resp = Fun::GamesController.action(:render_hello_world).call(request.env) # assert_equal 'hello: Iz guuut!', resp.last.body @@ -217,7 +215,6 @@ class IsolatedHelpersTest < Test::Unit::TestCase def call_controller(klass, action) request = ActionController::TestRequest.new - request.env["action_controller.rescue.request"] = request klass.action(action).call(request.env) end From 8118fca9beec675fba19395e7d1027eaa4b5703a Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 17 May 2009 12:24:42 -0500 Subject: [PATCH 37/45] Merge Failsafe middleware into ShowExceptions --- .../action_controller/dispatch/middlewares.rb | 1 - actionpack/lib/action_dispatch.rb | 1 - .../action_dispatch/middleware/failsafe.rb | 51 ----------- .../middleware/show_exceptions.rb | 91 +++++++++---------- actionpack/test/controller/rescue_test.rb | 14 +++ .../test/dispatch/show_exceptions_test.rb | 5 + .../test/new_base/render_action_test.rb | 4 +- actionpack/test/new_base/render_test.rb | 6 +- railties/lib/initializer.rb | 2 +- 9 files changed, 67 insertions(+), 108 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/middleware/failsafe.rb diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index 0e4ab6fa39..e4e3a704c0 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -2,7 +2,6 @@ use "Rack::Lock", :if => lambda { !ActionController::Base.allow_concurrency } -use "ActionDispatch::Failsafe" use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local } use "ActionDispatch::Rescue", lambda { controller = (::ApplicationController rescue ActionController::Base) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 27d229835a..f3c91d8624 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -38,7 +38,6 @@ module ActionDispatch autoload :Response, 'action_dispatch/http/response' autoload :StatusCodes, 'action_dispatch/http/status_codes' - autoload :Failsafe, 'action_dispatch/middleware/failsafe' autoload :ParamsParser, 'action_dispatch/middleware/params_parser' autoload :Rescue, 'action_dispatch/middleware/rescue' autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions' diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb deleted file mode 100644 index 389accbc36..0000000000 --- a/actionpack/lib/action_dispatch/middleware/failsafe.rb +++ /dev/null @@ -1,51 +0,0 @@ -module ActionDispatch - class Failsafe - cattr_accessor :error_file_path - self.error_file_path = Rails.public_path if defined?(Rails.public_path) - - def initialize(app) - @app = app - end - - def call(env) - @app.call(env) - rescue Exception => exception - if env["rails.raise_exceptions"] - raise - else - failsafe_response(exception) - end - end - - private - def failsafe_response(exception) - log_failsafe_exception(exception) - [500, {'Content-Type' => 'text/html'}, failsafe_response_body] - rescue Exception => failsafe_error # Logger or IO errors - $stderr.puts "Error during failsafe response: #{failsafe_error}" - end - - def failsafe_response_body - error_path = "#{self.class.error_file_path}/500.html" - if File.exist?(error_path) - [File.read(error_path)] - else - ["

500 Internal Server Error

"] - end - end - - def log_failsafe_exception(exception) - message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: 500 Internal Server Error\n" - message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception - failsafe_logger.fatal(message) - end - - def failsafe_logger - if defined?(Rails) && Rails.logger - Rails.logger - else - Logger.new($stderr) - end - end - end -end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 71c1e1b9a9..108355da63 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -4,8 +4,11 @@ module ActionDispatch LOCALHOST = '127.0.0.1'.freeze - DEFAULT_RESCUE_RESPONSE = :internal_server_error - DEFAULT_RESCUE_RESPONSES = { + RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates') + + cattr_accessor :rescue_responses + @@rescue_responses = Hash.new(:internal_server_error) + @@rescue_responses.update({ 'ActionController::RoutingError' => :not_found, 'ActionController::UnknownAction' => :not_found, 'ActiveRecord::RecordNotFound' => :not_found, @@ -15,25 +18,19 @@ module ActionDispatch 'ActionController::MethodNotAllowed' => :method_not_allowed, 'ActionController::NotImplemented' => :not_implemented, 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity - } + }) - DEFAULT_RESCUE_TEMPLATE = 'diagnostics' - DEFAULT_RESCUE_TEMPLATES = { + cattr_accessor :rescue_templates + @@rescue_templates = Hash.new('diagnostics') + @@rescue_templates.update({ 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', 'ActionController::UnknownAction' => 'unknown_action', 'ActionView::TemplateError' => 'template_error' - } + }) - RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates') - - cattr_accessor :rescue_responses - @@rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE) - @@rescue_responses.update DEFAULT_RESCUE_RESPONSES - - cattr_accessor :rescue_templates - @@rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE) - @@rescue_templates.update DEFAULT_RESCUE_TEMPLATES + FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'}, + ['

500 Internal Server Error

']] def initialize(app, consider_all_requests_local = false) @app = app @@ -43,34 +40,35 @@ module ActionDispatch def call(env) @app.call(env) rescue Exception => exception - raise exception if env['rack.test'] - - log_error(exception) if logger - - request = Request.new(env) - if @consider_all_requests_local || local_request?(request) - rescue_action_locally(request, exception) - else - rescue_action_in_public(exception) - end + raise exception if env['action_dispatch.show_exceptions'] == false + render_exception(env, exception) end private + def render_exception(env, exception) + log_error(exception) + + request = Request.new(env) + if @consider_all_requests_local || local_request?(request) + rescue_action_locally(request, exception) + else + rescue_action_in_public(exception) + end + rescue Exception => failsafe_error + $stderr.puts "Error during failsafe response: #{failsafe_error}" + FAILSAFE_RESPONSE + end + # Render detailed diagnostics for unhandled exceptions rescued from # a controller action. def rescue_action_locally(request, exception) template = ActionView::Base.new([RESCUES_TEMPLATE_PATH], - :template => template, :request => request, :exception => exception ) file = "rescues/#{@@rescue_templates[exception.class.name]}.erb" body = template.render(:file => file, :layout => 'rescues/layout.erb') - - headers = {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s} - status = status_code(exception) - - [status, headers, body] + render(status_code(exception), body) end # Attempts to render a static error page based on the @@ -86,11 +84,11 @@ module ActionDispatch path = "#{public_path}/#{status}.html" if locale_path && File.exist?(locale_path) - render_public_file(status, locale_path) + render(status, File.read(locale_path)) elsif File.exist?(path) - render_public_file(status, path) + render(status, File.read(path)) else - [status, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []] + render(status, '') end end @@ -99,24 +97,21 @@ module ActionDispatch request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST end - def render_public_file(status, path) - body = File.read(path) - [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body] - end - def status_code(exception) interpret_status(@@rescue_responses[exception.class.name]).to_i end - def public_path - if defined?(Rails) - Rails.public_path - else - "public" - end + def render(status, body) + [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body] end - def log_error(exception) #:doc: + def public_path + defined?(Rails.public_path) ? Rails.public_path : 'public_path' + end + + def log_error(exception) + return unless logger + ActiveSupport::Deprecation.silence do if ActionView::TemplateError === exception logger.fatal(exception.to_s) @@ -136,9 +131,7 @@ module ActionDispatch end def logger - if defined?(Rails.logger) - Rails.logger - end + defined?(Rails.logger) ? Rails.logger : Logger.new($stderr) end end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index f745926b20..490a4ff3b3 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -1,5 +1,19 @@ require 'abstract_unit' +module ActionDispatch + class ShowExceptions + private + def public_path + "#{FIXTURE_LOAD_PATH}/public" + end + + # Silence logger + def logger + nil + end + end +end + class RescueController < ActionController::Base class NotAuthorized < StandardError end diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index f8f562e7c1..0c0c087340 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -6,6 +6,11 @@ module ActionDispatch def public_path "#{FIXTURE_LOAD_PATH}/public" end + + # Silence logger + def logger + nil + end end end diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb index 96666077d2..626c7b3540 100644 --- a/actionpack/test/new_base/render_action_test.rb +++ b/actionpack/test/new_base/render_action_test.rb @@ -92,7 +92,7 @@ module RenderAction test "raises an exception when requesting a layout and none exist" do assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do - get "/render_action/basic/hello_world_with_layout", {}, "rails.raise_exceptions" => true + get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false end end end @@ -118,7 +118,7 @@ module RenderAction test "raises an exception when requesting a layout that does not exist" do assert_raise(ActionView::MissingTemplate) do - get "/render_action/basic/hello_world_with_custom_layout", {}, "rails.raise_exceptions" => true + get "/render_action/basic/hello_world_with_custom_layout", {}, "action_dispatch.show_exceptions" => false end end end diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb index 16578fbc82..ef5e7d89c5 100644 --- a/actionpack/test/new_base/render_test.rb +++ b/actionpack/test/new_base/render_test.rb @@ -48,7 +48,7 @@ module Render test "raises an exception" do assert_raises(AbstractController::DoubleRenderError) do - get "/render/double_render", {}, "rails.raise_exceptions" => true + get "/render/double_render", {}, "action_dispatch.show_exceptions" => false end end end @@ -58,13 +58,13 @@ module Render test "raises an exception when a method of Object is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/clone", {}, "rails.raise_exceptions" => true + get "/render/blank_render/clone", {}, "action_dispatch.show_exceptions" => false end end test "raises an exception when a private method is called" do assert_raises(AbstractController::ActionNotFound) do - get "/render/blank_render/secretz", {}, "rails.raise_exceptions" => true + get "/render/blank_render/secretz", {}, "action_dispatch.show_exceptions" => false end end end diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index e4d7589aba..b16f42b8a0 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -462,7 +462,7 @@ Run `rake gems:install` to install the missing gems. if RAILS_CACHE.respond_to?(:middleware) # Insert middleware to setup and teardown local cache for each request - configuration.middleware.insert_after(:"ActionDispatch::Failsafe", RAILS_CACHE.middleware) + configuration.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware) end end end From edc9c226d11e6104d191ceeb6416c7062ceda54a Mon Sep 17 00:00:00 2001 From: Mike Breen Date: Sun, 17 May 2009 19:48:15 +0200 Subject: [PATCH 38/45] Add tests for assert_template :template Signed-off-by: Pratik Naik --- .../controller/action_pack_assertions_test.rb | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 484d3c5ce7..c3c769919a 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -12,6 +12,9 @@ class ActionPackAssertionsController < ActionController::Base # a standard template def hello_xml_world() render :template => "test/hello_xml_world"; end + # a standard partial + def partial() render :partial => 'test/partial'; end + # a redirect to an internal location def redirect_internal() redirect_to "/nothing"; end @@ -331,6 +334,26 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase end end + def test_assert_template_with_partial + get :partial + assert_template :partial => '_partial' + end + + def test_assert_template_with_nil + get :nothing + assert_template nil + end + + def test_assert_template_with_string + get :hello_world + assert_template 'hello_world' + end + + def test_assert_template_with_symbol + get :hello_world + assert_template :hello_world + end + # check if we were rendered by a file-based template? def test_rendered_action process :nothing From 092089015b79752c5e9d664b3eeefef9e2223e36 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 17 May 2009 13:39:44 -0500 Subject: [PATCH 39/45] Extract generic callbacks middleware from dispatcher --- .../action_controller/dispatch/dispatcher.rb | 106 +++++++----------- .../action_controller/dispatch/middlewares.rb | 1 + actionpack/lib/action_dispatch.rb | 1 + .../action_dispatch/middleware/callbacks.rb | 40 +++++++ actionpack/test/controller/dispatcher_test.rb | 34 +++--- railties/lib/console_app.rb | 5 +- railties/lib/initializer.rb | 1 - 7 files changed, 106 insertions(+), 82 deletions(-) create mode 100644 actionpack/lib/action_dispatch/middleware/callbacks.rb diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb index 63866caed9..9ad1cadfd3 100644 --- a/actionpack/lib/action_controller/dispatch/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb @@ -1,46 +1,11 @@ +require 'active_support/core_ext/module/delegation' + module ActionController # Dispatches requests to the appropriate controller and takes care of # reloading the app after each request when Dependencies.load? is true. class Dispatcher - class << self - def define_dispatcher_callbacks(cache_classes) - unless cache_classes - # Development mode callbacks - before_dispatch :reload_application - after_dispatch :cleanup_application - - ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false - end - - if defined?(ActiveRecord) - to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } - end - - after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush) - - to_prepare do - I18n.reload! - end - end - - # Add a preparation callback. Preparation callbacks are run before every - # request in development mode, and before the first request in production - # mode. - # - # An optional identifier may be supplied for the callback. If provided, - # to_prepare may be called again with the same identifier to replace the - # existing callback. Passing an identifier is a suggested practice if the - # code adding a preparation block may be reloaded. - def to_prepare(identifier = nil, &block) - @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new - callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier) - @prepare_dispatch_callbacks.replace_or_append!(callback) - end - - def run_prepare_callbacks - new.send :run_callbacks, :prepare_dispatch - end - end + cattr_accessor :prepare_each_request + self.prepare_each_request = false cattr_accessor :router self.router = Routing::Routes @@ -51,37 +16,50 @@ module ActionController middleware.instance_eval(File.read(middlewares), middlewares, 1) end - include ActiveSupport::Callbacks - define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch + class << self + def define_dispatcher_callbacks(cache_classes) + unless cache_classes + # Run prepare callbacks before every request in development mode + self.prepare_each_request = true - def initialize - @app = @@middleware.build(@@router) - freeze - end + # Development mode callbacks + ActionDispatch::Callbacks.before_dispatch do |app| + ActionController::Dispatcher.router.reload + end - def call(env) - run_callbacks :before_dispatch - @app.call(env) - ensure - run_callbacks :after_dispatch, :enumerator => :reverse_each - end + ActionDispatch::Callbacks.after_dispatch do + # Cleanup the application before processing the current request. + ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) + ActiveSupport::Dependencies.clear + ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) + end - def reload_application - # Run prepare callbacks before every request in development mode - run_callbacks :prepare_dispatch + ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false + end - @@router.reload - end + if defined?(ActiveRecord) + to_prepare(:activerecord_instantiate_observers) do + ActiveRecord::Base.instantiate_observers + end + end - def cleanup_application - # Cleanup the application before processing the current request. - ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) - ActiveSupport::Dependencies.clear - ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) - end + if Base.logger && Base.logger.respond_to?(:flush) + after_dispatch do + Base.logger.flush + end + end - def flush_logger - Base.logger.flush + to_prepare do + I18n.reload! + end + end + + delegate :to_prepare, :prepare_dispatch, :before_dispatch, :after_dispatch, + :to => ActionDispatch::Callbacks + + def new + @@middleware.build(@@router) + end end end end diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index e4e3a704c0..b25ed3fd3f 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -3,6 +3,7 @@ use "Rack::Lock", :if => lambda { } use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local } +use "ActionDispatch::Callbacks", lambda { ActionController::Dispatcher.prepare_each_request } use "ActionDispatch::Rescue", lambda { controller = (::ApplicationController rescue ActionController::Base) # TODO: Replace with controller.action(:_rescue_action) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index f3c91d8624..6fc4ad3f21 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -38,6 +38,7 @@ module ActionDispatch autoload :Response, 'action_dispatch/http/response' autoload :StatusCodes, 'action_dispatch/http/status_codes' + autoload :Callbacks, 'action_dispatch/middleware/callbacks' autoload :ParamsParser, 'action_dispatch/middleware/params_parser' autoload :Rescue, 'action_dispatch/middleware/rescue' autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions' diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb new file mode 100644 index 0000000000..0a2b4cf5f7 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -0,0 +1,40 @@ +module ActionDispatch + class Callbacks + include ActiveSupport::Callbacks + define_callbacks :prepare, :before, :after + + class << self + # DEPRECATED + alias_method :prepare_dispatch, :prepare + alias_method :before_dispatch, :before + alias_method :after_dispatch, :after + end + + # Add a preparation callback. Preparation callbacks are run before every + # request in development mode, and before the first request in production + # mode. + # + # An optional identifier may be supplied for the callback. If provided, + # to_prepare may be called again with the same identifier to replace the + # existing callback. Passing an identifier is a suggested practice if the + # code adding a preparation block may be reloaded. + def self.to_prepare(identifier = nil, &block) + @prepare_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new + callback = ActiveSupport::Callbacks::Callback.new(:prepare, block, :identifier => identifier) + @prepare_callbacks.replace_or_append!(callback) + end + + def initialize(app, prepare_each_request = false) + @app, @prepare_each_request = app, prepare_each_request + run_callbacks :prepare + end + + def call(env) + run_callbacks :before + run_callbacks :prepare if @prepare_each_request + @app.call(env) + ensure + run_callbacks :after, :enumerator => :reverse_each + end + end +end diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index b315232a7b..9fae1fcf63 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -6,20 +6,20 @@ class DispatcherTest < Test::Unit::TestCase def setup ENV['REQUEST_METHOD'] = 'GET' - Dispatcher.middleware = ActionDispatch::MiddlewareStack.new do |middleware| - middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/dispatch/middlewares.rb")) - middleware.instance_eval(File.read(middlewares)) - end - # Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks - Dispatcher.instance_variable_set("@prepare_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - Dispatcher.instance_variable_set("@before_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - Dispatcher.instance_variable_set("@after_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + ActionDispatch::Callbacks.instance_variable_set("@prepare_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + ActionDispatch::Callbacks.instance_variable_set("@before_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + ActionDispatch::Callbacks.instance_variable_set("@after_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + @old_router, Dispatcher.router = Dispatcher.router, mock() + Dispatcher.router.stubs(:call).returns([200, {}, 'response']) + Dispatcher.router.stubs(:reload) Dispatcher.stubs(:require_dependency) end def teardown + Dispatcher.router = @old_router + @dispatcher = nil ENV.delete 'REQUEST_METHOD' end @@ -29,12 +29,12 @@ class DispatcherTest < Test::Unit::TestCase end def test_reloads_routes_before_dispatch_if_in_loading_mode - ActionController::Routing::Routes.expects(:reload).once + Dispatcher.router.expects(:reload).once dispatch(false) end def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode - ActionController::Routing::Routes.expects(:reload).never + Dispatcher.router.expects(:reload).never ActiveSupport::Dependencies.expects(:clear).never dispatch @@ -55,7 +55,7 @@ class DispatcherTest < Test::Unit::TestCase assert_nil a || b || c # Run callbacks - Dispatcher.run_prepare_callbacks + dispatch assert_equal 1, a assert_equal 2, b @@ -72,16 +72,22 @@ class DispatcherTest < Test::Unit::TestCase Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 } Dispatcher.to_prepare(:unique_id) { |*args| a = 2 } - Dispatcher.run_prepare_callbacks + dispatch assert_equal 2, a assert_equal nil, b end private def dispatch(cache_classes = true) - ActionController::Routing::RouteSet.any_instance.stubs(:call).returns([200, {}, 'response']) + ActionController::Dispatcher.prepare_each_request = false Dispatcher.define_dispatcher_callbacks(cache_classes) - Dispatcher.new.call({'rack.input' => StringIO.new('')}) + Dispatcher.middleware = ActionDispatch::MiddlewareStack.new do |middleware| + middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/dispatch/middlewares.rb")) + middleware.instance_eval(File.read(middlewares)) + end + + @dispatcher ||= Dispatcher.new + @dispatcher.call({'rack.input' => StringIO.new(''), 'action_dispatch.show_exceptions' => false}) end def assert_subclasses(howmany, klass, message = klass.subclasses.inspect) diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb index c944d49205..42bf50e01e 100644 --- a/railties/lib/console_app.rb +++ b/railties/lib/console_app.rb @@ -26,8 +26,7 @@ end #reloads the environment def reload! puts "Reloading..." - dispatcher = ActionController::Dispatcher.new - dispatcher.cleanup_application - dispatcher.reload_application + ActionController::Dispatcher.new + ActionController::Dispatcher.router.reload true end diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index b16f42b8a0..4c6de48a65 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -632,7 +632,6 @@ Run `rake gems:install` to install the missing gems. return unless configuration.frameworks.include?(:action_controller) require 'dispatcher' unless defined?(::Dispatcher) Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) - Dispatcher.run_prepare_callbacks end def disable_dependency_loading From b33c0d98329b97f8f540ba455d419d5046e6bb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 17 May 2009 13:51:35 -0500 Subject: [PATCH 40/45] replace the aaa_create_tables_test hack with loading test database schema in the test helper [#2663 state:resolved] Signed-off-by: Joshua Peek --- .../test/cases/aaa_create_tables_test.rb | 24 ------------------- activerecord/test/cases/helper.rb | 18 ++++++++++++++ activerecord/test/schema/schema.rb | 5 +++- activerecord/test/schema/schema2.rb | 6 ----- 4 files changed, 22 insertions(+), 31 deletions(-) delete mode 100644 activerecord/test/cases/aaa_create_tables_test.rb delete mode 100644 activerecord/test/schema/schema2.rb diff --git a/activerecord/test/cases/aaa_create_tables_test.rb b/activerecord/test/cases/aaa_create_tables_test.rb deleted file mode 100644 index 3911afac49..0000000000 --- a/activerecord/test/cases/aaa_create_tables_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -# The filename begins with "aaa" to ensure this is the first test. -require "cases/helper" - -class AAACreateTablesTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - def test_load_schema - eval(File.read(SCHEMA_ROOT + "/schema.rb")) - if File.exists?(adapter_specific_schema_file) - eval(File.read(adapter_specific_schema_file)) - end - assert true - end - - def test_drop_and_create_courses_table - eval(File.read(SCHEMA_ROOT + "/schema2.rb")) - assert true - end - - private - def adapter_specific_schema_file - SCHEMA_ROOT + '/' + ActiveRecord::Base.connection.adapter_name.downcase + '_specific_schema.rb' - end -end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 05e92433cd..f82784836e 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -5,6 +5,7 @@ require 'config' require 'rubygems' require 'test/unit' +require 'stringio' gem 'mocha', '>= 0.9.5' require 'mocha' @@ -72,3 +73,20 @@ class ActiveSupport::TestCase Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, {}, &block) end end + +# silence verbose schema loading +original_stdout = $stdout +$stdout = StringIO.new + +begin + adapter_name = ActiveRecord::Base.connection.adapter_name.downcase + adapter_specific_schema_file = SCHEMA_ROOT + "/#{adapter_name}_specific_schema.rb" + + load SCHEMA_ROOT + "/schema.rb" + + if File.exists?(adapter_specific_schema_file) + load adapter_specific_schema_file + end +ensure + $stdout = original_stdout +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index a776cd974b..4ee0ffe132 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -1,4 +1,3 @@ - ActiveRecord::Schema.define do def except(adapter_names_to_exclude) unless [adapter_names_to_exclude].flatten.include?(adapter_name) @@ -500,3 +499,7 @@ ActiveRecord::Schema.define do execute "ALTER TABLE fk_test_has_fk ADD CONSTRAINT fk_name FOREIGN KEY (#{quote_column_name 'fk_id'}) REFERENCES #{quote_table_name 'fk_test_has_pk'} (#{quote_column_name 'id'})" end end + +Course.connection.create_table :courses, :force => true do |t| + t.column :name, :string, :null => false +end diff --git a/activerecord/test/schema/schema2.rb b/activerecord/test/schema/schema2.rb deleted file mode 100644 index 8527f7ba8f..0000000000 --- a/activerecord/test/schema/schema2.rb +++ /dev/null @@ -1,6 +0,0 @@ -ActiveRecord::Schema.define do - - Course.connection.create_table :courses, :force => true do |t| - t.column :name, :string, :null => false - end -end From 01d7acd11d631d980497870aad1af42a0c66115c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 17 May 2009 14:42:36 -0500 Subject: [PATCH 41/45] Fix reset_session with ActiveRecord store [#2200 state:resolved] --- .../test/activerecord/active_record_store_test.rb | 6 +++--- activerecord/lib/active_record/session_store.rb | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index 663cd259c8..47f8496181 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -28,9 +28,9 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest end def call_reset_session - session[:bar] + session[:foo] reset_session - session[:bar] = "baz" + session[:foo] = "baz" head :ok end @@ -91,7 +91,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest get '/get_session_value' assert_response :success - assert_equal 'foo: nil', response.body + assert_equal 'foo: "baz"', response.body get '/get_session_id' assert_response :success diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 21471da419..9dda3361d8 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -295,7 +295,7 @@ module ActiveRecord def set_session(env, sid, session_data) Base.silence do - record = env[SESSION_RECORD_KEY] ||= find_session(sid) + record = get_session_model(env, sid) record.data = session_data return false unless record.save @@ -309,6 +309,14 @@ module ActiveRecord return true end + + def get_session_model(env, sid) + if env[ENV_SESSION_OPTIONS_KEY][:id].nil? + env[SESSION_RECORD_KEY] = find_session(sid) + else + env[SESSION_RECORD_KEY] ||= find_session(sid) + end + end def find_session(id) @@session_class.find_by_session_id(id) || From b0de061e7b8d3c291a328f6b0b9bfc5f48b2f907 Mon Sep 17 00:00:00 2001 From: Brian Lopez Date: Sun, 17 May 2009 16:09:28 -0500 Subject: [PATCH 42/45] Allow ParamsParser to parse YAML from the request body IO directly Signed-off-by: Joshua Peek --- actionpack/lib/action_dispatch/middleware/params_parser.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index a42c6598e0..e83cf9236b 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -34,7 +34,7 @@ module ActionDispatch when :xml_simple, :xml_node request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access when :yaml - YAML.load(request.raw_post) + YAML.load(request.body) when :json if request.body.size == 0 {} From e89241c92fbcf68b59d9efb50c21c5040e9f3156 Mon Sep 17 00:00:00 2001 From: rick Date: Sun, 17 May 2009 19:16:11 -0700 Subject: [PATCH 43/45] load the JSON Backend lazily. If the JSON gem is already loaded, use the JSONGem backend by default. --- activesupport/lib/active_support/json.rb | 11 ++++++++--- .../lib/active_support/json/backends/jsongem.rb | 4 +++- .../lib/active_support/json/backends/yaml.rb | 4 +++- activesupport/test/json/decoding_test.rb | 3 +++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb index 5072992cdf..1e8ded12da 100644 --- a/activesupport/lib/active_support/json.rb +++ b/activesupport/lib/active_support/json.rb @@ -40,9 +40,15 @@ module ActiveSupport end class << self - attr_reader :backend delegate :decode, :to => :backend - + + def backend + @backend || begin + self.backend = defined?(::JSON) ? "JSONGem" : "Yaml" + @backend + end + end + def backend=(name) if name.is_a?(Module) @backend = name @@ -77,6 +83,5 @@ module ActiveSupport end ActiveSupport.escape_html_entities_in_json = true -ActiveSupport::JSON.backend = 'Yaml' require 'active_support/json/encoding' diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb index d1a1cdd7d7..649e6301d1 100644 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ b/activesupport/lib/active_support/json/backends/jsongem.rb @@ -1,6 +1,8 @@ +require 'json' unless defined?(JSON) + module ActiveSupport module JSON - ParseError = ::JSON::ParserError + ParseError = ::JSON::ParserError unless const_defined?(:ParseError) module Backends module JSONGem diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb index 1c18fc4801..667016f45d 100644 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ b/activesupport/lib/active_support/json/backends/yaml.rb @@ -2,7 +2,9 @@ require 'active_support/core_ext/string/starts_ends_with' module ActiveSupport module JSON - class ParseError < StandardError + unless const_defined?(:ParseError) + class ParseError < StandardError + end end module Backends diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 7e1bfcca84..09fd0d09ba 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -36,6 +36,9 @@ class TestJSONDecoding < ActiveSupport::TestCase %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["","",""]} } + # load the default JSON backend + ActiveSupport::JSON.backend + backends = %w(Yaml) begin gem 'json', '>= 1.1' From 49afe81a13a98d1878f2400bef11a7b89468dff0 Mon Sep 17 00:00:00 2001 From: Kerry Buckley Date: Mon, 18 May 2009 11:13:51 +0200 Subject: [PATCH 44/45] Report errors in 'all project' rake tasks [#2224 state:resolved] Signed-off-by: Pratik Naik --- Rakefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 58e1247600..fbb7f2213c 100644 --- a/Rakefile +++ b/Rakefile @@ -15,9 +15,11 @@ task :default => :test %w(test isolated_test rdoc pgem package release).each do |task_name| desc "Run #{task_name} task for all projects" task task_name do + errors = [] PROJECTS.each do |project| - system %(cd #{project} && #{env} #{$0} #{task_name}) + system(%(cd #{project} && #{env} #{$0} #{task_name})) || errors << project end + fail("Errors in #{errors.join(', ')}") unless errors.empty? end end From 27de7f150b57a18d4ccdd274f6f8b621b58108c6 Mon Sep 17 00:00:00 2001 From: Benjamin Floering Date: Sun, 17 May 2009 23:35:47 -0700 Subject: [PATCH 45/45] Fixed limited eager loading associations with numbers in the name [#2668 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/associations.rb | 2 +- activerecord/test/cases/associations/eager_test.rb | 4 ++++ activerecord/test/fixtures/people.yml | 5 ++++- activerecord/test/models/person.rb | 1 + activerecord/test/schema/schema.rb | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c5e4df4950..76726b7845 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1668,7 +1668,7 @@ module ActiveRecord def tables_in_string(string) return [] if string.blank? - string.scan(/([\.a-zA-Z_]+).?\./).flatten + string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten end def tables_in_hash(hash) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index d23f86b700..65049c4f87 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -589,6 +589,10 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1) end + def test_limited_eager_with_numeric_in_association + assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'readers.id', :limit => 2, :offset => 0) + end + def test_preload_with_interpolation assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions end diff --git a/activerecord/test/fixtures/people.yml b/activerecord/test/fixtures/people.yml index 3babb1fe59..123673a2af 100644 --- a/activerecord/test/fixtures/people.yml +++ b/activerecord/test/fixtures/people.yml @@ -2,14 +2,17 @@ michael: id: 1 first_name: Michael primary_contact_id: 2 + number1_fan_id: 3 gender: M david: id: 2 first_name: David primary_contact_id: 3 + number1_fan_id: 1 gender: M susan: id: 3 first_name: Susan primary_contact_id: 2 - gender: F \ No newline at end of file + number1_fan_id: 1 + gender: F diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index ec2f684a6e..57fa6418f1 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -10,6 +10,7 @@ class Person < ActiveRecord::Base belongs_to :primary_contact, :class_name => 'Person' has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id' + belongs_to :number1_fan, :class_name => 'Person' named_scope :males, :conditions => { :gender => 'M' } named_scope :females, :conditions => { :gender => 'F' } diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 4ee0ffe132..6e8813d8ab 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -324,6 +324,7 @@ ActiveRecord::Schema.define do t.string :first_name, :null => false t.references :primary_contact t.string :gender, :limit => 1 + t.references :number1_fan t.integer :lock_version, :null => false, :default => 0 end
#{CGI.escapeHTML(name.to_s)}