From cfdda38088c95194c3d8bb2fedb70bc06e8fe2e0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 8 May 2014 18:42:30 -0700 Subject: use the helper method builder to construct helper methods --- .../action_dispatch/routing/polymorphic_routes.rb | 163 ++++++++++++++------- actionpack/lib/action_dispatch/routing/url_for.rb | 6 +- 2 files changed, 112 insertions(+), 57 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 83b8c11e70..7afb2838e0 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -101,62 +101,42 @@ module ActionDispatch # polymorphic_url(Comment) # same as comments_url() # def polymorphic_url(record_or_hash_or_array, options = {}) - recipient = self - - opts = options.except(:action, :routing_type) - - prefix = action_prefix options - suffix = routing_type options - - if options[:action] == 'new' - builder = HelperMethodBuilder.singular prefix, suffix - else - builder = HelperMethodBuilder.plural prefix, suffix + if Hash === record_or_hash_or_array + options = record_or_hash_or_array.dup.merge!(options) + record = options.delete :id + return polymorphic_url record, options end - case record_or_hash_or_array - when Array - if record_or_hash_or_array.empty? || record_or_hash_or_array.any?(&:nil?) - raise ArgumentError, "Nil location provided. Can't build URI." - end - if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy) - recipient = record_or_hash_or_array.shift - end - - method, args = builder.handle_list record_or_hash_or_array - when Hash - unless record_or_hash_or_array[:id] - raise ArgumentError, "Nil location provided. Can't build URI." - end - - opts = record_or_hash_or_array.dup.merge!(opts) - record = opts.delete(:id) - - method, args = builder.handle_model record - - when String, Symbol - method, args = builder.handle_string record_or_hash_or_array - when Class - method, args = builder.handle_class record_or_hash_or_array - - when nil - raise ArgumentError, "Nil location provided. Can't build URI." - else - method, args = builder.handle_model record_or_hash_or_array - end + opts = options.dup + action = opts.delete :action + type = opts.delete(:routing_type) || :url + HelperMethodBuilder.polymorphic_method self, + record_or_hash_or_array, + action, + type, + opts - if opts.empty? - recipient.send(method, *args) - else - recipient.send(method, *args, opts) - end end # Returns the path component of a URL for the given record. It uses # polymorphic_url with routing_type: :path. def polymorphic_path(record_or_hash_or_array, options = {}) - polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path)) + if Hash === record_or_hash_or_array + options = record_or_hash_or_array.dup.merge!(options) + record = options.delete :id + return polymorphic_path record, options + end + + opts = options.dup + action = opts.delete :action + type = :path + + HelperMethodBuilder.polymorphic_method self, + record_or_hash_or_array, + action, + type, + opts end @@ -179,6 +159,26 @@ module ActionDispatch private class HelperMethodBuilder # :nodoc: + CACHE = { 'path' => {}, 'url' => {} } + + def self.get(action, type) + type = type.to_s + CACHE[type].fetch(action) { build action, type } + end + + def self.url; CACHE['url'.freeze][nil]; end + def self.path; CACHE['path'.freeze][nil]; end + + def self.build(action, type) + prefix = action ? "#{action}_" : "" + suffix = type + if action.to_s == 'new' + HelperMethodBuilder.singular prefix, suffix + else + HelperMethodBuilder.plural prefix, suffix + end + end + def self.singular(prefix, suffix) new(->(name) { name.singular_route_key }, prefix, suffix) end @@ -187,6 +187,38 @@ module ActionDispatch new(->(name) { name.route_key }, prefix, suffix) end + def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options) + builder = get action, type + + case record_or_hash_or_array + when Array + if record_or_hash_or_array.empty? || record_or_hash_or_array.include?(nil) + raise ArgumentError, "Nil location provided. Can't build URI." + end + if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy) + recipient = record_or_hash_or_array.shift + end + + method, args = builder.handle_list record_or_hash_or_array + when String, Symbol + method, args = builder.handle_string record_or_hash_or_array + when Class + method, args = builder.handle_class record_or_hash_or_array + + when nil + raise ArgumentError, "Nil location provided. Can't build URI." + else + method, args = builder.handle_model record_or_hash_or_array + end + + + if options.empty? + recipient.send(method, *args) + else + recipient.send(method, *args, options) + end + end + attr_reader :suffix, :prefix def initialize(key_strategy, prefix, suffix) @@ -196,13 +228,19 @@ module ActionDispatch end def handle_string(record) - method = prefix + "#{record}_#{suffix}" - [method, []] + [get_method_for_string(record), []] + end + + def handle_string_call(target, str) + target.send get_method_for_string str end def handle_class(klass) - name = @key_strategy.call klass.model_name - [prefix + "#{name}_#{suffix}", []] + [get_method_for_class(klass), []] + end + + def handle_class_call(target, klass) + target.send get_method_for_class klass end def handle_model(record) @@ -221,6 +259,11 @@ module ActionDispatch [named_route, args] end + def handle_model_call(target, model) + method, args = handle_model model + target.send(method, *args) + end + def handle_list(list) record_list = list.dup record = record_list.pop @@ -260,15 +303,23 @@ module ActionDispatch named_route = prefix + route.join("_") [named_route, args] end - end - def action_prefix(options) - options[:action] ? "#{options[:action]}_" : '' + private + + def get_method_for_class(klass) + name = @key_strategy.call klass.model_name + prefix + "#{name}_#{suffix}" + end + + def get_method_for_string(str) + prefix + "#{str}_#{suffix}" end - def routing_type(options) - options[:routing_type] || :url + [nil, 'new', 'edit'].each do |action| + CACHE['url'][action] = build action, 'url' + CACHE['path'][action] = build action, 'path' 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 0976e46903..e624fe3c4a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -155,10 +155,14 @@ module ActionDispatch _routes.url_for(options.symbolize_keys.reverse_merge!(url_options)) when String options + when Symbol + HelperMethodBuilder.url.handle_string_call self, options when Array polymorphic_url(options, options.extract_options!) + when Class + HelperMethodBuilder.url.handle_class_call self, options else - polymorphic_url(options, {}) + HelperMethodBuilder.url.handle_model_call self, options end end -- cgit v1.2.3