diff options
Diffstat (limited to 'actionpack/lib/action_dispatch')
14 files changed, 171 insertions, 147 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index bc17cadb38..6e8a5dcb8a 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -18,7 +18,7 @@ module ActionDispatch HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM - HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| + HTTP_NEGOTIATE HTTP_PRAGMA ].each do |env| define_method(env.sub(/^HTTP_/n, '').downcase) do @env[env] end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 6dc563264f..8524bbd993 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -60,7 +60,7 @@ module ActionDispatch # :nodoc: end def status=(status) - @status = ActionDispatch::StatusCodes[status] + @status = Rack::Utils.status_code(status) end # The response code of the request @@ -74,7 +74,7 @@ module ActionDispatch # :nodoc: end def message - StatusCodes::STATUS_CODES[@status] + Rack::Utils::HTTP_STATUS_CODES[@status] end alias_method :status_message, :message diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb deleted file mode 100644 index 3d6ee685ea..0000000000 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'active_support/inflector' - -module ActionDispatch - module StatusCodes #:nodoc: - STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({ - 102 => "Processing", - 207 => "Multi-Status", - 226 => "IM Used", - 422 => "Unprocessable Entity", - 423 => "Locked", - 424 => "Failed Dependency", - 426 => "Upgrade Required", - 507 => "Insufficient Storage", - 510 => "Not Extended" - }).freeze - - def self.[](status) - if status.is_a?(Symbol) - SYMBOL_TO_STATUS_CODE[status] || 500 - else - status.to_i - end - end - - # Provides a symbol-to-fixnum lookup for converting a symbol (like - # :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[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code - hash - }.freeze - end -end diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 8970ccaf07..534390d4aa 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -1,4 +1,5 @@ require 'active_support/json' +require 'action_dispatch/http/request' module ActionDispatch class ParamsParser diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index c5c06f74a2..7d4f0998ce 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -1,4 +1,5 @@ require 'rack/utils' +require 'rack/request' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index bd552b458a..f27f22c7e7 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,4 +1,5 @@ -require "active_support/core_ext/hash/keys" +require 'active_support/core_ext/hash/keys' +require 'rack/request' module ActionDispatch module Session @@ -49,7 +50,7 @@ module ActionDispatch :expire_after => nil, :httponly => true }.freeze - + class OptionsHash < Hash def initialize(by, env, default_options) @session_data = env[CookieStore::ENV_SESSION_KEY] @@ -60,7 +61,7 @@ module ActionDispatch key == :id ? @session_data[:session_id] : super(key) end end - + ENV_SESSION_KEY = "rack.session".freeze ENV_SESSION_OPTIONS_KEY = "rack.session.options".freeze HTTP_SET_COOKIE = "Set-Cookie".freeze @@ -102,7 +103,7 @@ module ActionDispatch def call(env) env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env) env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) - + status, headers, body = @app.call(env) session_data = env[ENV_SESSION_KEY] diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index bd87764f5b..4ebc8a2ab9 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -1,4 +1,5 @@ -require "active_support/core_ext/exception" +require 'active_support/core_ext/exception' +require 'action_dispatch/http/request' module ActionDispatch class ShowExceptions @@ -101,7 +102,7 @@ module ActionDispatch end def status_code(exception) - ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[@@rescue_responses[exception.class.name]] + Rack::Utils.status_code(@@rescue_responses[exception.class.name]) end def render(status, body) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 46163706c3..a6b32e0152 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -19,9 +19,9 @@ module ActionDispatch @constraints.each { |constraint| if constraint.respond_to?(:matches?) && !constraint.matches?(req) - return [417, {}, []] + return [ 417, {}, [] ] elsif constraint.respond_to?(:call) && !constraint.call(req) - return [417, {}, []] + return [ 417, {}, [] ] end } @@ -29,94 +29,138 @@ module ActionDispatch end end - module Base - def initialize(set) - @set = set + class Mapping + def initialize(set, scope, args) + @set, @scope = set, scope + @path, @options = extract_path_and_options(args) end - - def root(options = {}) - match '/', options.merge(:as => :root) + + def to_route + [ app, conditions, requirements, defaults, @options[:as] ] end - - def match(*args) - if args.one? && args.first.is_a?(Hash) - path = args.first.keys.first - options = { :to => args.first.values.first } - else - path = args.first + + private + def extract_path_and_options(args) options = args.extract_options! - end - - conditions, defaults = {}, {} - - path = nil if path == "" - path = "#{@scope[:path]}#{path}" if @scope[:path] - path = Rack::Mount::Utils.normalize_path(path) if path - - raise ArgumentError, "path is required" unless path - constraints = options[:constraints] || {} - unless constraints.is_a?(Hash) - block, constraints = constraints, {} + if args.empty? + path, to = options.find { |name, value| name.is_a?(String) } + options.merge!(:to => to).delete(path) if path + else + path = args.first + end + + [ normalize_path(path), options ] end - blocks = ((@scope[:blocks] || []) + [block]).compact - constraints = (@scope[:constraints] || {}).merge(constraints) - options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) } - conditions[:path_info] = path - requirements = constraints.dup + def normalize_path(path) + path = nil if path == "" + path = "#{@scope[:path]}#{path}" if @scope[:path] + path = Rack::Mount::Utils.normalize_path(path) if path - path_regexp = Rack::Mount::Strexp.compile(path, constraints, SEPARATORS) - segment_keys = Rack::Mount::RegexpWithNamedGroups.new(path_regexp).names - constraints.reject! { |k, v| segment_keys.include?(k.to_s) } - conditions.merge!(constraints) + raise ArgumentError, "path is required" unless path + + path + end - requirements[:controller] ||= @set.controller_constraints - if via = options[:via] - via = Array(via).map { |m| m.to_s.upcase } - conditions[:request_method] = Regexp.union(*via) + def app + Constraints.new( + to.respond_to?(:call) ? to : Routing::RouteSet::Dispatcher.new(:defaults => defaults), + blocks + ) end - defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller] - - app = initialize_app_endpoint(options, defaults) - validate_defaults!(app, defaults, segment_keys) - app = Constraints.new(app, blocks) + def conditions + { :path_info => @path }.merge(constraints).merge(request_method_condition) + end + + def requirements + @requirements ||= returning(@options[:constraints] || {}) do |requirements| + requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints] + @options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) } + requirements[:controller] ||= @set.controller_constraints + end + end - @set.add_route(app, conditions, requirements, defaults, options[:as]) + def defaults + @defaults ||= if to.respond_to?(:call) + { } + else + defaults = case to + when String + controller, action = to.split('#') + { :controller => controller, :action => action } + when Symbol + { :controller => default_controller, :action => to.to_s } + else + { :controller => default_controller } + end + + if defaults[:controller].blank? && segment_keys.exclude?("controller") + raise ArgumentError, "missing :controller" + end + + if defaults[:action].blank? && segment_keys.exclude?("action") + raise ArgumentError, "missing :action" + end + + defaults + end + end - self - end + + def blocks + if @options[:constraints].present? && !@options[:constraints].is_a?(Hash) + block = @options[:constraints] + else + block = nil + end + + ((@scope[:blocks] || []) + [ block ]).compact + end + + def constraints + @constraints ||= requirements.reject { |k, v| segment_keys.include?(k.to_s) || k == :controller } + end - private - def initialize_app_endpoint(options, defaults) - app = nil - - if options[:to].respond_to?(:call) - app = options[:to] - defaults.delete(:controller) - defaults.delete(:action) - elsif options[:to].is_a?(String) - defaults[:controller], defaults[:action] = options[:to].split('#') - elsif options[:to].is_a?(Symbol) - defaults[:action] = options[:to].to_s + def request_method_condition + if via = @options[:via] + via = Array(via).map { |m| m.to_s.upcase } + { :request_method => Regexp.union(*via) } + else + { } end + end + + def segment_keys + @segment_keys ||= Rack::Mount::RegexpWithNamedGroups.new( + Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS) + ).names + end - app || Routing::RouteSet::Dispatcher.new(:defaults => defaults) + def to + @options[:to] + end + + def default_controller + @scope[:controller].to_s if @scope[:controller] end + end - def validate_defaults!(app, defaults, segment_keys) - return unless app.is_a?(Routing::RouteSet::Dispatcher) + module Base + def initialize(set) + @set = set + end - unless defaults.include?(:controller) || segment_keys.include?("controller") - raise ArgumentError, "missing :controller" - end + def root(options = {}) + match '/', options.reverse_merge(:as => :root) + end - unless defaults.include?(:action) || segment_keys.include?("action") - raise ArgumentError, "missing :action" - end - end + def match(*args) + @set.add_route(*Mapping.new(@set, @scope, args).to_route) + self + end end module HttpHelpers @@ -139,15 +183,16 @@ module ActionDispatch def redirect(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {} - path = args.shift || block - path_proc = path.is_a?(Proc) ? path : proc {|params| path % params } - status = options[:status] || 301 + path = args.shift || block + path_proc = path.is_a?(Proc) ? path : proc { |params| path % params } + status = options[:status] || 301 lambda do |env| - req = Rack::Request.new(env) + req = Rack::Request.new(env) params = path_proc.call(env["action_dispatch.request.path_parameters"]) - url = req.scheme + '://' + req.host + params - [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] + url = req.scheme + '://' + req.host + params + + [ status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently'] ] end end @@ -211,11 +256,11 @@ module ActionDispatch self ensure - @scope[:path] = path if path_set + @scope[:path] = path if path_set @scope[:name_prefix] = name_prefix if name_prefix_set - @scope[:controller] = controller if controller_set - @scope[:options] = options - @scope[:blocks] = blocks + @scope[:controller] = controller if controller_set + @scope[:options] = options + @scope[:blocks] = blocks @scope[:constraints] = constraints end @@ -311,12 +356,12 @@ module ActionDispatch with_scope_level(:resource, resource) do yield if block_given? - get "(.:format)", :to => :show, :as => resource.member_name - post "(.:format)", :to => :create - put "(.:format)", :to => :update - delete "(.:format)", :to => :destroy - get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" - get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" + get "(.:format)", :to => :show, :as => resource.member_name + post "(.:format)", :to => :create + put "(.:format)", :to => :update + delete "(.:format)", :to => :destroy + get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}" + get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}" end end @@ -346,8 +391,9 @@ module ActionDispatch yield if block_given? with_scope_level(:collection) do - get "(.:format)", :to => :index, :as => resource.collection_name + get "(.:format)", :to => :index, :as => resource.collection_name post "(.:format)", :to => :create + with_exclusive_name_prefix :new do get "/new(.:format)", :to => :new, :as => resource.singular end @@ -355,9 +401,10 @@ module ActionDispatch with_scope_level(:member) do scope("/:id") do - get "(.:format)", :to => :show, :as => resource.member_name - put "(.:format)", :to => :update + get "(.:format)", :to => :show, :as => resource.member_name + put "(.:format)", :to => :update delete "(.:format)", :to => :destroy + with_exclusive_name_prefix :edit do get "/edit(.:format)", :to => :edit, :as => resource.singular end @@ -473,4 +520,4 @@ module ActionDispatch include Resources end end -end +end
\ No newline at end of file diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index a4dc5e0956..498ad3268c 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -273,7 +273,7 @@ module ActionDispatch # TODO: Move this into Railties if defined?(Rails.application) # Find namespaces in controllers/ directory - Rails.application.configuration.controller_paths.each do |load_path| + Rails.application.config.controller_paths.each do |load_path| load_path = File.expand_path(load_path) Dir["#{load_path}/**/*_controller.rb"].collect do |path| namespaces << File.dirname(path).sub(/#{load_path}\/?/, '') diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb index 9a917f704a..9c215de743 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/dom.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + module ActionDispatch module Assertions module DomAssertions @@ -15,7 +17,7 @@ module ActionDispatch assert_block(full_message) { expected_dom == actual_dom } end - + # The negated form of +assert_dom_equivalent+. # # ==== Examples diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 501a7c4dfb..5686bbdbde 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -28,7 +28,7 @@ module ActionDispatch assert_block("") { true } # to count the assertion elsif type.is_a?(Fixnum) && @response.response_code == type assert_block("") { true } # to count the assertion - elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type] + elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type] assert_block("") { true } # to count the assertion else assert_block(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) { false } diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index d22adfa749..c2dc591ff7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + #-- # Copyright (c) 2006 Assaf Arkin (http://labnotes.org) # Under MIT and/or CC By license. @@ -16,7 +18,7 @@ module ActionDispatch # # Use +css_select+ to select elements without making an assertions, either # from the response HTML or elements selected by the enclosing assertion. - # + # # In addition to HTML responses, you can make the following assertions: # * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations. # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions. @@ -53,8 +55,8 @@ module ActionDispatch # end # # # Selects all list items in unordered lists - # items = css_select("ul>li") - # + # items = css_select("ul>li") + # # # Selects all form tags and then all inputs inside the form # forms = css_select("form") # forms.each do |form| @@ -212,7 +214,7 @@ module ActionDispatch # Otherwise just operate on the response document. root = response_from_page_or_rjs end - + # First or second argument is the selector: string and we pass # all remaining arguments. Array and we pass the argument. Also # accepts selector itself. @@ -225,7 +227,7 @@ module ActionDispatch selector = arg else raise ArgumentError, "Expecting a selector as the first argument" end - + # Next argument is used for equality tests. equals = {} case arg = args.shift @@ -315,10 +317,10 @@ module ActionDispatch # Returns all matches elements. matches end - + def count_description(min, max) #:nodoc: pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')} - + if min && max && (max != min) "between #{min} and #{max} elements" elsif min && !(min == 1 && max == 1) @@ -327,7 +329,7 @@ module ActionDispatch "at most #{max} #{pluralize['element', max]}" end end - + # :call-seq: # assert_select_rjs(id?) { |elements| ... } # assert_select_rjs(statement, id?) { |elements| ... } @@ -344,7 +346,7 @@ module ActionDispatch # that update or insert an element with that identifier. # # Use the first argument to narrow down assertions to only statements - # of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>, + # of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>, # <tt>:show</tt>, <tt>:hide</tt>, <tt>:toggle</tt>, <tt>:remove</tta>, # <tt>:insert_html</tt> and <tt>:redirect</tt>. # @@ -494,7 +496,7 @@ module ActionDispatch # end # end # end - # + # # # # Selects all paragraph tags from within the description of an RSS feed # assert_select_feed :rss, 2.0 do diff --git a/actionpack/lib/action_dispatch/testing/assertions/tag.rb b/actionpack/lib/action_dispatch/testing/assertions/tag.rb index b74dcb1fe4..5c735e61b2 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/tag.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/tag.rb @@ -1,3 +1,5 @@ +require 'action_controller/vendor/html-scanner' + module ActionDispatch module Assertions # Pair of assertions to testing elements in the HTML output of the response. diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 5c127dfe37..2a5f5dcd5c 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -411,7 +411,7 @@ module ActionDispatch # At its simplest, you simply extend IntegrationTest and write your tests # using the get/post methods: # - # require "#{File.dirname(__FILE__)}/test_helper" + # require "test_helper" # # class ExampleTest < ActionController::IntegrationTest # fixtures :people @@ -435,7 +435,7 @@ module ActionDispatch # powerful testing DSL that is specific for your application. You can even # reference any named routes you happen to have defined! # - # require "#{File.dirname(__FILE__)}/test_helper" + # require "test_helper" # # class AdvancedTest < ActionController::IntegrationTest # fixtures :people, :rooms |