diff options
Diffstat (limited to 'actionpack')
31 files changed, 315 insertions, 356 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 064e06bf92..04e44be291 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* +* Renamed the field error CSS class from fieldWithErrors to field_with_errors for consistency. [Jeremy Kemper] + * Add support for shorthand routes like /projects/status(.:format) #4423 [Diego Carrion] * Changed translate helper so that it doesn’t mark every translation as safe HTML. Only keys with a "_html" suffix and keys named "html" are considered to be safe HTML. All other translations are left untouched. [Craig Davey] diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index de95f935c2..2da4dc052c 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -12,7 +12,6 @@ require 'active_support/i18n' module AbstractController extend ActiveSupport::Autoload - autoload :Assigns autoload :Base autoload :Callbacks autoload :Collector diff --git a/actionpack/lib/abstract_controller/assigns.rb b/actionpack/lib/abstract_controller/assigns.rb deleted file mode 100644 index 21459c6d51..0000000000 --- a/actionpack/lib/abstract_controller/assigns.rb +++ /dev/null @@ -1,21 +0,0 @@ -module AbstractController - module Assigns - # This method should return a hash with assigns. - # You can overwrite this configuration per controller. - # :api: public - def view_assigns - hash = {} - variables = instance_variable_names - variables -= protected_instance_variables if respond_to?(:protected_instance_variables) - variables.each { |name| hash[name] = instance_variable_get(name) } - hash - end - - # This method assigns the hash specified in _assigns_hash to the given object. - # :api: private - # TODO Ideally, this should be done on AV::Base.new initialization. - def _evaluate_assigns(object) - view_assigns.each { |k,v| object.instance_variable_set(k, v) } - end - end -end
\ No newline at end of file diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index c12b584144..8500cbd7f2 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -1,4 +1,4 @@ -require 'active_support/ordered_options' +require 'active_support/configurable' module AbstractController class Error < StandardError; end @@ -8,6 +8,8 @@ module AbstractController attr_internal :response_body attr_internal :action_name + include ActiveSupport::Configurable + class << self attr_reader :abstract alias_method :abstract?, :abstract @@ -29,14 +31,6 @@ module AbstractController @descendants ||= [] end - def config - @config ||= ActiveSupport::InheritableOptions.new(superclass < Base ? superclass.config : {}) - end - - def configure - yield config - end - # A list of all internal methods for a controller. This finds the first # abstract superclass of a controller, and gets a list of all public # instance methods on that abstract class. Public instance methods of @@ -99,10 +93,6 @@ module AbstractController abstract! - def config - @config ||= ActiveSupport::InheritableOptions.new(self.class.config) - end - # Calls the action going through the entire action dispatch stack. # # The actual method that is called is determined by calling @@ -133,6 +123,7 @@ module AbstractController end private + # Returns true if the name can be considered an action. This can # be overridden in subclasses to modify the semantics of what # can be considered an action. diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index 53cf6b3931..4374b439d0 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -8,7 +8,6 @@ module AbstractController included do class_attribute :_helpers - delegate :_helpers, :to => :'self.class' self._helpers = Module.new end diff --git a/actionpack/lib/abstract_controller/logger.rb b/actionpack/lib/abstract_controller/logger.rb index 9318f5e369..0b196119f4 100644 --- a/actionpack/lib/abstract_controller/logger.rb +++ b/actionpack/lib/abstract_controller/logger.rb @@ -6,7 +6,7 @@ module AbstractController extend ActiveSupport::Concern included do - cattr_accessor :logger + config_accessor :logger extend ActiveSupport::Benchmarkable end end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 2e94a20d9d..092fe98588 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -65,8 +65,11 @@ module ActionController @subclasses ||= [] end + # TODO Move this to the appropriate module + config_accessor :assets_dir, :asset_path, :javascripts_dir, :stylesheets_dir + ActiveSupport.run_load_hooks(:action_controller, self) end end -require "action_controller/deprecated/base" +require "action_controller/deprecated/base"
\ No newline at end of file diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 0da0ca1893..4105f9e14f 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -63,12 +63,10 @@ module ActionController #:nodoc: included do extend ConfigMethods - delegate :perform_caching, :perform_caching=, :to => :config - singleton_class.delegate :perform_caching, :perform_caching=, :to => :config - self.perform_caching = true + config_accessor :perform_caching + self.perform_caching = true if perform_caching.nil? end - def caching_allowed? request.get? && response.status == 200 end diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 20df3a1a69..cefd1f48c0 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -44,8 +44,8 @@ module ActionController #:nodoc: # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>Rails.root + "/public"</tt>). Changing # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your # web server to look in the new location for cached files. - singleton_class.delegate :page_cache_directory, :page_cache_directory=, :to => :config - self.page_cache_directory = '' + config_accessor :page_cache_directory + self.page_cache_directory ||= '' ## # :singleton-method: @@ -53,8 +53,8 @@ module ActionController #:nodoc: # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>. # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps. - singleton_class.delegate :page_cache_extension, :page_cache_extension=, :to => :config - self.page_cache_extension = '.html' + config_accessor :page_cache_extension + self.page_cache_extension ||= '.html' end module ClassMethods diff --git a/actionpack/lib/action_controller/deprecated/base.rb b/actionpack/lib/action_controller/deprecated/base.rb index 57203ce95f..3975afcaf0 100644 --- a/actionpack/lib/action_controller/deprecated/base.rb +++ b/actionpack/lib/action_controller/deprecated/base.rb @@ -1,33 +1,16 @@ module ActionController class Base - class << self - def deprecated_config_accessor(option, message = nil) - deprecated_config_reader(option, message) - deprecated_config_writer(option, message) + # Deprecated methods. Wrap them in a module so they can be overwritten by plugins + # (like the verify method.) + module DeprecatedBehavior #:nodoc: + def relative_url_root + ActiveSupport::Deprecation.warn "ActionController::Base.relative_url_root is ineffective. " << + "Please stop using it.", caller end - def deprecated_config_reader(option, message = nil) - message ||= "Reading #{option} directly from ActionController::Base is deprecated. " \ - "Please read it from config.#{option}" - - self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{option} - ActiveSupport::Deprecation.warn #{message.inspect}, caller - config.#{option} - end - RUBY - end - - def deprecated_config_writer(option, message = nil) - message ||= "Setting #{option} directly on ActionController::Base is deprecated. " \ - "Please set it on config.action_controller.#{option}" - - self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{option}=(val) - ActiveSupport::Deprecation.warn #{message.inspect}, caller - config.#{option} = val - end - RUBY + def relative_url_root= + ActiveSupport::Deprecation.warn "ActionController::Base.relative_url_root= is ineffective. " << + "Please stop using it.", caller end def consider_all_requests_local @@ -125,9 +108,7 @@ module ActionController def use_accept_header=(val) use_accept_header end - end - module DeprecatedBehavior # This method has been moved to ActionDispatch::Request.filter_parameters def filter_parameter_logging(*args, &block) ActiveSupport::Deprecation.warn("Setting filter_parameter_logging in ActionController is deprecated and has no longer effect, please set 'config.filter_parameters' in config/application.rb instead", caller) @@ -146,17 +127,6 @@ module ActionController extend DeprecatedBehavior - deprecated_config_writer :session_options - deprecated_config_writer :session_store - - deprecated_config_accessor :assets_dir - deprecated_config_accessor :asset_path - deprecated_config_accessor :helpers_path - deprecated_config_accessor :javascripts_dir - deprecated_config_accessor :page_cache_directory - deprecated_config_accessor :relative_url_root, "relative_url_root is ineffective. Please stop using it" - deprecated_config_accessor :stylesheets_dir - delegate :consider_all_requests_local, :consider_all_requests_local=, :allow_concurrency, :allow_concurrency=, :to => :"self.class" end diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 02722360f1..d49465fa0b 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -21,8 +21,8 @@ module ActionController delegate :default_charset=, :to => "ActionDispatch::Response" end - # cattr_reader :protected_instance_variables - cattr_accessor :protected_instance_variables + # TODO: Update protected instance variables list + config_accessor :protected_instance_variables self.protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller @action_name diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 82bedc3fad..1110d7c117 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -52,8 +52,8 @@ module ActionController include AbstractController::Helpers included do - class_attribute :helpers_path - self.helpers_path = [] + config_accessor :helpers_path + self.helpers_path ||= [] end module ClassMethods diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index 47759aa2fe..0be07cd1fc 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -79,12 +79,12 @@ module ActionController add :js do |js, options| self.content_type ||= Mime::JS - self.response_body = js.respond_to?(:to_js) ? js.to_js : js + self.response_body = js.respond_to?(:to_js) ? js.to_js(options) : js end add :xml do |xml, options| self.content_type ||= Mime::XML - self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml + self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml end add :update do |proc, options| diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 39a809657b..2ba0d6e5cd 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -4,6 +4,45 @@ module ActionController #:nodoc: class InvalidAuthenticityToken < ActionControllerError #:nodoc: end + # Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current + # web application, not a forged link from another site, is done by embedding a token based on a random + # string stored in the session (which an attacker wouldn't know) in all forms and Ajax requests generated + # by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript + # requests are checked, so this will not protect your XML API (presumably you'll have a different + # authentication scheme there anyway). Also, GET requests are not protected as these should be + # idempotent anyway. + # + # This is turned on with the <tt>protect_from_forgery</tt> method, which will check the token and raise an + # ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the + # error message in production by editing public/422.html. A call to this method in ApplicationController is + # generated by default in post-Rails 2.0 applications. + # + # The token parameter is named <tt>authenticity_token</tt> by default. If you are generating an HTML form + # manually (without the use of Rails' <tt>form_for</tt>, <tt>form_tag</tt> or other helpers), you have to + # include a hidden field named like that and set its value to what is returned by + # <tt>form_authenticity_token</tt>. + # + # Request forgery protection is disabled by default in test environment. If you are upgrading from Rails + # 1.x, add this to config/environments/test.rb: + # + # # Disable request forgery protection in test environment + # config.action_controller.allow_forgery_protection = false + # + # == Learn more about CSRF (Cross-Site Request Forgery) attacks + # + # Here are some resources: + # * http://isc.sans.org/diary.html?storyid=1750 + # * http://en.wikipedia.org/wiki/Cross-site_request_forgery + # + # Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application. + # There are a few guidelines you should follow: + # + # * Keep your GET requests safe and idempotent. More reading material: + # * http://www.xml.com/pub/a/2002/04/24/deviant.html + # * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 + # * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look + # for "Expires: at end of session" + # module RequestForgeryProtection extend ActiveSupport::Concern @@ -12,54 +51,17 @@ module ActionController #:nodoc: included do # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ # sets it to <tt>:authenticity_token</tt> by default. - config.request_forgery_protection_token ||= :authenticity_token + config_accessor :request_forgery_protection_token + self.request_forgery_protection_token ||= :authenticity_token # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. - config.allow_forgery_protection ||= true + config_accessor :allow_forgery_protection + self.allow_forgery_protection = true if allow_forgery_protection.nil? helper_method :form_authenticity_token helper_method :protect_against_forgery? end - # Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current - # web application, not a forged link from another site, is done by embedding a token based on a random - # string stored in the session (which an attacker wouldn't know) in all forms and Ajax requests generated - # by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript - # requests are checked, so this will not protect your XML API (presumably you'll have a different - # authentication scheme there anyway). Also, GET requests are not protected as these should be - # idempotent anyway. - # - # This is turned on with the <tt>protect_from_forgery</tt> method, which will check the token and raise an - # ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the - # error message in production by editing public/422.html. A call to this method in ApplicationController is - # generated by default in post-Rails 2.0 applications. - # - # The token parameter is named <tt>authenticity_token</tt> by default. If you are generating an HTML form - # manually (without the use of Rails' <tt>form_for</tt>, <tt>form_tag</tt> or other helpers), you have to - # include a hidden field named like that and set its value to what is returned by - # <tt>form_authenticity_token</tt>. - # - # Request forgery protection is disabled by default in test environment. If you are upgrading from Rails - # 1.x, add this to config/environments/test.rb: - # - # # Disable request forgery protection in test environment - # config.action_controller.allow_forgery_protection = false - # - # == Learn more about CSRF (Cross-Site Request Forgery) attacks - # - # Here are some resources: - # * http://isc.sans.org/diary.html?storyid=1750 - # * http://en.wikipedia.org/wiki/Cross-site_request_forgery - # - # Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application. - # There are a few guidelines you should follow: - # - # * Keep your GET requests safe and idempotent. More reading material: - # * http://www.xml.com/pub/a/2002/04/24/deviant.html - # * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 - # * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look - # for "Expires: at end of session" - # module ClassMethods # Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked. # @@ -79,22 +81,6 @@ module ActionController #:nodoc: self.request_forgery_protection_token ||= :authenticity_token before_filter :verify_authenticity_token, options end - - def request_forgery_protection_token - config.request_forgery_protection_token - end - - def request_forgery_protection_token=(val) - config.request_forgery_protection_token = val - end - - def allow_forgery_protection - config.allow_forgery_protection - end - - def allow_forgery_protection=(val) - config.allow_forgery_protection = val - end end protected @@ -104,22 +90,6 @@ module ActionController #:nodoc: before_filter :verify_authenticity_token, options end - def request_forgery_protection_token - config.request_forgery_protection_token - end - - def request_forgery_protection_token=(val) - config.request_forgery_protection_token = val - end - - def allow_forgery_protection - config.allow_forgery_protection - end - - def allow_forgery_protection=(val) - config.allow_forgery_protection = val - end - # The actual before_filter that is used. Modify this to change how you handle unverified requests. def verify_authenticity_token verified_request? || raise(ActionController::InvalidAuthenticityToken) @@ -146,7 +116,7 @@ module ActionController #:nodoc: end def protect_against_forgery? - config.allow_forgery_protection + allow_forgery_protection end end end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index b029434004..0e3cdffadc 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -13,64 +13,51 @@ module ActionController class Railtie < Rails::Railtie config.action_controller = ActiveSupport::OrderedOptions.new - ad = config.action_dispatch - config.action_controller.singleton_class.send(:define_method, :session) do - ActiveSupport::Deprecation.warn "config.action_controller.session has been " \ - "renamed to config.action_dispatch.session.", caller - ad.session - end + config.action_controller.singleton_class.tap do |d| + d.send(:define_method, :session) do + ActiveSupport::Deprecation.warn "config.action_controller.session has been deprecated. " << + "Please use Rails.application.config.session_store instead.", caller + end - config.action_controller.singleton_class.send(:define_method, :session=) do |val| - ActiveSupport::Deprecation.warn "config.action_controller.session has been " \ - "renamed to config.action_dispatch.session.", caller - ad.session = val - end + d.send(:define_method, :session=) do |val| + ActiveSupport::Deprecation.warn "config.action_controller.session= has been deprecated. " << + "Please use config.session_store(name, options) instead.", caller + end - config.action_controller.singleton_class.send(:define_method, :session_store) do - ActiveSupport::Deprecation.warn "config.action_controller.session_store has been " \ - "renamed to config.action_dispatch.session_store.", caller - ad.session_store - end + d.send(:define_method, :session_store) do + ActiveSupport::Deprecation.warn "config.action_controller.session_store has been deprecated. " << + "Please use Rails.application.config.session_store instead.", caller + end - config.action_controller.singleton_class.send(:define_method, :session_store=) do |val| - ActiveSupport::Deprecation.warn "config.action_controller.session_store has been " \ - "renamed to config.action_dispatch.session_store.", caller - ad.session_store = val + d.send(:define_method, :session_store=) do |val| + ActiveSupport::Deprecation.warn "config.action_controller.session_store= has been deprecated. " << + "Please use config.session_store(name, options) instead.", caller + end end log_subscriber :action_controller, ActionController::Railties::LogSubscriber.new - initializer "action_controller.logger" do - ActiveSupport.on_load(:action_controller) { self.logger ||= Rails.logger } - end - - initializer "action_controller.page_cache_directory" do - ActiveSupport.on_load(:action_controller) do - self.page_cache_directory = Rails.public_path - end - end - initializer "action_controller.set_configs" do |app| paths = app.config.paths ac = app.config.action_controller - ac.assets_dir = paths.public.to_a.first - ac.javascripts_dir = paths.public.javascripts.to_a.first - ac.stylesheets_dir = paths.public.stylesheets.to_a.first + ac.assets_dir ||= paths.public.to_a.first + ac.javascripts_dir ||= paths.public.javascripts.to_a.first + ac.stylesheets_dir ||= paths.public.stylesheets.to_a.first + ac.page_cache_directory ||= paths.public.to_a.first + ac.helpers_path ||= paths.app.helpers.to_a ActiveSupport.on_load(:action_controller) do self.config.merge!(ac) end end - initializer "action_controller.initialize_framework_caches" do - ActiveSupport.on_load(:action_controller) { self.cache_store ||= RAILS_CACHE } + initializer "action_controller.logger" do + ActiveSupport.on_load(:action_controller) { self.logger ||= Rails.logger } end - initializer "action_controller.set_helpers_path" do |app| - ActiveSupport.on_load(:action_controller) do - self.helpers_path = app.config.paths.app.helpers.to_a - end + initializer "action_controller.initialize_framework_caches" do + ActiveSupport.on_load(:action_controller) { self.cache_store ||= RAILS_CACHE } end initializer "action_controller.url_helpers" do |app| diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index b3758218a2..2b9b34961e 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -36,6 +36,7 @@ module ActionController end def teardown_subscriptions + ActiveSupport::Notifications.unsubscribe("action_view.render_template") ActiveSupport::Notifications.unsubscribe("action_view.render_template!") end @@ -282,165 +283,143 @@ module ActionController # # assert_redirected_to page_url(:title => 'foo') class TestCase < ActiveSupport::TestCase - include ActionDispatch::TestProcess - include ActionController::TemplateAssertions + module Behavior + extend ActiveSupport::Concern + include ActionDispatch::TestProcess - attr_reader :response, :request + attr_reader :response, :request - # Executes a request simulating GET HTTP method and set/volley the response - def get(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "GET") - end + module ClassMethods - # Executes a request simulating POST HTTP method and set/volley the response - def post(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "POST") - end + # Sets the controller class name. Useful if the name can't be inferred from test class. + # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>. + def tests(controller_class) + self.controller_class = controller_class + end + + def controller_class=(new_class) + prepare_controller_class(new_class) if new_class + write_inheritable_attribute(:controller_class, new_class) + end - # Executes a request simulating PUT HTTP method and set/volley the response - def put(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "PUT") - end + def controller_class + if current_controller_class = read_inheritable_attribute(:controller_class) + current_controller_class + else + self.controller_class = determine_default_controller_class(name) + end + end - # Executes a request simulating DELETE HTTP method and set/volley the response - def delete(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "DELETE") - end + def determine_default_controller_class(name) + name.sub(/Test$/, '').constantize + rescue NameError + nil + end - # Executes a request simulating HEAD HTTP method and set/volley the response - def head(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "HEAD") - end + def prepare_controller_class(new_class) + new_class.send :include, ActionController::TestCase::RaiseActionExceptions + end - def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) - @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') - returning __send__(request_method, action, parameters, session, flash) do - @request.env.delete 'HTTP_X_REQUESTED_WITH' - @request.env.delete 'HTTP_ACCEPT' end - end - alias xhr :xml_http_request - - def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') - # Sanity check for required instance variables so we can give an - # understandable error message. - %w(@routes @controller @request @response).each do |iv_name| - if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? - raise "#{iv_name} is nil: make sure you set it in your test's setup method." - end + + # Executes a request simulating GET HTTP method and set/volley the response + def get(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "GET") end - @request.recycle! - @response.recycle! - @controller.response_body = nil - @controller.formats = nil - @controller.params = nil - - @html_document = nil - @request.env['REQUEST_METHOD'] = http_method - - parameters ||= {} - @request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) - - @request.session = ActionController::TestSession.new(session) unless session.nil? - @request.session["flash"] = @request.flash.update(flash || {}) - @request.session["flash"].sweep - - @controller.request = @request - @controller.params.merge!(parameters) - build_request_uri(action, parameters) - Base.class_eval { include Testing } - @controller.process_with_new_base_test(@request, @response) - @request.session.delete('flash') if @request.session['flash'].blank? - @response - end + # Executes a request simulating POST HTTP method and set/volley the response + def post(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "POST") + end - include ActionDispatch::Assertions + # Executes a request simulating PUT HTTP method and set/volley the response + def put(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "PUT") + end - # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline - # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular - # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else - # than 0.0.0.0. - # - # The exception is stored in the exception accessor for further inspection. - module RaiseActionExceptions - def self.included(base) - base.class_eval do - attr_accessor :exception - protected :exception, :exception= - end + # Executes a request simulating DELETE HTTP method and set/volley the response + def delete(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "DELETE") end - protected - def rescue_action_without_handler(e) - self.exception = e + # Executes a request simulating HEAD HTTP method and set/volley the response + def head(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "HEAD") + end - if request.remote_addr == "0.0.0.0" - raise(e) - else - super(e) + def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) + @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' + @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') + returning __send__(request_method, action, parameters, session, flash) do + @request.env.delete 'HTTP_X_REQUESTED_WITH' + @request.env.delete 'HTTP_ACCEPT' + end + end + alias xhr :xml_http_request + + def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') + # Sanity check for required instance variables so we can give an + # understandable error message. + %w(@routes @controller @request @response).each do |iv_name| + if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? + raise "#{iv_name} is nil: make sure you set it in your test's setup method." end end - end - setup :setup_controller_request_and_response + @request.recycle! + @response.recycle! + @controller.response_body = nil + @controller.formats = nil + @controller.params = nil - @@controller_class = nil + @html_document = nil + @request.env['REQUEST_METHOD'] = http_method - class << self - # Sets the controller class name. Useful if the name can't be inferred from test class. - # Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>. - def tests(controller_class) - self.controller_class = controller_class - end + parameters ||= {} + @request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) - def controller_class=(new_class) - prepare_controller_class(new_class) if new_class - write_inheritable_attribute(:controller_class, new_class) - end + @request.session = ActionController::TestSession.new(session) unless session.nil? + @request.session["flash"] = @request.flash.update(flash || {}) + @request.session["flash"].sweep - def controller_class - if current_controller_class = read_inheritable_attribute(:controller_class) - current_controller_class - else - self.controller_class = determine_default_controller_class(name) - end + @controller.request = @request + @controller.params.merge!(parameters) + build_request_uri(action, parameters) + Base.class_eval { include Testing } + @controller.process_with_new_base_test(@request, @response) + @request.session.delete('flash') if @request.session['flash'].blank? + @response end - def determine_default_controller_class(name) - name.sub(/Test$/, '').constantize - rescue NameError - nil - end + def setup_controller_request_and_response + @request = TestRequest.new + @response = TestResponse.new - def prepare_controller_class(new_class) - new_class.send :include, RaiseActionExceptions - end - end + if klass = self.class.controller_class + @controller ||= klass.new rescue nil + end - def setup_controller_request_and_response - @request = TestRequest.new - @response = TestResponse.new + @request.env.delete('PATH_INFO') - if klass = self.class.controller_class - @controller ||= klass.new rescue nil + if @controller + @controller.request = @request + @controller.params = {} + end end - @request.env.delete('PATH_INFO') - - if @controller - @controller.request = @request - @controller.params = {} + # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local + def rescue_action_in_public! + @request.remote_addr = '208.77.188.166' # example.com end - end - # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local - def rescue_action_in_public! - @request.remote_addr = '208.77.188.166' # example.com - end + included do + include ActionController::TemplateAssertions + include ActionDispatch::Assertions + setup :setup_controller_request_and_response + end private + def build_request_uri(action, parameters) unless @request.env["PATH_INFO"] options = @controller.__send__(:url_options).merge(parameters) @@ -458,4 +437,33 @@ module ActionController end end end + + # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline + # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular + # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else + # than 0.0.0.0. + # + # The exception is stored in the exception accessor for further inspection. + module RaiseActionExceptions + def self.included(base) + base.class_eval do + attr_accessor :exception + protected :exception, :exception= + end + end + + protected + def rescue_action_without_handler(e) + self.exception = e + + if request.remote_addr == "0.0.0.0" + raise(e) + else + super(e) + end + end + end + + include Behavior + end end diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index fb236dce53..db17615d92 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -128,7 +128,7 @@ module ActionDispatch when String options when nil, Hash - _router.url_for(url_options.merge(options || {})) + _router.url_for(url_options.merge((options || {}).symbolize_keys)) else polymorphic_url(options) end diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index a7650c0050..d9f09b5dc5 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/object/blank' module ActionView ActiveSupport.on_load(:action_view) do class ActionView::Base - @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe } + @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe } cattr_accessor :field_error_proc end end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 68efe8fc5f..210f148c02 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -102,7 +102,7 @@ module ActionView escape = true options when Hash - options = { :only_path => options[:host].nil? }.update(options.to_hash.symbolize_keys) + options = { :only_path => options[:host].nil? }.update(options.symbolize_keys) escape = options.key?(:escape) ? options.delete(:escape) : false super when :back diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index beda7743bf..f6417d5c2c 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -31,8 +31,8 @@ module ActionView include ActionController::PolymorphicRoutes include ActionController::RecordIdentifier + include AbstractController::Helpers include ActionView::Helpers - include ActionController::Helpers class_inheritable_accessor :helper_class attr_accessor :controller, :output_buffer, :rendered diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index acf887ee4a..f3ff258016 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -143,6 +143,12 @@ class BasicController end end +class ActionDispatch::IntegrationTest < ActiveSupport::TestCase + setup do + @routes = SharedTestRoutes + end +end + class ActionController::IntegrationTest < ActiveSupport::TestCase def self.build_app(routes = nil) RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware| @@ -275,4 +281,4 @@ module ActionController class Base include SharedTestRoutes.url_helpers end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index cb3e848dfa..4ef6fa4000 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 #-- # Copyright (c) 2006 Assaf Arkin (http://labnotes.org) # Under MIT and/or CC By license. @@ -347,7 +348,6 @@ class AssertSelectTest < ActionController::TestCase assert_select str, :text => "\343\203\201\343\202\261\343\203\203\343\203\210" assert_select str, "\343\203\201\343\202\261\343\203\203\343\203\210" if str.respond_to?(:force_encoding) - str.force_encoding(Encoding::UTF_8) assert_select str, /\343\203\201..\343\203\210/u assert_raise(Assertion) { assert_select str, /\343\203\201.\343\203\210/u } else diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index e1c1128753..48be7571ea 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'rbconfig' # The view_paths array must be set on Base and not LayoutTest so that LayoutTest's inherited # method has access to the view_paths array when looking for a layout to automatically assign. @@ -209,7 +210,7 @@ class LayoutStatusIsRenderedTest < ActionController::TestCase end end -unless RUBY_PLATFORM =~ /mswin|mingw/ +unless Config::CONFIG['host_os'] =~ /mswin|mingw/ class LayoutSymlinkedTest < LayoutTest layout "symlinked/symlinked_layout" end diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index 2580ada88b..5958b18d80 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -3,6 +3,14 @@ require 'controller/fake_models' require 'pathname' class RenderJsonTest < ActionController::TestCase + class JsonRenderable + def as_json(options={}) + hash = { :a => :b, :c => :d, :e => :f } + hash.except!(*options[:except]) if options[:except] + hash + end + end + class TestController < ActionController::Base protect_from_forgery @@ -37,6 +45,10 @@ class RenderJsonTest < ActionController::TestCase def render_json_with_render_to_string render :json => {:hello => render_to_string(:partial => 'partial')} end + + def render_json_with_extra_options + render :json => JsonRenderable.new, :except => [:c, :e] + end end tests TestController @@ -91,4 +103,10 @@ class RenderJsonTest < ActionController::TestCase assert_equal '{"hello":"partial html"}', @response.body assert_equal 'application/json', @response.content_type end + + def test_render_json_forwards_extra_options + get :render_json_with_extra_options + assert_equal '{"a":"b"}', @response.body + assert_equal 'application/json', @response.content_type + end end diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index 4da6c954cf..4bf867fa41 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -3,6 +3,13 @@ require 'controller/fake_models' require 'pathname' class RenderXmlTest < ActionController::TestCase + class XmlRenderable + def to_xml(options) + options[:root] ||= "i-am-xml" + "<#{options[:root]}/>" + end + end + class TestController < ActionController::Base protect_from_forgery @@ -20,13 +27,7 @@ class RenderXmlTest < ActionController::TestCase end def render_with_to_xml - to_xmlable = Class.new do - def to_xml - "<i-am-xml/>" - end - end.new - - render :xml => to_xmlable + render :xml => XmlRenderable.new end def formatted_xml_erb @@ -35,6 +36,10 @@ class RenderXmlTest < ActionController::TestCase def render_xml_with_custom_content_type render :xml => "<blah/>", :content_type => "application/atomsvc+xml" end + + def render_xml_with_custom_options + render :xml => XmlRenderable.new, :root => "i-am-THE-xml" + end end tests TestController @@ -58,6 +63,11 @@ class RenderXmlTest < ActionController::TestCase assert_equal "<i-am-xml/>", @response.body end + def test_rendering_xml_should_call_to_xml_with_extra_options + get :render_xml_with_custom_options + assert_equal "<i-am-THE-xml/>", @response.body + end + def test_rendering_with_object_location_should_set_header_with_url_for with_routing do |set| set.draw do |map| diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 30c9a65b7c..36b8055810 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -25,7 +25,7 @@ class SendFileController < ActionController::Base end def multibyte_text_data - send_data("Кирилица\n祝您好運", options) + send_data("Кирилица\n祝您好運.", options) end end @@ -128,7 +128,7 @@ class SendFileTest < ActionController::TestCase assert_equal 'image/png', @controller.content_type end - + def test_send_file_headers_with_bad_symbol options = { diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index fc7773dffe..907acf9573 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -257,10 +257,24 @@ module AbstractController assert_equal second_class.default_url_options[:host], second_host end + def test_with_stringified_keys + assert_equal("/c", W.new.url_for('controller' => 'c', 'only_path' => true)) + assert_equal("/c/a", W.new.url_for('controller' => 'c', 'action' => 'a', 'only_path' => true)) + end + + def test_with_hash_with_indifferent_access + W.default_url_options[:controller] = 'd' + W.default_url_options[:only_path] = false + assert_equal("/c", W.new.url_for(HashWithIndifferentAccess.new('controller' => 'c', 'only_path' => true))) + + W.default_url_options[:action] = 'b' + assert_equal("/c/a", W.new.url_for(HashWithIndifferentAccess.new('controller' => 'c', 'action' => 'a', 'only_path' => true))) + end + private def extract_params(url) url.split('?', 2).last.split('&').sort end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 5bca476b27..b508996467 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -237,8 +237,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest AltRoutes = ActionDispatch::Routing::RouteSet.new(AltRequest) AltRoutes.draw do - get "/" => XHeader.new, :constraints => {:x_header => /HEADER/} - get "/" => AltApp.new + get "/" => TestRoutingMapper::TestAltApp::XHeader.new, :constraints => {:x_header => /HEADER/} + get "/" => TestRoutingMapper::TestAltApp::AltApp.new end def app @@ -1000,6 +1000,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_assert_recognizes_account_overview + with_test_routes do + assert_recognizes({:controller => "account", :action => "overview"}, "/account/overview") + end + end + private def with_test_routes yield diff --git a/actionpack/test/template/active_model_helper_test.rb b/actionpack/test/template/active_model_helper_test.rb index 8deeb78eab..b1705072c2 100644 --- a/actionpack/test/template/active_model_helper_test.rb +++ b/actionpack/test/template/active_model_helper_test.rb @@ -27,14 +27,14 @@ class ActiveModelHelperTest < ActionView::TestCase def test_text_area_with_errors assert_dom_equal( - %(<div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>), + %(<div class="field_with_errors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>), text_area("post", "body") ) end def test_text_field_with_errors assert_dom_equal( - %(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>), text_field("post", "author_name") ) end @@ -42,11 +42,11 @@ class ActiveModelHelperTest < ActionView::TestCase def test_field_error_proc old_proc = ActionView::Base.field_error_proc ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| - %(<div class=\"fieldWithErrors\">#{html_tag} <span class="error">#{[instance.error_message].join(', ')}</span></div>).html_safe + %(<div class=\"field_with_errors\">#{html_tag} <span class="error">#{[instance.error_message].join(', ')}</span></div>).html_safe end assert_dom_equal( - %(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /> <span class="error">can't be empty</span></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /> <span class="error">can't be empty</span></div>), text_field("post", "author_name") ) ensure diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index b4f3f82b29..abb0e1df93 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -3,9 +3,6 @@ require 'abstract_unit' class FormTagHelperTest < ActionView::TestCase tests ActionView::Helpers::FormTagHelper - # include ActiveSupport::Configurable - # DEFAULT_CONFIG = ActionView::DEFAULT_CONFIG - def setup super @controller = BasicController.new diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 9962b7af3f..8b6c107a21 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -1,3 +1,4 @@ +# encoding: us-ascii require 'abstract_unit' require 'testing_sandbox' begin |