From f7af75976a9117aa1cb294114af4f99a1d28f1cd Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 23 Jun 2010 02:38:44 +0200 Subject: require 'active_support/dependencies' in action_dispatch/middleware/stack --- actionpack/lib/action_dispatch/middleware/stack.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 5a029a60d1..6f243574e4 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 -- cgit v1.2.3 From 28016d33b0f2e668ca59a912c7fb2d777e3cf0a3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 1 Jul 2010 09:04:30 +0200 Subject: Use env['action_dispatch.routes'] to determine if we should generate prefix or not. This technique is here to allow using routes from Engine in Application and vice versa. When using Engine routes inside Application it should generate prefix based on mount point. When using Engine routes inside Engine it should use env['SCRIPT_NAME']. In any other case it should generate prefix as env should not be even available. --- actionpack/lib/action_dispatch/routing/mapper.rb | 27 ++++++++++++++++++++++ .../lib/action_dispatch/routing/route_set.rb | 20 +++++++++++----- actionpack/lib/action_dispatch/routing/url_for.rb | 8 ++++++- 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index a2570cb877..f3aa09f4a7 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -261,7 +261,11 @@ module ActionDispatch 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,29 @@ module ActionDispatch @set.default_url_options = options end alias_method :default_url_options, :default_url_options= + + private + def app_name(app) + return unless app.respond_to?(:routes) + class_name = app.class.is_a?(Class) ? app.name : app.class.name + ActiveSupport::Inflector.underscore(class_name).gsub("/", "_") + end + + def define_generate_prefix(app, name) + return unless app.respond_to?(:routes) + + _route = @set.named_routes.routes[name.to_sym] + _router = @set + app.routes.class_eval do + define_method :_generate_prefix do |options| + keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS + prefix_options = options.reject { |k, v| !(keys).include?(k) } + # we must actually delete prefix segment keys to avoid passing them to next url_for + _route.segment_keys.each { |k| options.delete(k) } + _router.url_helpers.send("#{name}_path", prefix_options) + end + end + end end module HttpHelpers diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index b531cc1a8e..cb0373951f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -303,10 +303,9 @@ module ActionDispatch 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 +400,7 @@ module ActionDispatch 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 +452,11 @@ module ActionDispatch 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, :skip_prefix, :routes] + + def _generate_prefix(options = {}) + nil + end def url_for(options) finalize! @@ -464,7 +467,6 @@ module ActionDispatch 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 +478,15 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options.key?(:port) end + path = [options.delete(:script_name)] + if !options.delete(:skip_prefix) + path << _generate_prefix(options) + end + 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 || {}) + path = path.compact.join '' # 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/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 28ec830fe8..f73067688c 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -128,7 +128,13 @@ module ActionDispatch when String options when nil, Hash - _routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + routes = (options ? options.delete(:routes) : nil) || _routes + + if respond_to?(:env) && env && routes.equal?(env["action_dispatch.routes"]) + options[:skip_prefix] = true + end + + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) else polymorphic_url(options) end -- cgit v1.2.3 From 451c9942bb493190d5673c1b55be7506056db13b Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 7 Jul 2010 11:26:03 +0200 Subject: Allow to generate Application routes inside Engine This requires knowledge about original SCRIPT_NAME and the parent router. It should be pass through the env as ORIGIAL_SCRIPT_NAME and action_dispatch.parent_routes --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index f3aa09f4a7..0e138524cd 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -289,7 +289,7 @@ module ActionDispatch app.routes.class_eval do define_method :_generate_prefix do |options| keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS - prefix_options = options.reject { |k, v| !(keys).include?(k) } + prefix_options = options.slice(*keys) # we must actually delete prefix segment keys to avoid passing them to next url_for _route.segment_keys.each { |k| options.delete(k) } _router.url_helpers.send("#{name}_path", prefix_options) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index f73067688c..deaf1cdf03 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -129,9 +129,9 @@ module ActionDispatch options when nil, Hash routes = (options ? options.delete(:routes) : nil) || _routes - - if respond_to?(:env) && env && routes.equal?(env["action_dispatch.routes"]) - options[:skip_prefix] = true + if respond_to?(:env) && env + options[:skip_prefix] = true if routes.equal?(env["action_dispatch.routes"]) + options[:script_name] = env["ORIGINAL_SCRIPT_NAME"] if routes.equal?(env["action_dispatch.parent_routes"]) end routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) -- cgit v1.2.3 From eedbf87d15b99a7cae38b0d8894fc39f1e70a81e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 8 Jul 2010 15:42:40 +0200 Subject: New way of generating urls for Application from Engine. It's based specifying application's script_name with: Rails.application.default_url_options = {:script_name => "/foo"} default_url_options method is delegated to routes. If router used to generate url differs from the router passed via env it always overwrites :script_name with this value. --- actionpack/lib/action_dispatch/routing/route_set.rb | 4 ++-- actionpack/lib/action_dispatch/routing/url_for.rb | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index cb0373951f..7519d74183 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -280,10 +280,10 @@ module ActionDispatch # Yes plz - JP included do routes.install_helpers(self) - singleton_class.send(:define_method, :_routes) { routes } + singleton_class.send(:define_method, :_routes) { @_routes || routes } end - define_method(:_routes) { routes } + define_method(:_routes) { @_routes || routes } end helpers diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index deaf1cdf03..5da41df485 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -129,16 +129,21 @@ module ActionDispatch options when nil, Hash routes = (options ? options.delete(:routes) : nil) || _routes - if respond_to?(:env) && env - options[:skip_prefix] = true if routes.equal?(env["action_dispatch.routes"]) - options[:script_name] = env["ORIGINAL_SCRIPT_NAME"] if routes.equal?(env["action_dispatch.parent_routes"]) - end - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + _with_routes(routes) do + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + end else polymorphic_url(options) end end + + def _with_routes(routes) + old_routes, @_routes = @_routes, routes + yield + ensure + @_routes = old_routes + end end end end -- cgit v1.2.3 From 8a077089d9b7aa89cb56ef754b4540f411453375 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 9 Jul 2010 01:22:18 +0200 Subject: Get rid of :skip_prefix options in routes --- actionpack/lib/action_dispatch/routing/route_set.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 7519d74183..6f182ae652 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -452,7 +452,7 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :skip_prefix, :routes] + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :routes] def _generate_prefix(options = {}) nil @@ -478,15 +478,12 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options.key?(:port) end - path = [options.delete(:script_name)] - if !options.delete(:skip_prefix) - path << _generate_prefix(options) - 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 = path.compact.join '' # 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) -- cgit v1.2.3 From b53efd21059b9d829a6617fb5b2dd86754684c60 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 14 Jul 2010 00:46:42 +0200 Subject: Extended url_for to handle specifying which router should be used. A few examples: url_for Blog::Engine, :posts_path url_for Blog::Engine, @post url_for Blog::Engine, :action => "main", :controller => "index" --- .../action_dispatch/routing/polymorphic_routes.rb | 2 +- .../lib/action_dispatch/routing/route_set.rb | 24 ++++++------ actionpack/lib/action_dispatch/routing/url_for.rb | 45 ++++++++++++++-------- 3 files changed, 42 insertions(+), 29 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index fb2118a8d7..15ee7c8051 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,7 +111,7 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - send(named_route, *args) + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end # Returns the path component of a URL for the given record. It uses diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 6f182ae652..c94b00257b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -158,10 +158,17 @@ module ActionDispatch # 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,14 +192,7 @@ module ActionDispatch @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 diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 5da41df485..edcb7f9cbe 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,27 +123,40 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(options = nil) - case options - when String - options - when nil, Hash - routes = (options ? options.delete(:routes) : nil) || _routes - - _with_routes(routes) do - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + def url_for(*args) + if args.first.respond_to?(:routes) + app = args.shift + _with_routes(app.routes) do + if args.first.is_a? Symbol + named_route = args.shift + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + else + url_for(*args) + end end else - polymorphic_url(options) + options = args.first + case options + when String + options + when nil, Hash + routes = (options ? options.delete(:routes) : nil) || _routes + _with_routes(routes) do + routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) + end + else + polymorphic_url(options) + end end end - def _with_routes(routes) - old_routes, @_routes = @_routes, routes - yield - ensure - @_routes = old_routes - end + protected + def _with_routes(routes) + old_routes, @_routes = @_routes, routes + yield + ensure + @_routes = old_routes + end end end end -- cgit v1.2.3 From e9791bec823e42372eca095b946c93c1712a0613 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 15 Jul 2010 01:18:02 +0200 Subject: Routes refactoring: * added more tests for prefix generation * fixed bug with generating host for both prefix and url * refactored url_for method * organized tests for prefix generation --- actionpack/lib/action_dispatch/routing/mapper.rb | 3 +-- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 10 ++++------ 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0e138524cd..88152ac290 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -288,8 +288,7 @@ module ActionDispatch _router = @set app.routes.class_eval do define_method :_generate_prefix do |options| - keys = _route.segment_keys + ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS - prefix_options = options.slice(*keys) + 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) } _router.url_helpers.send("#{name}_path", prefix_options) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c94b00257b..b3945a4963 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -452,7 +452,7 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name, :routes] + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name] def _generate_prefix(options = {}) nil diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index edcb7f9cbe..30b456f3df 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,19 +123,17 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(*args) - if args.first.respond_to?(:routes) - app = args.shift - _with_routes(app.routes) do + def url_for(options = nil, *args) + if options.respond_to?(:routes) + _with_routes(options.routes) do if args.first.is_a? Symbol named_route = args.shift - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + url_for _routes.url_helpers.send("hash_for_#{named_route}", *args) else url_for(*args) end end else - options = args.first case options when String options -- cgit v1.2.3 From 6c95e0f879aafa5921cd7898d5951b9a926d3c9a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 18 Jul 2010 19:49:51 +0200 Subject: Add mounted_helpers to routes mounted_helpers are a bit similar to url_helpers. They're automatically included in controllers for Rails.application and each of mounted Engines. Mounted helper allows to call url_for and named helpers for given application. Given Blog::Engine mounted as blog_engine, there are 2 helpers defined: app and blog_engine. You can call routes for app and engine using those helpers: app.root_url app.url_for(:controller => "foo") blog_engine.posts_path blog_engine.url_for(@post) --- actionpack/lib/action_dispatch/routing/mapper.rb | 5 +- .../lib/action_dispatch/routing/route_set.rb | 59 ++++++++++++++++++++++ actionpack/lib/action_dispatch/routing/url_for.rb | 28 +++------- 3 files changed, 69 insertions(+), 23 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 88152ac290..ef1bee106a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -285,13 +285,14 @@ module ActionDispatch return unless app.respond_to?(:routes) _route = @set.named_routes.routes[name.to_sym] - _router = @set + _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) } - _router.url_helpers.send("#{name}_path", prefix_options) + _routes.url_helpers.send("#{name}_path", prefix_options) end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index b3945a4963..0f8bb5c504 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -261,6 +261,65 @@ module ActionDispatch named_routes.install(destinations, regenerate_code) end + class RoutesProxy + include ActionDispatch::Routing::UrlFor + + %w(url_options polymorphic_url polymorphic_path).each do |method| + self.class_eval <<-RUBY, __FILE__, __LINE__ +1 + def #{method}(*args) + scope.send(:_with_routes, routes) do + scope.#{method}(*args) + end + end + RUBY + end + + attr_accessor :scope, :routes + alias :_routes :routes + + def initialize(routes, scope) + @routes, @scope = routes, scope + 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 + + module MountedHelpers + end + + def mounted_helpers(name = nil) + define_mounted_helper(name) if name + MountedHelpers + end + + def define_mounted_helper(name, helpers = nil) + routes = self + MountedHelpers.class_eval do + define_method "_#{name}" do + RoutesProxy.new(routes, self) + end + end + + MountedHelpers.class_eval <<-RUBY + def #{name} + @#{name} ||= _#{name} + end + RUBY + end + def url_helpers @url_helpers ||= begin routes = self diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 30b456f3df..19db730b6a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -123,28 +123,14 @@ module ActionDispatch # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok' # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/' # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33' - def url_for(options = nil, *args) - if options.respond_to?(:routes) - _with_routes(options.routes) do - if args.first.is_a? Symbol - named_route = args.shift - url_for _routes.url_helpers.send("hash_for_#{named_route}", *args) - else - url_for(*args) - end - end + def url_for(options = nil) + case options + when String + options + when nil, Hash + _routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) else - case options - when String - options - when nil, Hash - routes = (options ? options.delete(:routes) : nil) || _routes - _with_routes(routes) do - routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) - end - else - polymorphic_url(options) - end + polymorphic_url(options) end end -- cgit v1.2.3 From a132229d7b4382d9ffe8847fa58f469cb8f2ecfc Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 22 Jul 2010 22:11:32 +0200 Subject: Added ability to set asset_path for engines --- actionpack/lib/action_dispatch/testing/test_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index b3e67f6e36..c587a36930 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -10,7 +10,7 @@ module ActionDispatch 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' -- cgit v1.2.3 From 4cd6f7752658f0ec13d082fa2ee2a6f766410645 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 24 Jul 2010 17:43:33 +0200 Subject: We don't need delegating polymorphic_url and polymorphic_path anymore --- actionpack/lib/action_dispatch/routing/route_set.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0f8bb5c504..121e7c2c75 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -264,16 +264,6 @@ module ActionDispatch class RoutesProxy include ActionDispatch::Routing::UrlFor - %w(url_options polymorphic_url polymorphic_path).each do |method| - self.class_eval <<-RUBY, __FILE__, __LINE__ +1 - def #{method}(*args) - scope.send(:_with_routes, routes) do - scope.#{method}(*args) - end - end - RUBY - end - attr_accessor :scope, :routes alias :_routes :routes @@ -281,6 +271,12 @@ module ActionDispatch @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 -- cgit v1.2.3 From bfccbc6df91a3c24bbf99262383c6f1e9069e1dd Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 26 Jul 2010 17:05:04 +0200 Subject: Add Rails::Railtie.railtie_name method to allow setting custom name for railtie --- actionpack/lib/action_dispatch/routing/mapper.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index ef1bee106a..b437d7a17d 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -277,8 +277,13 @@ module ActionDispatch private def app_name(app) return unless app.respond_to?(:routes) - class_name = app.class.is_a?(Class) ? app.name : app.class.name - ActiveSupport::Inflector.underscore(class_name).gsub("/", "_") + + 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) -- cgit v1.2.3 From 401cd97923fb52c8f8c458b8cb276b338e0b20f3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 29 Jul 2010 14:12:25 +0200 Subject: Modified ActionDispatch::Static to allow passing multiple roots --- .../lib/action_dispatch/middleware/static.rb | 60 ++++++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index d7e88a54e4..c2d686f514 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -2,11 +2,43 @@ require 'rack/utils' module ActionDispatch class Static + class FileHandler + def initialize(at, root) + @at = at.chomp("/") + @file_server = ::Rack::File.new(root) + end + + def file_exist?(path) + (path = full_readable_path(path)) && File.file?(path) + end + + def directory_exist?(path) + (path = full_readable_path(path)) && File.directory?(path) + end + + def call(env) + env["PATH_INFO"].gsub!(/^#{@at}/, "") + @file_server.call(env) + end + + private + def includes_path?(path) + @at == "" || path =~ /^#{@at}/ + end + + def full_readable_path(path) + return unless includes_path?(path) + path = path.gsub(/^#{@at}/, "") + File.join(@file_server.root, ::Rack::Utils.unescape(path)) + end + end + FILE_METHODS = %w(GET HEAD).freeze - def initialize(app, root) + def initialize(app, roots) @app = app - @file_server = ::Rack::File.new(root) + roots = normalize_roots(roots) + @file_handlers = file_handlers(roots) end def call(env) @@ -14,15 +46,15 @@ module ActionDispatch method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - if file_exist?(path) - return @file_server.call(env) + if file_handler = file_exist?(path) + return file_handler.call(env) else cached_path = directory_exist?(path) ? "#{path}/index" : path cached_path += ::ActionController::Base.page_cache_extension - if file_exist?(cached_path) + if file_handler = file_exist?(cached_path) env['PATH_INFO'] = cached_path - return @file_server.call(env) + return file_handler.call(env) end end end @@ -32,13 +64,21 @@ module ActionDispatch private def file_exist?(path) - full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path)) - File.file?(full_path) && File.readable?(full_path) + @file_handlers.detect { |f| f.file_exist?(path) } end def directory_exist?(path) - full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path)) - File.directory?(full_path) && File.readable?(full_path) + @file_handlers.detect { |f| f.directory_exist?(path) } + end + + def normalize_roots(roots) + roots.is_a?(Hash) ? roots : { "/" => roots.chomp("/") } + end + + def file_handlers(roots) + roots.map do |at, root| + FileHandler.new(at, root) + end end end end -- cgit v1.2.3 From 99131939316230065b4297573d080d1585e4e5a7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 31 Jul 2010 11:27:08 +0200 Subject: For view_context we need to initialize RoutesProxy in context of controller, not view, quick fix, I need to dig into it later --- actionpack/lib/action_dispatch/routing/route_set.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 121e7c2c75..c67b0199ce 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -301,11 +301,13 @@ module ActionDispatch MountedHelpers end - def define_mounted_helper(name, helpers = nil) + 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) + RoutesProxy.new(routes, (self.respond_to?(:controller) ? controller : self)) end end -- cgit v1.2.3 From befa77fc18ba54c1be89553466312039c1073f02 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 2 Aug 2010 02:55:01 +0200 Subject: Fix generating urls with mounted helpers in view context There were actually 2 problems with this one: * script_name was added to options as a string and then it was used in RouteSet#url_for with usage of <<, which was changing the original script_name * the second issue was with _with_routes method. It was called in RoutesProxy to modify _routes in view_context, but url_helpers in views is just delegating it to controller, so another _with_routes call is needed there --- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c67b0199ce..6e7e133cc5 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -307,7 +307,7 @@ module ActionDispatch routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, (self.respond_to?(:controller) ? controller : self)) + RoutesProxy.new(routes, self) end end -- cgit v1.2.3 From 79bd92b7833d52b74f50259cf8a21f9b05f3e9e3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 3 Aug 2010 19:36:53 +0200 Subject: Refactor ActionMailer to not use hide_actions --- actionpack/lib/action_dispatch/routing/route_set.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 6e7e133cc5..219fa37fcb 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -337,7 +337,12 @@ module ActionDispatch # Yes plz - JP included do routes.install_helpers(self) - singleton_class.send(:define_method, :_routes) { @_routes || routes } + singleton_class.send(:define_method, :_routes) { routes } + end + + def initialize(*) + @_routes = nil + super end define_method(:_routes) { @_routes || routes } -- cgit v1.2.3 From f3c703a32f6c7833705e46b8e14f172330a1c916 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 4 Aug 2010 16:20:56 +0200 Subject: Refactor RoutesProxy to avoid using _with_routes in helpers --- actionpack/lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/lib/action_dispatch/routing/url_for.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 219fa37fcb..363bcbd2b0 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -307,7 +307,7 @@ module ActionDispatch routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, self) + RoutesProxy.new(routes, self._routes_context) end end diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 19db730b6a..e836cf7c8e 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -141,6 +141,10 @@ module ActionDispatch ensure @_routes = old_routes end + + def _routes_context + self + end end end end -- cgit v1.2.3 From 8fb9df535e9fcf4c117ffd3254027e0fe2425cb7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 4 Aug 2010 23:00:33 +0200 Subject: Modified polymorphic_url to check for model's namespace This change allows using namespaced models with polymorphic_url, in the way that you would use them without namespace. Let's say that you have Blog::Post model in namespaced Engine. When you use polymorphic_path with Blog::Post instances, like in form_for(@post), it will look for blog_posts_path named url helper. As we are inside Blog::Engine, it's annoying to always use the prefix. With this commit, blog_ prefix will be removed and posts_path will be called. --- actionpack/lib/action_dispatch/routing/polymorphic_routes.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 15ee7c8051..037b94b577 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,6 +111,10 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end + if namespace = record.class.parents.detect { |n| n.respond_to?(:_railtie) } + named_route.sub!(/#{namespace._railtie.railtie_name}_/, '') + end + url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end -- cgit v1.2.3 From 00874a2009ce209d0c3a3cc2bf6c26b1bb15f3e5 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 22 Aug 2010 18:06:03 +0200 Subject: This was used only to clear warning in ActionMailer tests, it shouldn't be done like that --- actionpack/lib/action_dispatch/routing/route_set.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 363bcbd2b0..c09c1fef6f 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -340,11 +340,6 @@ module ActionDispatch singleton_class.send(:define_method, :_routes) { routes } end - def initialize(*) - @_routes = nil - super - end - define_method(:_routes) { @_routes || routes } end -- cgit v1.2.3 From 8ec2175aee93ecfd928de67c0a125bccc5e1c152 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 23 Aug 2010 14:02:05 +0200 Subject: Added more tests for polymorphic_url with namespaced models and implemented missing use cases --- .../lib/action_dispatch/routing/polymorphic_routes.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 037b94b577..517936bc96 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -111,10 +111,6 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - if namespace = record.class.parents.detect { |n| n.respond_to?(:_railtie) } - named_route.sub!(/#{namespace._railtie.railtie_name}_/, '') - end - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) end @@ -159,7 +155,8 @@ module ActionDispatch if parent.is_a?(Symbol) || parent.is_a?(String) parent else - ActiveModel::Naming.plural(parent).singularize + str = ActiveModel::Naming.plural(parent).singularize + remove_namespace(str, parent) end end end @@ -168,6 +165,7 @@ module ActionDispatch route << record else route << ActiveModel::Naming.plural(record) + remove_namespace(route, record) route = [route.join("_").singularize] if inflection == :singular route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural end @@ -177,6 +175,13 @@ module ActionDispatch action_prefix(options) + route.join("_") end + def remove_namespace(string, parent) + if namespace = parent.class.parents.detect { |n| n.respond_to?(:_railtie) } + string.sub!(/#{namespace._railtie.railtie_name}_/, '') + end + string + end + def extract_record(record_or_hash_or_array) case record_or_hash_or_array when Array; record_or_hash_or_array.last -- cgit v1.2.3 From b1c66f060bba22d16abf6d24d3df762c240e367c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 13:41:56 +0200 Subject: Move RoutesProxy to separate file --- actionpack/lib/action_dispatch/routing.rb | 1 + .../lib/action_dispatch/routing/route_set.rb | 32 -------------------- .../lib/action_dispatch/routing/routes_proxy.rb | 35 ++++++++++++++++++++++ 3 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 actionpack/lib/action_dispatch/routing/routes_proxy.rb (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 0b9689dc88..b2b0f4c08e 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -268,6 +268,7 @@ module ActionDispatch 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/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c09c1fef6f..0d83ca956b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -261,38 +261,6 @@ module ActionDispatch named_routes.install(destinations, regenerate_code) end - class RoutesProxy - 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 - module MountedHelpers end 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 0000000000..f7d5f6397d --- /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 -- cgit v1.2.3 From 613cbe1f0075eed7ebf1ac521e99f652f6891330 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 15:42:24 +0200 Subject: Add possibility to explicitly call engine's routes through polymorphic_routes, for example: polymorphic_url([blog, @post]) --- .../action_dispatch/routing/polymorphic_routes.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 517936bc96..e8ba1de40e 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -42,6 +42,18 @@ module ActionDispatch # # 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 ActionDispatch 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,11 @@ module ActionDispatch args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options end - url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args) + if proxy + proxy.send(named_route, *args) + else + 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 -- cgit v1.2.3 From 706a3223a303d56feeee2cc7601da1bd9f381243 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 25 Aug 2010 15:59:25 +0200 Subject: Add short note on using url_for instead of directly calling named route in polymorphic_url --- actionpack/lib/action_dispatch/routing/polymorphic_routes.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index e8ba1de40e..ecc1651dfe 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -129,6 +129,9 @@ module ActionDispatch 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 -- cgit v1.2.3 From 2607def8621c41d5b0bee09e379ae26890b27f7d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 31 Aug 2010 23:43:32 +0200 Subject: Use new ActiveModel::Naming.route_key in polymorphic_routes --- .../lib/action_dispatch/routing/polymorphic_routes.rb | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index ecc1651dfe..02ba5236ee 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -177,8 +177,7 @@ module ActionDispatch if parent.is_a?(Symbol) || parent.is_a?(String) parent else - str = ActiveModel::Naming.plural(parent).singularize - remove_namespace(str, parent) + ActiveModel::Naming.route_key(parent).singularize end end end @@ -186,8 +185,7 @@ module ActionDispatch if record.is_a?(Symbol) || record.is_a?(String) route << record else - route << ActiveModel::Naming.plural(record) - remove_namespace(route, record) + route << ActiveModel::Naming.route_key(record) route = [route.join("_").singularize] if inflection == :singular route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural end @@ -197,13 +195,6 @@ module ActionDispatch action_prefix(options) + route.join("_") end - def remove_namespace(string, parent) - if namespace = parent.class.parents.detect { |n| n.respond_to?(:_railtie) } - string.sub!(/#{namespace._railtie.railtie_name}_/, '') - end - string - end - def extract_record(record_or_hash_or_array) case record_or_hash_or_array when Array; record_or_hash_or_array.last -- cgit v1.2.3 From b8d6dc3c84321c751ab2ca8232e1e3fb332a844c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 1 Sep 2010 19:17:47 +0200 Subject: Implemented RouteSet#default_scope, which allows to set the scope for the entire routes object --- actionpack/lib/action_dispatch/routing/mapper.rb | 6 ++++++ actionpack/lib/action_dispatch/routing/route_set.rb | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index b437d7a17d..900900ee24 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -274,6 +274,12 @@ module ActionDispatch 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) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0d83ca956b..107e44287d 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -199,7 +199,7 @@ module ActionDispatch 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 @@ module ActionDispatch 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 -- cgit v1.2.3 From 9f0a1ae14e2a9306605d7b572612ccf36fa8b2da Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Sep 2010 12:48:21 +0200 Subject: Optimize ActionDispatch::Static --- .../lib/action_dispatch/middleware/static.rb | 86 +++++++++------------- 1 file changed, 35 insertions(+), 51 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index c2d686f514..e7e335df49 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -1,44 +1,43 @@ require 'rack/utils' module ActionDispatch - class Static - class FileHandler - def initialize(at, root) - @at = at.chomp("/") - @file_server = ::Rack::File.new(root) - end - - def file_exist?(path) - (path = full_readable_path(path)) && File.file?(path) - end - - def directory_exist?(path) - (path = full_readable_path(path)) && File.directory?(path) - end - - def call(env) - env["PATH_INFO"].gsub!(/^#{@at}/, "") - @file_server.call(env) - end + 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) + + ext = ::ActionController::Base.page_cache_extension + @ext = "{,#{ext},/index#{ext}}" + end - private - def includes_path?(path) - @at == "" || path =~ /^#{@at}/ + 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 full_readable_path(path) - return unless includes_path?(path) - path = path.gsub(/^#{@at}/, "") - File.join(@file_server.root, ::Rack::Utils.unescape(path)) - end + def call(env) + @file_server.call(env) end + end + class Static FILE_METHODS = %w(GET HEAD).freeze def initialize(app, roots) @app = app - roots = normalize_roots(roots) - @file_handlers = file_handlers(roots) + @file_handlers = create_file_handlers(roots) end def call(env) @@ -46,14 +45,9 @@ module ActionDispatch method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - if file_handler = file_exist?(path) - return file_handler.call(env) - else - cached_path = directory_exist?(path) ? "#{path}/index" : path - cached_path += ::ActionController::Base.page_cache_extension - - if file_handler = file_exist?(cached_path) - env['PATH_INFO'] = cached_path + @file_handlers.each do |file_handler| + if match = file_handler.match?(path) + env["PATH_INFO"] = match return file_handler.call(env) end end @@ -63,22 +57,12 @@ module ActionDispatch end private - def file_exist?(path) - @file_handlers.detect { |f| f.file_exist?(path) } - end + def create_file_handlers(roots) + roots = { '' => roots } unless roots.is_a?(Hash) - def directory_exist?(path) - @file_handlers.detect { |f| f.directory_exist?(path) } - end - - def normalize_roots(roots) - roots.is_a?(Hash) ? roots : { "/" => roots.chomp("/") } - end - - def file_handlers(roots) roots.map do |at, root| - FileHandler.new(at, root) - end + FileHandler.new(at, root) if File.exist?(root) + end.compact end end end -- cgit v1.2.3 From c3c1a1e14859e6716970283caeab0c4c3720862e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 3 Sep 2010 23:25:57 +0200 Subject: Do not use ActionController::Base.page_cache_extension in initialize to not load more ActiveSupport than we need --- actionpack/lib/action_dispatch/middleware/static.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'actionpack/lib/action_dispatch') diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index e7e335df49..581cadbeb4 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -7,16 +7,13 @@ module ActionDispatch @compiled_at = Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank? @compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/) @file_server = ::Rack::File.new(root) - - ext = ::ActionController::Base.page_cache_extension - @ext = "{,#{ext},/index#{ext}}" 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}" + paths = "#{full_path}#{ext}" matches = Dir[paths] match = matches.detect { |m| File.file?(m) } @@ -30,6 +27,13 @@ module ActionDispatch 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 -- cgit v1.2.3