diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 31e1b26afd54b909c40d6eb27e9e076a1b93aa5d..6ae3940e6d10ba357ba306e8c8f1778063a65969 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -361,7 +361,6 @@ class Base < AbstractController::Base
}.freeze
class << self
-
def mailer_name
@mailer_name ||= name.underscore
end
@@ -725,28 +724,6 @@ def insert_part(container, response, charset) #:nodoc:
container.add_part(part)
end
- module DeprecatedUrlOptions
- def default_url_options
- deprecated_url_options
- end
-
- def default_url_options=(val)
- deprecated_url_options
- end
-
- def deprecated_url_options
- raise "You can no longer call ActionMailer::Base.default_url_options " \
- "directly. You need to set config.action_mailer.default_url_options. " \
- "If you are using ActionMailer standalone, you need to include the " \
- "routing url_helpers directly."
- end
- end
-
- # This module will complain if the user tries to set default_url_options
- # directly instead of through the config object. In Action Mailer's Railtie,
- # we include the router's url_helpers, which will override this module.
- extend DeprecatedUrlOptions
-
ActiveSupport.run_load_hooks(:action_mailer, self)
end
end
diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb
index ce6d8cc5b5b230729f5bc622f547ac9a23d966c1..a2b00addc9c9026523dfbec22c59b39e24eb69fc 100644
--- a/actionmailer/lib/action_mailer/railtie.rb
+++ b/actionmailer/lib/action_mailer/railtie.rb
@@ -1,5 +1,6 @@
require "action_mailer"
require "rails"
+require "abstract_controller/railties/routes_helpers"
module ActionMailer
class Railtie < Rails::Railtie
@@ -18,9 +19,11 @@ class Railtie < Rails::Railtie
options.stylesheets_dir ||= paths.public.stylesheets.to_a.first
ActiveSupport.on_load(:action_mailer) do
- include app.routes.url_helpers
+ include AbstractController::UrlFor
+ extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
+ include app.routes.mounted_helpers(:app)
options.each { |k,v| send("#{k}=", v) }
end
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb
index f8fc79936f54644db7d2fb273c0a5286f725a394..cc5878c88ea5c37b0cdcc5ab8181c6122e98d2f5 100644
--- a/actionpack/lib/abstract_controller.rb
+++ b/actionpack/lib/abstract_controller.rb
@@ -24,4 +24,5 @@ module AbstractController
autoload :Translation
autoload :AssetPaths
autoload :ViewPaths
+ autoload :UrlFor
end
diff --git a/actionpack/lib/abstract_controller/railties/routes_helpers.rb b/actionpack/lib/abstract_controller/railties/routes_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dec1e9d6d92e87f0c57ab0e52214428636f2d63f
--- /dev/null
+++ b/actionpack/lib/abstract_controller/railties/routes_helpers.rb
@@ -0,0 +1,18 @@
+module AbstractController
+ module Railties
+ module RoutesHelpers
+ def self.with(routes)
+ Module.new do
+ define_method(:inherited) do |klass|
+ super(klass)
+ if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) }
+ klass.send(:include, namespace._railtie.routes.url_helpers)
+ else
+ klass.send(:include, routes.url_helpers)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index b81d5954eb9c8a2b8335245438bcd7682e3aa509..5d9b35d297a3f3488ac9ae803bde2318731d37ba 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -52,6 +52,7 @@ def view_context_class
if controller.respond_to?(:_routes)
include controller._routes.url_helpers
+ include controller._routes.mounted_helpers
end
# TODO: Fix RJS to not require this
diff --git a/actionpack/lib/abstract_controller/url_for.rb b/actionpack/lib/abstract_controller/url_for.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2e9de22ecda95caa15b2bb73f2d9333380e6892e
--- /dev/null
+++ b/actionpack/lib/abstract_controller/url_for.rb
@@ -0,0 +1,28 @@
+module AbstractController
+ module UrlFor
+ extend ActiveSupport::Concern
+
+ include ActionDispatch::Routing::UrlFor
+
+ def _routes
+ raise "In order to use #url_for, you must include routing helpers explicitly. " \
+ "For instance, `include Rails.application.routes.url_helpers"
+ end
+
+ module ClassMethods
+ def _routes
+ nil
+ end
+
+ def action_methods
+ @action_methods ||= begin
+ if _routes
+ super - _routes.named_routes.helper_names
+ else
+ super
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 7a1464c2aae0b8f0080550ee7fd60b630e9622b3..b37bc0212788d935935b59c9fa5d6c7bc8441c1b 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -221,11 +221,6 @@ def self.without_modules(*modules)
# Rails 2.x compatibility
include ActionController::Compatibility
- def self.inherited(klass)
- super
- klass.helper :all if klass.superclass == ActionController::Base
- end
-
ActiveSupport.run_load_hooks(:action_controller, self)
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 96ac138ba3ea3e05cb326eba45b8a23985e8ccfb..def28a005494a752371c7328ae618250e61498ff 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -52,7 +52,11 @@ def build(action, app=nil, &block)
class Metal < AbstractController::Base
abstract!
- attr_internal :env
+ attr_internal_writer :env
+
+ def env
+ @_env ||= {}
+ end
# Returns the last part of the controller's name, underscored, without the ending
# Controller. For instance, PostsController returns posts.
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 4b6897c5dd82bf48fdb75bdb9ca16c5fb0dd973f..c5d7842db3c9939b26d8b1be3e5c23373abe8948 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -101,8 +101,12 @@ def modules_for_helpers(args)
# Extract helper names from files in app/helpers/**/*_helper.rb
def all_application_helpers
+ all_helpers_from_path(helpers_path)
+ end
+
+ def all_helpers_from_path(path)
helpers = []
- Array.wrap(helpers_path).each do |path|
+ Array.wrap(path).each do |path|
extract = /^#{Regexp.quote(path.to_s)}\/?(.*)_helper.rb$/
helpers += Dir["#{path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
end
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index a51fc5b8e4e1f21897eb8eb4d78a2e8896424c9b..85c6b0a9b544dd42e111974a8cd10387149ad27c 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -2,27 +2,19 @@ module ActionController
module UrlFor
extend ActiveSupport::Concern
- include ActionDispatch::Routing::UrlFor
+ include AbstractController::UrlFor
def url_options
- super.reverse_merge(
+ options = {}
+ if _routes.equal?(env["action_dispatch.routes"])
+ options[:script_name] = request.script_name.dup
+ end
+
+ super.merge(options).reverse_merge(
:host => request.host_with_port,
:protocol => request.protocol,
:_path_segments => request.symbolized_path_parameters
- ).merge(:script_name => request.script_name)
- end
-
- def _routes
- raise "In order to use #url_for, you must include routing helpers explicitly. " \
- "For instance, `include Rails.application.routes.url_helpers"
- end
-
- module ClassMethods
- def action_methods
- @action_methods ||= begin
- super - _routes.named_routes.helper_names
- end
- end
+ )
end
end
end
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index cd2dfafbe6898aa09add991d25ea955484468f6d..0cb40418550817f14141a81d1dfd55edd5194d82 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -4,6 +4,8 @@
require "action_view/railtie"
require "active_support/deprecation/proxy_wrappers"
require "active_support/deprecation"
+require "abstract_controller/railties/routes_helpers"
+require "action_controller/railties/paths"
module ActionController
class Railtie < Rails::Railtie
@@ -47,10 +49,11 @@ class Railtie < Rails::Railtie
options.javascripts_dir ||= paths.public.javascripts.to_a.first
options.stylesheets_dir ||= paths.public.stylesheets.to_a.first
options.page_cache_directory ||= paths.public.to_a.first
- options.helpers_path ||= paths.app.helpers.to_a
ActiveSupport.on_load(:action_controller) do
- include app.routes.url_helpers
+ include app.routes.mounted_helpers(:app)
+ extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
+ extend ::ActionController::Railties::Paths.with(app)
options.each { |k,v| send("#{k}=", v) }
end
end
@@ -63,4 +66,4 @@ class Railtie < Rails::Railtie
ActionController::Routing::Routes = proxy
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fa71d55946d8ecac11630353b1ab856b875ed475
--- /dev/null
+++ b/actionpack/lib/action_controller/railties/paths.rb
@@ -0,0 +1,20 @@
+module ActionController
+ module Railties
+ module Paths
+ def self.with(app)
+ Module.new do
+ define_method(:inherited) do |klass|
+ super(klass)
+ if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) }
+ klass.helpers_path = namespace._railtie.config.paths.app.helpers.to_a
+ else
+ klass.helpers_path = app.config.helpers_paths
+ end
+
+ klass.helper :all if klass.superclass == ActionController::Base
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 5a029a60d1f8f05b155770a2af60e75eddf62f2f..6f243574e45300f74d6e8d52b78145b14225db3e 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -1,4 +1,5 @@
require "active_support/inflector/methods"
+require "active_support/dependencies"
module ActionDispatch
class MiddlewareStack < Array
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index d7e88a54e478cf498d2f9e9542e16c014d1105f5..581cadbeb49a8fcb84862820b7d0ea924624d680 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -1,12 +1,47 @@
require 'rack/utils'
module ActionDispatch
+ class FileHandler
+ def initialize(at, root)
+ @at, @root = at.chomp('/'), root.chomp('/')
+ @compiled_at = Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank?
+ @compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/)
+ @file_server = ::Rack::File.new(root)
+ end
+
+ def match?(path)
+ path = path.dup
+ if @compiled_at.blank? || path.sub!(@compiled_at, '')
+ full_path = File.join(@root, ::Rack::Utils.unescape(path))
+ paths = "#{full_path}#{ext}"
+
+ matches = Dir[paths]
+ match = matches.detect { |m| File.file?(m) }
+ if match
+ match.sub!(@compiled_root, '')
+ match
+ end
+ end
+ end
+
+ def call(env)
+ @file_server.call(env)
+ end
+
+ def ext
+ @ext ||= begin
+ ext = ::ActionController::Base.page_cache_extension
+ "{,#{ext},/index#{ext}}"
+ end
+ end
+ end
+
class Static
FILE_METHODS = %w(GET HEAD).freeze
- def initialize(app, root)
+ def initialize(app, roots)
@app = app
- @file_server = ::Rack::File.new(root)
+ @file_handlers = create_file_handlers(roots)
end
def call(env)
@@ -14,15 +49,10 @@ def call(env)
method = env['REQUEST_METHOD']
if FILE_METHODS.include?(method)
- if file_exist?(path)
- return @file_server.call(env)
- else
- cached_path = directory_exist?(path) ? "#{path}/index" : path
- cached_path += ::ActionController::Base.page_cache_extension
-
- if file_exist?(cached_path)
- env['PATH_INFO'] = cached_path
- return @file_server.call(env)
+ @file_handlers.each do |file_handler|
+ if match = file_handler.match?(path)
+ env["PATH_INFO"] = match
+ return file_handler.call(env)
end
end
end
@@ -31,14 +61,12 @@ def call(env)
end
private
- def file_exist?(path)
- full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path))
- File.file?(full_path) && File.readable?(full_path)
- end
+ def create_file_handlers(roots)
+ roots = { '' => roots } unless roots.is_a?(Hash)
- def directory_exist?(path)
- full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path))
- File.directory?(full_path) && File.readable?(full_path)
+ roots.map do |at, root|
+ FileHandler.new(at, root) if File.exist?(root)
+ end.compact
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 0b9689dc881397033f9ff777dd6b928226a624ce..b2b0f4c08e3c376fff4d778dd6243a10b01efb06 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -268,6 +268,7 @@ module Routing
autoload :Mapper, 'action_dispatch/routing/mapper'
autoload :Route, 'action_dispatch/routing/route'
autoload :RouteSet, 'action_dispatch/routing/route_set'
+ autoload :RoutesProxy, 'action_dispatch/routing/routes_proxy'
autoload :UrlFor, 'action_dispatch/routing/url_for'
autoload :PolymorphicRoutes, 'action_dispatch/routing/polymorphic_routes'
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index a2570cb877f319af97ff80d3d069732a2491020a..900900ee24145443ff2aebc3a3a0a89a7fbbf97c 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -261,7 +261,11 @@ def mount(app, options = nil)
raise "A rack application must be specified" unless path
+ options[:as] ||= app_name(app)
+
match(path, options.merge(:to => app, :anchor => false, :format => false))
+
+ define_generate_prefix(app, options[:as])
self
end
@@ -269,6 +273,40 @@ def default_url_options=(options)
@set.default_url_options = options
end
alias_method :default_url_options, :default_url_options=
+
+ def with_default_scope(scope, &block)
+ scope(scope) do
+ instance_exec(&block)
+ end
+ end
+
+ private
+ def app_name(app)
+ return unless app.respond_to?(:routes)
+
+ if app.respond_to?(:railtie_name)
+ app.railtie_name
+ else
+ class_name = app.class.is_a?(Class) ? app.name : app.class.name
+ ActiveSupport::Inflector.underscore(class_name).gsub("/", "_")
+ end
+ end
+
+ def define_generate_prefix(app, name)
+ return unless app.respond_to?(:routes)
+
+ _route = @set.named_routes.routes[name.to_sym]
+ _routes = @set
+ app.routes.define_mounted_helper(name)
+ app.routes.class_eval do
+ define_method :_generate_prefix do |options|
+ prefix_options = options.slice(*_route.segment_keys)
+ # we must actually delete prefix segment keys to avoid passing them to next url_for
+ _route.segment_keys.each { |k| options.delete(k) }
+ _routes.url_helpers.send("#{name}_path", prefix_options)
+ end
+ end
+ end
end
module HttpHelpers
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index fb2118a8d769849b331d1e18fa05e6393991a5fd..02ba5236ee72c9b1c324be28527e9d8da43f2dac 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -42,6 +42,18 @@ module Routing
#
# edit_polymorphic_path(@post) # => "/posts/1/edit"
# polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf"
+ #
+ # == Using with mounted engines
+ #
+ # If you use mounted engine, there is a possibility that you will need to use
+ # polymorphic_url pointing at engine's routes. To do that, just pass proxy used
+ # to reach engine's routes as a first argument:
+ #
+ # For example:
+ #
+ # polymorphic_url([blog, @post]) # it will call blog.post_path(@post)
+ # form_for([blog, @post]) # => "/blog/posts/1
+ #
module PolymorphicRoutes
# Constructs a call to a named RESTful route for the given record and returns the
# resulting URL string. For example:
@@ -78,6 +90,9 @@ module PolymorphicRoutes
def polymorphic_url(record_or_hash_or_array, options = {})
if record_or_hash_or_array.kind_of?(Array)
record_or_hash_or_array = record_or_hash_or_array.compact
+ if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
+ proxy = record_or_hash_or_array.shift
+ end
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
end
@@ -111,7 +126,14 @@ def polymorphic_url(record_or_hash_or_array, options = {})
args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
end
- send(named_route, *args)
+ if proxy
+ proxy.send(named_route, *args)
+ else
+ # we need to use url_for, because polymorphic_url can be used in context of other than
+ # current routes (e.g. engine's routes). As named routes from engine are not included
+ # calling engine's named route directly would fail.
+ url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args)
+ end
end
# Returns the path component of a URL for the given record. It uses
@@ -155,7 +177,7 @@ def build_named_route_call(records, inflection, options = {})
if parent.is_a?(Symbol) || parent.is_a?(String)
parent
else
- ActiveModel::Naming.plural(parent).singularize
+ ActiveModel::Naming.route_key(parent).singularize
end
end
end
@@ -163,7 +185,7 @@ def build_named_route_call(records, inflection, options = {})
if record.is_a?(Symbol) || record.is_a?(String)
route << record
else
- route << ActiveModel::Naming.plural(record)
+ route << ActiveModel::Naming.route_key(record)
route = [route.join("_").singularize] if inflection == :singular
route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index b531cc1a8e3d39c932bc0bcf5123cd93dc68aced..107e44287de18ec94f130e3e567d5b0dd14778cf 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -158,10 +158,17 @@ def define_hash_access(route, name, kind, options)
# We use module_eval to avoid leaks
@module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- def #{selector}(options = nil) # def hash_for_users_url(options = nil)
- options ? #{options.inspect}.merge(options) : #{options.inspect} # options ? {:only_path=>false}.merge(options) : {:only_path=>false}
- end # end
- protected :#{selector} # protected :hash_for_users_url
+ def #{selector}(*args)
+ options = args.extract_options!
+
+ if args.any?
+ options[:_positional_args] = args
+ options[:_positional_keys] = #{route.segment_keys.inspect}
+ end
+
+ options ? #{options.inspect}.merge(options) : #{options.inspect}
+ end
+ protected :#{selector}
END_EVAL
helpers << selector
end
@@ -185,21 +192,14 @@ def define_url_helper(route, name, kind, options)
@module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
def #{selector}(*args)
- options = #{hash_access_method}(args.extract_options!)
-
- if args.any?
- options[:_positional_args] = args
- options[:_positional_keys] = #{route.segment_keys.inspect}
- end
-
- url_for(options)
+ url_for(#{hash_access_method}(*args))
end
END_EVAL
helpers << selector
end
end
- attr_accessor :set, :routes, :named_routes
+ attr_accessor :set, :routes, :named_routes, :default_scope
attr_accessor :disable_clear_and_finalize, :resources_path_names
attr_accessor :default_url_options, :request_class, :valid_conditions
@@ -230,7 +230,11 @@ def draw(&block)
if block.arity == 1
mapper.instance_exec(DeprecatedMapper.new(self), &block)
else
- mapper.instance_exec(&block)
+ if default_scope
+ mapper.with_default_scope(default_scope, &block)
+ else
+ mapper.instance_exec(&block)
+ end
end
finalize! unless @disable_clear_and_finalize
@@ -261,6 +265,31 @@ def install_helpers(destinations = [ActionController::Base, ActionView::Base], r
named_routes.install(destinations, regenerate_code)
end
+ module MountedHelpers
+ end
+
+ def mounted_helpers(name = nil)
+ define_mounted_helper(name) if name
+ MountedHelpers
+ end
+
+ def define_mounted_helper(name)
+ return if MountedHelpers.method_defined?(name)
+
+ routes = self
+ MountedHelpers.class_eval do
+ define_method "_#{name}" do
+ RoutesProxy.new(routes, self._routes_context)
+ end
+ end
+
+ MountedHelpers.class_eval <<-RUBY
+ def #{name}
+ @#{name} ||= _#{name}
+ end
+ RUBY
+ end
+
def url_helpers
@url_helpers ||= begin
routes = self
@@ -283,7 +312,7 @@ class << self
singleton_class.send(:define_method, :_routes) { routes }
end
- define_method(:_routes) { routes }
+ define_method(:_routes) { @_routes || routes }
end
helpers
@@ -303,10 +332,9 @@ def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil
end
class Generator #:nodoc:
- attr_reader :options, :recall, :set, :script_name, :named_route
+ attr_reader :options, :recall, :set, :named_route
def initialize(options, recall, set, extras = false)
- @script_name = options.delete(:script_name)
@named_route = options.delete(:use_route)
@options = options.dup
@recall = recall.dup
@@ -401,7 +429,7 @@ def generate
return [path, params.keys] if @extras
path << "?#{params.to_query}" if params.any?
- "#{script_name}#{path}"
+ path
rescue Rack::Mount::RoutingError
raise_routing_error
end
@@ -453,7 +481,11 @@ def generate(options, recall = {}, extras = false)
Generator.new(options, recall, self, extras).generate
end
- RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash]
+ RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name]
+
+ def _generate_prefix(options = {})
+ nil
+ end
def url_for(options)
finalize!
@@ -464,7 +496,6 @@ def url_for(options)
rewritten_url = ""
path_segments = options.delete(:_path_segments)
-
unless options[:only_path]
rewritten_url << (options[:protocol] || "http")
rewritten_url << "://" unless rewritten_url.match("://")
@@ -476,9 +507,12 @@ def url_for(options)
rewritten_url << ":#{options.delete(:port)}" if options.key?(:port)
end
+ script_name = options.delete(:script_name)
+ path = (script_name.blank? ? _generate_prefix(options) : script_name).to_s
+
path_options = options.except(*RESERVED_OPTIONS)
path_options = yield(path_options) if block_given?
- path = generate(path_options, path_segments || {})
+ path << generate(path_options, path_segments || {})
# ROUTES TODO: This can be called directly, so script_name should probably be set in the routes
rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f7d5f6397d0be267b13f77e75805f2f2c16b5e76
--- /dev/null
+++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
@@ -0,0 +1,35 @@
+module ActionDispatch
+ module Routing
+ class RoutesProxy #:nodoc:
+ include ActionDispatch::Routing::UrlFor
+
+ attr_accessor :scope, :routes
+ alias :_routes :routes
+
+ def initialize(routes, scope)
+ @routes, @scope = routes, scope
+ end
+
+ def url_options
+ scope.send(:_with_routes, routes) do
+ scope.url_options
+ end
+ end
+
+ def method_missing(method, *args)
+ if routes.url_helpers.respond_to?(method)
+ self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{method}(*args)
+ options = args.extract_options!
+ args << url_options.merge((options || {}).symbolize_keys)
+ routes.url_helpers.#{method}(*args)
+ end
+ RUBY
+ send(method, *args)
+ else
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index 28ec830fe8a1b0e955c0fa979d97ebacdb7950b1..e836cf7c8e26f52d9153be7ae969f28e0dcaba4a 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -133,6 +133,18 @@ def url_for(options = nil)
polymorphic_url(options)
end
end
+
+ protected
+ def _with_routes(routes)
+ old_routes, @_routes = @_routes, routes
+ yield
+ ensure
+ @_routes = old_routes
+ end
+
+ def _routes_context
+ self
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index b3e67f6e36582e0fa65d6f3cb32dba65a0007947..c587a36930757e62d4dfeb5302d73c5265124e69 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -10,7 +10,7 @@ def self.new(env = {})
end
def initialize(env = {})
- env = Rails.application.env_defaults.merge(env) if defined?(Rails.application)
+ env = Rails.application.env_config.merge(env) if defined?(Rails.application)
super(DEFAULT_ENV.merge(env))
self.host = 'test.host'
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index a3c43d3e9323b82097cbf68bef5074deda2c01de..3329a8b368b0d49d15d2860cb27811e6f10fcb66 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -727,6 +727,9 @@ def compute_public_path(source, dir, ext = nil, include_host = true)
source += ".#{ext}" if rewrite_extension?(source, dir, ext)
source = "/#{dir}/#{source}" unless source[0] == ?/
+ if controller.respond_to?(:env) && controller.env["action_dispatch.asset_path"]
+ source = rewrite_asset_path(source, controller.env["action_dispatch.asset_path"])
+ end
source = rewrite_asset_path(source, config.asset_path)
has_request = controller.respond_to?(:request)
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 94dc25eb85b9b24f12a8d9b39e39f6ea379d4342..43dbedc448f8a39453cc9d870877cd59f477b311 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -304,12 +304,12 @@ def form_for(record_or_name_or_array, *args, &proc)
object_name = record_or_name_or_array
when Array
object = record_or_name_or_array.last
- object_name = options[:as] || ActiveModel::Naming.singular(object)
+ object_name = options[:as] || ActiveModel::Naming.param_key(object)
apply_form_for_options!(record_or_name_or_array, options)
args.unshift object
else
object = record_or_name_or_array
- object_name = options[:as] || ActiveModel::Naming.singular(object)
+ object_name = options[:as] || ActiveModel::Naming.param_key(object)
apply_form_for_options!([object], options)
args.unshift object
end
@@ -539,7 +539,7 @@ def fields_for(record, record_object = nil, options = nil, &block)
object_name = record
else
object = record
- object_name = ActiveModel::Naming.singular(object)
+ object_name = ActiveModel::Naming.param_key(object)
end
builder = options[:builder] || ActionView::Base.default_form_builder
@@ -1168,11 +1168,11 @@ def fields_for(record_or_name_or_array, *args, &block)
end
when Array
object = record_or_name_or_array.last
- name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]"
+ name = "#{object_name}#{index}[#{ActiveModel::Naming.param_key(object)}]"
args.unshift(object)
else
object = record_or_name_or_array
- name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]"
+ name = "#{object_name}#{index}[#{ActiveModel::Naming.param_key(object)}]"
args.unshift(object)
end
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index b8df2d9a69b4580c131b37a1026ed757721d3431..555be6ed2b117b5a1254c635f91cc596a67f300d 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -22,6 +22,10 @@ module UrlHelper
include ActionDispatch::Routing::UrlFor
include TagHelper
+ def _routes_context
+ controller
+ end
+
# Need to map default url options to controller one.
# def default_url_options(*args) #:nodoc:
# controller.send(:default_url_options, *args)
diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb
index 90a1ef982c350010d99772009aed1aadfba990a8..448aaa5eeef2436db426fe44246b01a56a7325ee 100644
--- a/actionpack/test/activerecord/polymorphic_routes_test.rb
+++ b/actionpack/test/activerecord/polymorphic_routes_test.rb
@@ -25,6 +25,22 @@ class Series < ActiveRecord::Base
set_table_name 'projects'
end
+module Blog
+ class Post < ActiveRecord::Base
+ set_table_name 'projects'
+ end
+
+ class Blog < ActiveRecord::Base
+ set_table_name 'projects'
+ end
+
+ def self._railtie
+ o = Object.new
+ def o.railtie_name; "blog" end
+ o
+ end
+end
+
class PolymorphicRoutesTest < ActionController::TestCase
include SharedTestRoutes.url_helpers
self.default_url_options[:host] = 'example.com'
@@ -37,6 +53,38 @@ def setup
@tax = Tax.new
@fax = Fax.new
@series = Series.new
+ @blog_post = Blog::Post.new
+ @blog_blog = Blog::Blog.new
+ end
+
+ def test_passing_routes_proxy
+ with_namespaced_routes(:blog) do
+ proxy = ActionDispatch::Routing::RoutesProxy.new(_routes, self)
+ @blog_post.save
+ assert_equal "http://example.com/posts/#{@blog_post.id}", polymorphic_url([proxy, @blog_post])
+ end
+ end
+
+ def test_namespaced_model
+ with_namespaced_routes(:blog) do
+ @blog_post.save
+ assert_equal "http://example.com/posts/#{@blog_post.id}", polymorphic_url(@blog_post)
+ end
+ end
+
+ def test_namespaced_model_with_name_the_same_as_namespace
+ with_namespaced_routes(:blog) do
+ @blog_blog.save
+ assert_equal "http://example.com/blogs/#{@blog_blog.id}", polymorphic_url(@blog_blog)
+ end
+ end
+
+ def test_namespaced_model_with_nested_resources
+ with_namespaced_routes(:blog) do
+ @blog_post.save
+ @blog_blog.save
+ assert_equal "http://example.com/blogs/#{@blog_blog.id}/posts/#{@blog_post.id}", polymorphic_url([@blog_blog, @blog_post])
+ end
end
def test_with_record
@@ -385,6 +433,22 @@ def test_uncountable_resource
end
end
+ def with_namespaced_routes(name)
+ with_routing do |set|
+ set.draw do
+ scope(:module => name) do
+ resources :blogs do
+ resources :posts
+ end
+ resources :posts
+ end
+ end
+
+ self.class.send(:include, @routes.url_helpers)
+ yield
+ end
+ end
+
def with_test_routes(options = {})
with_routing do |set|
set.draw do |map|
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3b47a1b72d7258a81bd77590546a50a6f6459624
--- /dev/null
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -0,0 +1,256 @@
+require 'abstract_unit'
+
+module TestGenerationPrefix
+ class WithMountedEngine < ActionDispatch::IntegrationTest
+ require 'rack/test'
+ include Rack::Test::Methods
+
+ class BlogEngine
+ def self.routes
+ @routes ||= begin
+ routes = ActionDispatch::Routing::RouteSet.new
+ routes.draw do
+ match "/posts/:id", :to => "inside_engine_generating#show", :as => :post
+ match "/posts", :to => "inside_engine_generating#index", :as => :posts
+ match "/url_to_application", :to => "inside_engine_generating#url_to_application"
+ match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine"
+ match "/conflicting_url", :to => "inside_engine_generating#conflicting"
+ end
+
+ routes
+ end
+ end
+
+ def self.call(env)
+ env['action_dispatch.routes'] = routes
+ routes.call(env)
+ end
+ end
+
+ class RailsApplication
+ def self.routes
+ @routes ||= begin
+ routes = ActionDispatch::Routing::RouteSet.new
+ routes.draw do
+ scope "/:omg", :omg => "awesome" do
+ mount BlogEngine => "/blog", :as => "blog_engine"
+ end
+ match "/generate", :to => "outside_engine_generating#index"
+ match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine"
+ match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for"
+ match "/conflicting_url", :to => "outside_engine_generating#conflicting"
+ root :to => "outside_engine_generating#index"
+ end
+
+ routes
+ end
+ end
+
+ def self.call(env)
+ env['action_dispatch.routes'] = routes
+ routes.call(env)
+ end
+ end
+
+ # force draw
+ RailsApplication.routes
+
+ class Post
+ extend ActiveModel::Naming
+
+ def to_param
+ "1"
+ end
+
+ def self.model_name
+ klass = "Post"
+ def klass.name; self end
+
+ ActiveModel::Name.new(klass)
+ end
+ end
+
+ class ::InsideEngineGeneratingController < ActionController::Base
+ include BlogEngine.routes.url_helpers
+ include RailsApplication.routes.mounted_helpers(:app)
+
+ def index
+ render :text => posts_path
+ end
+
+ def show
+ render :text => post_path(:id => params[:id])
+ end
+
+ def url_to_application
+ path = app.url_for( :controller => "outside_engine_generating",
+ :action => "index",
+ :only_path => true)
+ render :text => path
+ end
+
+ def polymorphic_path_for_engine
+ render :text => polymorphic_path(Post.new)
+ end
+
+ def conflicting
+ render :text => "engine"
+ end
+ end
+
+ class ::OutsideEngineGeneratingController < ActionController::Base
+ include BlogEngine.routes.mounted_helpers
+
+ def index
+ render :text => blog_engine.post_path(:id => 1)
+ end
+
+ def polymorphic_path_for_engine
+ render :text => blog_engine.polymorphic_path(Post.new)
+ end
+
+ def polymorphic_with_url_for
+ render :text => blog_engine.url_for(Post.new)
+ end
+
+ def conflicting
+ render :text => "application"
+ end
+ end
+
+ class EngineObject
+ include ActionDispatch::Routing::UrlFor
+ include BlogEngine.routes.url_helpers
+ end
+
+ class AppObject
+ include ActionDispatch::Routing::UrlFor
+ include RailsApplication.routes.url_helpers
+ end
+
+ def app
+ RailsApplication
+ end
+
+ def engine_object
+ @engine_object ||= EngineObject.new
+ end
+
+ def app_object
+ @app_object ||= AppObject.new
+ end
+
+ def setup
+ RailsApplication.routes.default_url_options = {}
+ end
+
+ # Inside Engine
+ test "[ENGINE] generating engine's url use SCRIPT_NAME from request" do
+ get "/pure-awesomeness/blog/posts/1"
+ assert_equal "/pure-awesomeness/blog/posts/1", last_response.body
+ end
+
+ test "[ENGINE] generating application's url never uses SCRIPT_NAME from request" do
+ get "/pure-awesomeness/blog/url_to_application"
+ assert_equal "/generate", last_response.body
+ end
+
+ test "[ENGINE] generating application's url includes default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ get "/pure-awesomeness/blog/url_to_application"
+ assert_equal "/something/generate", last_response.body
+ end
+
+ test "[ENGINE] generating application's url should give higher priority to default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ get "/pure-awesomeness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo'
+ assert_equal "/something/generate", last_response.body
+ end
+
+ test "[ENGINE] generating engine's url with polymorphic path" do
+ get "/pure-awesomeness/blog/polymorphic_path_for_engine"
+ assert_equal "/pure-awesomeness/blog/posts/1", last_response.body
+ end
+
+ test "[ENGINE] url_helpers from engine have higher priotity than application's url_helpers" do
+ get "/awesome/blog/conflicting_url"
+ assert_equal "engine", last_response.body
+ end
+
+ # Inside Application
+ test "[APP] generating engine's route includes prefix" do
+ get "/generate"
+ assert_equal "/awesome/blog/posts/1", last_response.body
+ end
+
+ test "[APP] generating engine's route includes default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ get "/generate"
+ assert_equal "/something/awesome/blog/posts/1", last_response.body
+ end
+
+ test "[APP] generating engine's route should give higher priority to default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ get "/generate", {}, 'SCRIPT_NAME' => "/foo"
+ assert_equal "/something/awesome/blog/posts/1", last_response.body
+ end
+
+ test "[APP] generating engine's url with polymorphic path" do
+ get "/polymorphic_path_for_engine"
+ assert_equal "/awesome/blog/posts/1", last_response.body
+ end
+
+ test "[APP] generating engine's url with url_for(@post)" do
+ get "/polymorphic_with_url_for"
+ assert_equal "http://example.org/awesome/blog/posts/1", last_response.body
+ end
+
+ # Inside any Object
+ test "[OBJECT] generating engine's route includes prefix" do
+ assert_equal "/awesome/blog/posts/1", engine_object.post_path(:id => 1)
+ end
+
+ test "[OBJECT] generating engine's route includes dynamic prefix" do
+ assert_equal "/pure-awesomeness/blog/posts/3", engine_object.post_path(:id => 3, :omg => "pure-awesomeness")
+ end
+
+ test "[OBJECT] generating engine's route includes default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ assert_equal "/something/pure-awesomeness/blog/posts/3", engine_object.post_path(:id => 3, :omg => "pure-awesomeness")
+ end
+
+ test "[OBJECT] generating application's route" do
+ assert_equal "/", app_object.root_path
+ end
+
+ test "[OBJECT] generating application's route includes default_url_options[:script_name]" do
+ RailsApplication.routes.default_url_options = {:script_name => "/something"}
+ assert_equal "/something/", app_object.root_path
+ end
+
+ test "[OBJECT] generating engine's route with url_for" do
+ path = engine_object.url_for(:controller => "inside_engine_generating",
+ :action => "show",
+ :only_path => true,
+ :omg => "omg",
+ :id => 1)
+ assert_equal "/omg/blog/posts/1", path
+ end
+
+ test "[OBJECT] generating engine's route with named helpers" do
+ path = engine_object.posts_path
+ assert_equal "/awesome/blog/posts", path
+
+ path = engine_object.posts_url(:host => "example.com")
+ assert_equal "http://example.com/awesome/blog/posts", path
+ end
+
+ test "[OBJECT] generating engine's route with polymorphic_url" do
+ path = engine_object.polymorphic_path(Post.new)
+ assert_equal "/awesome/blog/posts/1", path
+
+ path = engine_object.polymorphic_url(Post.new, :host => "www.example.com")
+ assert_equal "http://www.example.com/awesome/blog/posts/1", path
+ end
+ end
+end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index c90c1041ed2b98f39c7878d723719b9f1b117531..b642adc06bc450c019a56acddd0bf5fe9037dd66 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -2151,3 +2151,32 @@ def expected_redirect_body(url)
%(
You are being redirected.)
end
end
+
+
+class TestDefaultScope < ActionController::IntegrationTest
+ module ::Blog
+ class PostsController < ActionController::Base
+ def index
+ render :text => "blog/posts#index"
+ end
+ end
+ end
+
+ DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new
+ DefaultScopeRoutes.default_scope = {:module => :blog}
+ DefaultScopeRoutes.draw do
+ resources :posts
+ end
+
+ def app
+ DefaultScopeRoutes
+ end
+
+ include DefaultScopeRoutes.url_helpers
+
+ def test_default_scope
+ get '/posts'
+ assert_equal "blog/posts#index", @response.body
+ end
+end
+
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index e6957bb0ea1b370a782d53aa9143a9059e036e35..2eb82fc5d897f028f2a463812f4a85cfaa4e0d17 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -1,28 +1,23 @@
require 'abstract_unit'
-class StaticTest < ActiveSupport::TestCase
- DummyApp = lambda { |env|
- [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]]
- }
- App = ActionDispatch::Static.new(DummyApp, "#{FIXTURE_LOAD_PATH}/public")
-
- test "serves dynamic content" do
+module StaticTests
+ def test_serves_dynamic_content
assert_equal "Hello, World!", get("/nofile")
end
- test "serves static index at root" do
+ def test_serves_static_index_at_root
assert_equal "/index.html", get("/index.html")
assert_equal "/index.html", get("/index")
assert_equal "/index.html", get("/")
end
- test "serves static file in directory" do
+ def test_serves_static_file_in_directory
assert_equal "/foo/bar.html", get("/foo/bar.html")
assert_equal "/foo/bar.html", get("/foo/bar/")
assert_equal "/foo/bar.html", get("/foo/bar")
end
- test "serves static index file in directory" do
+ def test_serves_static_index_file_in_directory
assert_equal "/foo/index.html", get("/foo/index.html")
assert_equal "/foo/index.html", get("/foo/")
assert_equal "/foo/index.html", get("/foo")
@@ -30,6 +25,50 @@ class StaticTest < ActiveSupport::TestCase
private
def get(path)
- Rack::MockRequest.new(App).request("GET", path).body
+ Rack::MockRequest.new(@app).request("GET", path).body
end
end
+
+class StaticTest < ActiveSupport::TestCase
+ DummyApp = lambda { |env|
+ [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]]
+ }
+ App = ActionDispatch::Static.new(DummyApp, "#{FIXTURE_LOAD_PATH}/public")
+
+ def setup
+ @app = App
+ end
+
+ include StaticTests
+end
+
+class MultipleDirectorisStaticTest < ActiveSupport::TestCase
+ DummyApp = lambda { |env|
+ [200, {"Content-Type" => "text/plain"}, ["Hello, World!"]]
+ }
+ App = ActionDispatch::Static.new(DummyApp,
+ { "/" => "#{FIXTURE_LOAD_PATH}/public",
+ "/blog" => "#{FIXTURE_LOAD_PATH}/blog_public",
+ "/foo" => "#{FIXTURE_LOAD_PATH}/non_existing_dir"
+ })
+
+ def setup
+ @app = App
+ end
+
+ include StaticTests
+
+ test "serves files from other mounted directories" do
+ assert_equal "/blog/index.html", get("/blog/index.html")
+ assert_equal "/blog/index.html", get("/blog/index")
+ assert_equal "/blog/index.html", get("/blog/")
+
+ assert_equal "/blog/blog.html", get("/blog/blog/")
+ assert_equal "/blog/blog.html", get("/blog/blog.html")
+ assert_equal "/blog/blog.html", get("/blog/blog")
+
+ assert_equal "/blog/subdir/index.html", get("/blog/subdir/index.html")
+ assert_equal "/blog/subdir/index.html", get("/blog/subdir/")
+ assert_equal "/blog/subdir/index.html", get("/blog/subdir")
+ end
+end
diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb
index f83651d5835c9eaeac45c988b04ce8ba213ebccb..2b54bc62b0e5a8e35c45acec47100f42d84ef419 100644
--- a/actionpack/test/dispatch/url_generation_test.rb
+++ b/actionpack/test/dispatch/url_generation_test.rb
@@ -31,7 +31,7 @@ def app
end
test "the request's SCRIPT_NAME takes precedence over the routes'" do
- get "/foo", {}, 'SCRIPT_NAME' => "/new"
+ get "/foo", {}, 'SCRIPT_NAME' => "/new", 'action_dispatch.routes' => Routes
assert_equal "/new/foo", response.body
end
@@ -41,3 +41,4 @@ def app
end
end
end
+
diff --git a/actionpack/test/fixtures/blog_public/.gitignore b/actionpack/test/fixtures/blog_public/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..312e635ee658be737380ccb8e62c7b29ad8dabd2
--- /dev/null
+++ b/actionpack/test/fixtures/blog_public/.gitignore
@@ -0,0 +1 @@
+absolute/*
diff --git a/actionpack/test/fixtures/blog_public/blog.html b/actionpack/test/fixtures/blog_public/blog.html
new file mode 100644
index 0000000000000000000000000000000000000000..79ad44c010a0d990aa4e8a68d7e5253fefcadbfa
--- /dev/null
+++ b/actionpack/test/fixtures/blog_public/blog.html
@@ -0,0 +1 @@
+/blog/blog.html
\ No newline at end of file
diff --git a/actionpack/test/fixtures/blog_public/index.html b/actionpack/test/fixtures/blog_public/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..2de3825481fa324355dd9575a46737134c93924c
--- /dev/null
+++ b/actionpack/test/fixtures/blog_public/index.html
@@ -0,0 +1 @@
+/blog/index.html
\ No newline at end of file
diff --git a/actionpack/test/fixtures/blog_public/subdir/index.html b/actionpack/test/fixtures/blog_public/subdir/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..517bded33514eb381d919ac0fb5b86fa536b51fd
--- /dev/null
+++ b/actionpack/test/fixtures/blog_public/subdir/index.html
@@ -0,0 +1 @@
+/blog/subdir/index.html
\ No newline at end of file
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
index bf3e175f1fc6edcc8acb79d3f321c8697b9d8388..c4127ee699c7c02e67ba6f272cb03e56242efce4 100644
--- a/actionpack/test/lib/controller/fake_models.rb
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -83,7 +83,7 @@ def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end
def to_key; id ? [id] : nil end
def save; @id = 1; @post_id = 1 end
def persisted?; @id.present? end
- def to_param; @id; end
+ def to_param; @id.to_s; end
def name
@id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
end
@@ -149,3 +149,18 @@ class Author < Comment
attr_accessor :post
def post_attributes=(attributes); end
end
+
+module Blog
+ def self._railtie
+ self
+ end
+
+ class Post < Struct.new(:title, :id)
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
+ def persisted?
+ id.present?
+ end
+ end
+end
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 6d5e4893c4704d30ff13d05ef6a3691ad66ee7aa..2b83cfe1a9ceeced537685caa854937c841f7efb 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -387,6 +387,15 @@ def test_string_asset_id
assert_equal %(), image_tag("rails.png")
end
+ def test_env_asset_path
+ @controller.config.asset_path = "/assets%s"
+ def @controller.env; @_env ||= {} end
+ @controller.env["action_dispatch.asset_path"] = "/omg%s"
+
+ expected_path = "/assets/omg/images/rails.png"
+ assert_equal %(), image_tag("rails.png")
+ end
+
def test_proc_asset_id
@controller.config.asset_path = Proc.new do |asset_path|
"/assets.v12345#{asset_path}"
@@ -396,6 +405,20 @@ def test_proc_asset_id
assert_equal %(), image_tag("rails.png")
end
+ def test_env_proc_asset_path
+ @controller.config.asset_path = Proc.new do |asset_path|
+ "/assets.v12345#{asset_path}"
+ end
+
+ def @controller.env; @_env ||= {} end
+ @controller.env["action_dispatch.asset_path"] = Proc.new do |asset_path|
+ "/omg#{asset_path}"
+ end
+
+ expected_path = "/assets.v12345/omg/images/rails.png"
+ assert_equal %(), image_tag("rails.png")
+ end
+
def test_image_tag_interpreting_email_cid_correctly
# An inline image has no need for an alt tag to be automatically generated from the cid:
assert_equal '', image_tag("cid:thi%25%25sis@acontentid")
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 9a1fe01872968fe8ac8f90377791ce4d82c5a804..97a08d45ba2c2e33877bb05282026997b4f469a9 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -75,15 +75,39 @@ def @post.to_param; '123'; end
@post.body = "Back to the hill and over it again!"
@post.secret = 1
@post.written_on = Date.new(2004, 6, 15)
+
+ @blog_post = Blog::Post.new("And his name will be forty and four.", 44)
end
+ Routes = ActionDispatch::Routing::RouteSet.new
+ Routes.draw do
+ resources :posts do
+ resources :comments
+ end
+
+ namespace :admin do
+ resources :posts do
+ resources :comments
+ end
+ end
+
+ match "/foo", :to => "controller#action"
+ root :to => "main#index"
+ end
+
+ def _routes
+ Routes
+ end
+
+ include Routes.url_helpers
+
def url_for(object)
@url_for_options = object
- if object.is_a?(Hash)
- "http://www.example.com"
- else
- super
+ if object.is_a?(Hash) && object[:use_route].blank? && object[:controller].blank?
+ object.merge!(:controller => "main", :action => "index")
end
+ object
+ super
end
def test_label
@@ -628,7 +652,7 @@ def test_form_for
end
expected =
- ""
+ end
+
def test_form_for_with_symbol_object_name
form_for(@post, :as => "other_name", :html => { :id => 'create-post' }) do |f|
concat f.label(:title, :class => 'post_title')
@@ -683,7 +722,7 @@ def test_form_for_with_method
end
end
- expected = whole_form("http://www.example.com", "create-post", nil, "put") do
+ expected = whole_form("/", "create-post", nil, "put") do
"" +
"" +
"" +
@@ -702,7 +741,7 @@ def test_form_for_with_remote
end
end
- expected = whole_form("http://www.example.com", "create-post", nil, :method => "put", :remote => true) do
+ expected = whole_form("/", "create-post", nil, :method => "put", :remote => true) do
"" +
"" +
"" +
@@ -721,7 +760,7 @@ def test_form_for_with_remote_without_html
end
end
- expected = whole_form("http://www.example.com", nil, nil, :remote => true) do
+ expected = whole_form("/", nil, nil, :remote => true) do
"" +
"" +
"" +
@@ -738,7 +777,7 @@ def test_form_for_without_object
concat f.check_box(:secret)
end
- expected = whole_form("http://www.example.com", "create-post") do
+ expected = whole_form("/", "create-post") do
"" +
"" +
"" +
@@ -1478,7 +1517,7 @@ def test_form_for_and_fields_for
end
expected =
- "