Skip to content

Commit

Permalink
Add support for mount RackApp, :at => "/sprockets" with a shorthand o…
Browse files Browse the repository at this point in the history
…f mount Sprockets => "/sprockets".

This is different from the match syntax in that it cannot be used for controller/action and it does not 
assume an anchor at the end of the match. 

For instance, in the above example, if the client asked for "/sprockets/foo.js", the Sprockets app would
have a SCRIPT_NAME of "/sprockets" and PATH_INFO of "/foo.js".
  • Loading branch information
Carlhuda committed Mar 8, 2010
1 parent 7942e90 commit f38e2e0
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 10 deletions.
27 changes: 21 additions & 6 deletions actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1,5 +1,3 @@
require "active_support/core_ext/hash/except"

module ActionDispatch
module Routing
class Mapper
Expand Down Expand Up @@ -38,7 +36,7 @@ def initialize(set, scope, args)
end

def to_route
[ app, conditions, requirements, defaults, @options[:as] ]
[ app, conditions, requirements, defaults, @options[:as], @options[:anchor] ]
end

private
Expand Down Expand Up @@ -66,7 +64,7 @@ def using_to_shorthand?(args, options)

# match "account/overview"
def using_match_shorthand?(args, options)
args.present? && options.except(:via).empty? && !args.first.include?(':')
args.present? && options.except(:via, :anchor).empty? && !args.first.include?(':')
end

def normalize_path(path)
Expand All @@ -87,7 +85,7 @@ def conditions
end

def requirements
@requirements ||= (@options[:constraints] || {}).tap do |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) }
end
Expand Down Expand Up @@ -176,7 +174,8 @@ def root(options = {})
end

def match(*args)
@set.add_route(*Mapping.new(@set, @scope, args).to_route)
mapping = Mapping.new(@set, @scope, args).to_route
@set.add_route(*mapping)
self
end
end
Expand Down Expand Up @@ -295,6 +294,7 @@ def match(*args)
options = args.extract_options!

options = (@scope[:options] || {}).merge(options)
options[:anchor] = true unless options.key?(:anchor)

if @scope[:name_prefix] && !options[:as].blank?
options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}"
Expand Down Expand Up @@ -538,6 +538,21 @@ def nested
end
end

def mount(app, options = nil)
if options
path = options.delete(:at)
else
options = app
app, path = options.find { |k, v| k.respond_to?(:call) }
options.delete(app) if app
end

raise "A rack application must be specified" unless path

match(path, options.merge(:to => app, :anchor => false))
self
end

def match(*args)
options = args.extract_options!

Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_dispatch/routing/route.rb
Expand Up @@ -4,7 +4,7 @@ class Route #:nodoc:
attr_reader :app, :conditions, :defaults, :name
attr_reader :path, :requirements

def initialize(app, conditions = {}, requirements = {}, defaults = {}, name = nil)
def initialize(app, conditions, requirements, defaults, name, anchor)
@app = app
@defaults = defaults
@name = name
Expand All @@ -17,7 +17,7 @@ def initialize(app, conditions = {}, requirements = {}, defaults = {}, name = ni

if path = conditions[:path_info]
@path = path
conditions[:path_info] = ::Rack::Mount::Strexp.compile(path, requirements, SEPARATORS)
conditions[:path_info] = ::Rack::Mount::Strexp.compile(path, requirements, SEPARATORS, anchor)
end

@conditions = conditions.inject({}) { |h, (k, v)|
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_dispatch/routing/route_set.rb
Expand Up @@ -293,8 +293,8 @@ def empty?
routes.empty?
end

def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil)
route = Route.new(app, conditions, requirements, defaults, name)
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
route = Route.new(app, conditions, requirements, defaults, name, anchor)
@set.add_route(*route)
named_routes[name] = route if name
routes << route
Expand Down
36 changes: 36 additions & 0 deletions actionpack/test/dispatch/mount_test.rb
@@ -0,0 +1,36 @@
require 'abstract_unit'

class TestRoutingMount < ActionDispatch::IntegrationTest
SprocketsApp = lambda { |env|
[200, {"Content-Type" => "text/html"}, ["#{env["SCRIPT_NAME"]} -- #{env["PATH_INFO"]}"]]
}

Router = ActionDispatch::Routing::RouteSet.new
Router.draw do
mount SprocketsApp, :at => "/sprockets"
mount SprocketsApp => "/shorthand"

scope "/its_a" do
mount SprocketsApp, :at => "/sprocket"
end
end

def app
Router
end

def test_mounting_sets_script_name
get "/sprockets/omg"
assert_equal "/sprockets -- /omg", response.body
end

def test_mounting_works_with_scope
get "/its_a/sprocket/omg"
assert_equal "/its_a/sprocket -- /omg", response.body
end

def test_mounting_with_shorthand
get "/shorthand/omg"
assert_equal "/shorthand -- /omg", response.body
end
end

0 comments on commit f38e2e0

Please sign in to comment.