| Module | Ardes::ResourcesController::NamedRouteHelper |
| In: |
lib/ardes/resources_controller/named_route_helper.rb
|
This module provides methods are provided to aid in writing inheritable controllers.
When writing an action that redirects to the list of resources, you may use resources_url and the controller will call the url_writer method appropriate to what the controller is a resources controller for.
If the route specified requires a member argument and you don‘t provide it, the current resource is used.
In general you may subsitute ‘resource’ for the current (maybe polymorphic) resource. e.g.
You may also substitute ‘enclosing_resource’ to get urls for the enclosing resource
(in attachable/attachments where attachable is a Post)
resources_path # => post_attachments_path
formatted_edit_resource_path('js') # => formatted_post_attachments_path(<current post>, <current attachment>, 'js')
resource_tags_path # => post_attachments_tags_paths(<current post>, <current attachment>)
resource_tags_path(foo) # => post_attachments_tags_paths(<current post>, foo)
enclosing_resource_path # => post_path(<current post>)
enclosing_resources_path # => posts_path
enclosing_resource_tags_path # => post_tags_path(<current post>)
enclosing_resource_path(2) # => post_path(2)
The enclosing_resource stuff works with deep nesting if you‘re into that.
These methods are defined as they are used. The ActionView Helper module delegates to the current controller to access these methods
# File lib/ardes/resources_controller/named_route_helper.rb, line 35
35: def self.included(base)
36: base.class_eval do
37: alias_method_chain :method_missing, :named_route_helper
38: alias_method_chain :respond_to?, :named_route_helper
39: end
40: base.hide_action *instance_methods
41: base.hide_action :method_missing_without_named_route_helper, :respond_to_without_named_route_helper?, :respond_to?
42: end
# File lib/ardes/resources_controller/named_route_helper.rb, line 44
44: def method_missing_with_named_route_helper(method, *args, &block)
45: # TODO: test that methods are only defined once
46: if resource_named_route_helper_method?(method, raise_error = true)
47: define_resource_named_route_helper_method(method)
48: send(method, *args)
49: elsif resource_named_route_helper_method_for_name_prefix?(method)
50: define_resource_named_route_helper_method_for_name_prefix(method)
51: send(method, *args)
52: else
53: method_missing_without_named_route_helper(method, *args, &block)
54: end
55: end
return true if the passed method (e.g. ‘resources_path’) corresponds to a defined named route helper method
# File lib/ardes/resources_controller/named_route_helper.rb, line 63
63: def resource_named_route_helper_method?(resource_method, raise_error = false)
64: if resource_method.to_s =~ /_(path|url)$/ && resource_method.to_s =~ /(^|^.*_)enclosing_resource(s)?_/
65: _, route_method = *route_and_method_from_enclosing_resource_method_and_name_prefix(resource_method, name_prefix)
66: elsif resource_method.to_s =~ /_(path|url)$/ && resource_method.to_s =~ /(^|^.*_)resource(s)?_/
67: _, route_method = *route_and_method_from_resource_method_and_name_prefix(resource_method, name_prefix)
68: else
69: return false
70: end
71: respond_to_without_named_route_helper?(route_method) || (raise_error && raise_resource_url_mapping_error(resource_method, route_method))
72: end
# File lib/ardes/resources_controller/named_route_helper.rb, line 57
57: def respond_to_with_named_route_helper?(method)
58: respond_to_without_named_route_helper?(method) || resource_named_route_helper_method?(method)
59: end
defines a method that calls the appropriate named route method, with appropraite args.
# File lib/ardes/resources_controller/named_route_helper.rb, line 111
111: def define_resource_named_route_helper_method(method)
112: self.class.send :module_eval, "def \#{method}(*args)\nsend \"\#{method}_for_\\\#{name_prefix}\", *args\nend\n", __FILE__, __LINE__
113: end
# File lib/ardes/resources_controller/named_route_helper.rb, line 124
124: def define_resource_named_route_helper_method_for_name_prefix(method)
125: resource_method = method.to_s.sub(/_for_.*$/,'')
126: name_prefix = method.to_s.sub(/^.*_for_/,'')
127: if resource_method =~ /enclosing_resource/
128: route, route_method = *route_and_method_from_enclosing_resource_method_and_name_prefix(resource_method, name_prefix)
129: required_args = route.significant_keys.reject{|k| [:controller, :action].include?(k)}.size
130:
131: self.class.send :module_eval, "def \#{method}(*args)\noptions = args.extract_options!\nargs = args.size < \#{required_args} ? enclosing_collection_resources + args : enclosing_collection_resources - [enclosing_resource] + args\nargs = args + [options] if options.size > 0\nsend :\#{route_method}, *args\nend\n", __FILE__, __LINE__
132:
133: else
134: route, route_method = *route_and_method_from_resource_method_and_name_prefix(resource_method, name_prefix)
135: required_args = route.significant_keys.reject{|k| [:controller, :action].include?(k)}.size
136:
137: self.class.send :module_eval, "def \#{method}(*args)\noptions = args.extract_options!\n\#{\"args = [resource] + args if enclosing_collection_resources.size + args.size < \#{required_args}\" if required_args > 0}\nargs = args + [options] if options.size > 0\nsend :\#{route_method}, *(enclosing_collection_resources + args)\nend\n", __FILE__, __LINE__
138: end
139:
140: self.class.send :private, method
141: end
# File lib/ardes/resources_controller/named_route_helper.rb, line 75
75: def raise_resource_url_mapping_error(resource_method, route_method)
76: raise CantMapRoute, "Tried to map :\#{resource_method} to :\#{route_method},\nwhich doesn't exist. You may not have defined the route in config/routes.rb.\n\nOr, if you have unconventianal route names or name prefixes, you may need\nto explicictly set the :route option in resources_controller_for, and set\nthe :name_prefix option on your enclosing resources.\n\nCurrently:\n:route is '\#{route_name}'\ngenerated name_prefix is '\#{name_prefix}'\n"
77: end
# File lib/ardes/resources_controller/named_route_helper.rb, line 120
120: def resource_named_route_helper_method_for_name_prefix?(method)
121: method.to_s =~ /_for_.*$/ && resource_named_route_helper_method?(method.to_s.sub(/_for_.*$/,''))
122: end
passed something like (^|.*_)enclosing_resource(s)_.*(url|path)$, will return the [route, route_method] for the expanded resource
# File lib/ardes/resources_controller/named_route_helper.rb, line 93
93: def route_and_method_from_enclosing_resource_method_and_name_prefix(method, name_prefix)
94: if enclosing_resource
95: enclosing_route = name_prefix.sub(/_$/,'')
96: route_method = method.to_s.sub(/enclosing_resource(s)?/) { $1 ? enclosing_route.pluralize : enclosing_route }
97: return [ActionController::Routing::Routes.named_routes.get(route_method.sub(/_(path|url)$/,'').to_sym), route_method]
98: else
99: raise NoMethodError, "Tried to map :#{method} but there is no enclosing_resource for this controller"
100: end
101: end
passed something like (^|.*_)resource(s)_.*(url|path)$, will return the [route, route_method] for the expanded resource
# File lib/ardes/resources_controller/named_route_helper.rb, line 105
105: def route_and_method_from_resource_method_and_name_prefix(method, name_prefix)
106: route_method = method.to_s.sub(/resource(s)?/) { $1 ? "#{name_prefix}#{route_name.pluralize}" : "#{name_prefix}#{route_name}" }
107: return [ActionController::Routing::Routes.named_routes.get(route_method.sub(/_(path|url)$/,'').to_sym), route_method]
108: end