rails_legacy_mapper 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemtest +0 -0
- data/CHANGELOG +3 -0
- data/LICENSE +20 -0
- data/README +25 -0
- data/Rakefile +27 -0
- data/lib/rails_legacy_mapper.rb +23 -0
- data/lib/rails_legacy_mapper/mapper.rb +488 -0
- data/lib/rails_legacy_mapper/route_set_extensions.rb +53 -0
- data/lib/rails_legacy_mapper/version.rb +3 -0
- data/rails_legacy_mapper.gemspec +55 -0
- data/test/fake_controllers.rb +66 -0
- data/test/legacy_route_set_test.rb +578 -0
- data/test/rack_mount_integration_test.rb +310 -0
- data/test/resources_test.rb +1395 -0
- data/test/route_set_test.rb +959 -0
- data/test/test_helper.rb +48 -0
- data/test/uri_reserved_characters_routing_test.rb +54 -0
- metadata +158 -0
data/.gemtest
ADDED
File without changes
|
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Andrew White
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
== Rails Legacy Mapper
|
2
|
+
This gem provides an extraction of the DeprecatedMapper from Rails 3.0.
|
3
|
+
If you have a legacy application with an old style routes.rb file this
|
4
|
+
allows you to get your application running quickly in Rails 3.1.
|
5
|
+
|
6
|
+
=== Example
|
7
|
+
The trigger for using the legacy mapper is the arity (number of args)
|
8
|
+
of the block passed to draw, e.g:
|
9
|
+
|
10
|
+
LegacyApp::Application.routes.draw do |map|
|
11
|
+
|
12
|
+
map.root :controller => 'pages', :action => 'index'
|
13
|
+
|
14
|
+
map.namespace :admin do |admin|
|
15
|
+
admin.resources :pages
|
16
|
+
end
|
17
|
+
|
18
|
+
map.page '/pages/:id', :controller => 'pages', :action => 'show'
|
19
|
+
|
20
|
+
map.connect '/:controller/:action/:id/'
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
=== License
|
25
|
+
Copyright (c) 2011 Andrew White, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
desc 'Default: run rails_legacy_mapper tests.'
|
10
|
+
task :default => :test
|
11
|
+
|
12
|
+
desc 'Test the sortifiable gem.'
|
13
|
+
Rake::TestTask.new(:test) do |t|
|
14
|
+
t.libs << 'lib'
|
15
|
+
t.libs << 'test'
|
16
|
+
t.pattern = 'test/**/*_test.rb'
|
17
|
+
t.verbose = true
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Generate documentation for the rails_legacy_mapper gem.'
|
21
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'Rails Legacy Mapper'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RailsLegacyMapper
|
2
|
+
# This gem provides an extraction of the DeprecatedMapper from Rails 3.0
|
3
|
+
|
4
|
+
# Returns the current resource action separator - defaults to '/'
|
5
|
+
def self.resource_action_separator
|
6
|
+
@resource_action_separator ||= '/'
|
7
|
+
end
|
8
|
+
|
9
|
+
# Set the resource action separator, e.g:
|
10
|
+
#
|
11
|
+
# # config/initializers/rails_legacy_mapper.rb
|
12
|
+
# RailsLegacyMapper.resource_action_separator = ';'
|
13
|
+
def self.resource_action_separator=(value)
|
14
|
+
@resource_action_separator = value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rails_legacy_mapper/mapper'
|
19
|
+
require 'rails_legacy_mapper/route_set_extensions'
|
20
|
+
require 'rails_legacy_mapper/version'
|
21
|
+
require 'action_dispatch'
|
22
|
+
|
23
|
+
ActionDispatch::Routing::RouteSet.send(:include, RailsLegacyMapper::RouteSetExtensions)
|
@@ -0,0 +1,488 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'active_support/core_ext/object/with_options'
|
4
|
+
require 'active_support/core_ext/object/try'
|
5
|
+
require 'active_support/inflector'
|
6
|
+
|
7
|
+
module RailsLegacyMapper
|
8
|
+
class Mapper #:nodoc:
|
9
|
+
def initialize(set) #:nodoc:
|
10
|
+
@set = set
|
11
|
+
end
|
12
|
+
|
13
|
+
def connect(path, options = {})
|
14
|
+
options = options.dup
|
15
|
+
|
16
|
+
if conditions = options.delete(:conditions)
|
17
|
+
conditions = conditions.dup
|
18
|
+
method = Array.wrap(conditions.delete(:method))
|
19
|
+
method.map! { |m|
|
20
|
+
if m == :head
|
21
|
+
raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
|
22
|
+
end
|
23
|
+
|
24
|
+
unless ActionDispatch::Routing::HTTP_METHODS.include?(m)
|
25
|
+
raise ArgumentError, "Invalid HTTP method specified in route conditions"
|
26
|
+
end
|
27
|
+
|
28
|
+
m.to_s.dasherize.upcase
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
path_prefix = options.delete(:path_prefix)
|
33
|
+
name_prefix = options.delete(:name_prefix)
|
34
|
+
namespace = options.delete(:namespace)
|
35
|
+
|
36
|
+
name = options.delete(:_name)
|
37
|
+
name = "#{name_prefix}#{name}" if name_prefix
|
38
|
+
|
39
|
+
requirements = options.delete(:requirements) || {}
|
40
|
+
defaults = options.delete(:defaults) || {}
|
41
|
+
options.each do |k, v|
|
42
|
+
if v.is_a?(Regexp)
|
43
|
+
if value = options.delete(k)
|
44
|
+
requirements[k.to_sym] = value
|
45
|
+
end
|
46
|
+
else
|
47
|
+
value = options.delete(k)
|
48
|
+
defaults[k.to_sym] = value.is_a?(Symbol) ? value : value.to_param
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
requirements.each do |_, requirement|
|
53
|
+
if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
|
54
|
+
raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
|
55
|
+
end
|
56
|
+
if requirement.multiline?
|
57
|
+
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
requirements[:controller] ||= @set.controller_constraints
|
62
|
+
|
63
|
+
if defaults[:controller]
|
64
|
+
defaults[:action] ||= 'index'
|
65
|
+
defaults[:controller] = defaults[:controller].to_s
|
66
|
+
defaults[:controller] = "#{namespace}#{defaults[:controller]}" if namespace
|
67
|
+
end
|
68
|
+
|
69
|
+
if defaults[:action]
|
70
|
+
defaults[:action] = defaults[:action].to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
if path.is_a?(String)
|
74
|
+
path = "#{path_prefix}/#{path}" if path_prefix
|
75
|
+
path = path.gsub('.:format', '(.:format)')
|
76
|
+
path = optionalize_trailing_dynamic_segments(path, requirements, defaults)
|
77
|
+
glob = $1.to_sym if path =~ /\/\*(\w+)$/
|
78
|
+
path = ::Rack::Mount::Utils.normalize_path(path)
|
79
|
+
|
80
|
+
if glob && !defaults[glob].blank?
|
81
|
+
raise ActionController::RoutingError, "paths cannot have non-empty default values"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
app = ActionDispatch::Routing::RouteSet::Dispatcher.new(:defaults => defaults, :glob => glob)
|
86
|
+
|
87
|
+
conditions = {}
|
88
|
+
conditions[:request_method] = method if method && !method.empty?
|
89
|
+
conditions[:path_info] = path if path
|
90
|
+
|
91
|
+
@set.add_route(app, conditions, requirements, defaults, name)
|
92
|
+
end
|
93
|
+
|
94
|
+
def optionalize_trailing_dynamic_segments(path, requirements, defaults) #:nodoc:
|
95
|
+
path = (path =~ /^\//) ? path.dup : "/#{path}"
|
96
|
+
optional, segments = true, []
|
97
|
+
|
98
|
+
required_segments = requirements.keys
|
99
|
+
required_segments -= defaults.keys.compact
|
100
|
+
|
101
|
+
old_segments = path.split('/')
|
102
|
+
old_segments.shift
|
103
|
+
length = old_segments.length
|
104
|
+
|
105
|
+
old_segments.reverse.each_with_index do |segment, index|
|
106
|
+
required_segments.each do |required|
|
107
|
+
if segment =~ /#{required}/
|
108
|
+
optional = false
|
109
|
+
break
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if optional
|
114
|
+
if segment == ":id" && segments.include?(":action")
|
115
|
+
optional = false
|
116
|
+
elsif segment == ":controller" || segment == ":action" || segment == ":id"
|
117
|
+
# Ignore
|
118
|
+
elsif !(segment =~ /^:\w+$/) &&
|
119
|
+
!(segment =~ /^:\w+\(\.:format\)$/)
|
120
|
+
optional = false
|
121
|
+
elsif segment =~ /^:(\w+)$/
|
122
|
+
if defaults.has_key?($1.to_sym)
|
123
|
+
defaults.delete($1.to_sym) if defaults[$1.to_sym].nil?
|
124
|
+
else
|
125
|
+
optional = false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if optional && index < length - 1
|
131
|
+
segments.unshift('(/', segment)
|
132
|
+
segments.push(')')
|
133
|
+
elsif optional
|
134
|
+
segments.unshift('/(', segment)
|
135
|
+
segments.push(')')
|
136
|
+
else
|
137
|
+
segments.unshift('/', segment)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
segments.join
|
142
|
+
end
|
143
|
+
private :optionalize_trailing_dynamic_segments
|
144
|
+
|
145
|
+
# Creates a named route called "root" for matching the root level request.
|
146
|
+
def root(options = {})
|
147
|
+
if options.is_a?(Symbol)
|
148
|
+
if source_route = @set.named_routes.routes[options]
|
149
|
+
options = source_route.defaults.merge({ :conditions => source_route.conditions })
|
150
|
+
end
|
151
|
+
end
|
152
|
+
named_route("root", '', options)
|
153
|
+
end
|
154
|
+
|
155
|
+
def named_route(name, path, options = {}) #:nodoc:
|
156
|
+
options[:_name] = name
|
157
|
+
connect(path, options)
|
158
|
+
end
|
159
|
+
|
160
|
+
def namespace(name, options = {}, &block)
|
161
|
+
if options[:namespace]
|
162
|
+
with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block)
|
163
|
+
else
|
164
|
+
with_options({:path_prefix => name, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def method_missing(route_name, *args, &proc) #:nodoc:
|
169
|
+
super unless args.length >= 1 && proc.nil?
|
170
|
+
named_route(route_name, *args)
|
171
|
+
end
|
172
|
+
|
173
|
+
INHERITABLE_OPTIONS = :namespace, :shallow
|
174
|
+
|
175
|
+
class Resource #:nodoc:
|
176
|
+
DEFAULT_ACTIONS = :index, :create, :new, :edit, :show, :update, :destroy
|
177
|
+
|
178
|
+
attr_reader :collection_methods, :member_methods, :new_methods
|
179
|
+
attr_reader :path_prefix, :name_prefix, :path_segment
|
180
|
+
attr_reader :plural, :singular
|
181
|
+
attr_reader :options, :defaults
|
182
|
+
|
183
|
+
def initialize(entities, options, defaults)
|
184
|
+
@plural ||= entities
|
185
|
+
@singular ||= options[:singular] || plural.to_s.singularize
|
186
|
+
@path_segment = options.delete(:as) || @plural
|
187
|
+
|
188
|
+
@options = options
|
189
|
+
@defaults = defaults
|
190
|
+
|
191
|
+
arrange_actions
|
192
|
+
add_default_actions
|
193
|
+
set_allowed_actions
|
194
|
+
set_prefixes
|
195
|
+
end
|
196
|
+
|
197
|
+
def controller
|
198
|
+
@controller ||= "#{options[:namespace]}#{(options[:controller] || plural).to_s}"
|
199
|
+
end
|
200
|
+
|
201
|
+
def requirements(with_id = false)
|
202
|
+
@requirements ||= @options[:requirements] || {}
|
203
|
+
@id_requirement ||= { :id => @requirements.delete(:id) || /[^#{ActionDispatch::Routing::SEPARATORS.join}]+/ }
|
204
|
+
|
205
|
+
with_id ? @requirements.merge(@id_requirement) : @requirements
|
206
|
+
end
|
207
|
+
|
208
|
+
def conditions
|
209
|
+
@conditions ||= @options[:conditions] || {}
|
210
|
+
end
|
211
|
+
|
212
|
+
def path
|
213
|
+
@path ||= "#{path_prefix}/#{path_segment}"
|
214
|
+
end
|
215
|
+
|
216
|
+
def new_path
|
217
|
+
new_action = self.options[:path_names][:new] if self.options[:path_names]
|
218
|
+
new_action ||= self.defaults[:path_names][:new]
|
219
|
+
@new_path ||= "#{path}/#{new_action}"
|
220
|
+
end
|
221
|
+
|
222
|
+
def shallow_path_prefix
|
223
|
+
@shallow_path_prefix ||= @options[:shallow] ? @options[:namespace].try(:sub, /\/$/, '') : path_prefix
|
224
|
+
end
|
225
|
+
|
226
|
+
def member_path
|
227
|
+
@member_path ||= "#{shallow_path_prefix}/#{path_segment}/:id"
|
228
|
+
end
|
229
|
+
|
230
|
+
def nesting_path_prefix
|
231
|
+
@nesting_path_prefix ||= "#{shallow_path_prefix}/#{path_segment}/:#{singular}_id"
|
232
|
+
end
|
233
|
+
|
234
|
+
def shallow_name_prefix
|
235
|
+
@shallow_name_prefix ||= @options[:shallow] ? @options[:namespace].try(:gsub, /\//, '_') : name_prefix
|
236
|
+
end
|
237
|
+
|
238
|
+
def nesting_name_prefix
|
239
|
+
"#{shallow_name_prefix}#{singular}_"
|
240
|
+
end
|
241
|
+
|
242
|
+
def action_separator
|
243
|
+
@action_separator ||= RailsLegacyMapper.resource_action_separator
|
244
|
+
end
|
245
|
+
|
246
|
+
def uncountable?
|
247
|
+
@singular.to_s == @plural.to_s
|
248
|
+
end
|
249
|
+
|
250
|
+
def has_action?(action)
|
251
|
+
!DEFAULT_ACTIONS.include?(action) || action_allowed?(action)
|
252
|
+
end
|
253
|
+
|
254
|
+
protected
|
255
|
+
def arrange_actions
|
256
|
+
@collection_methods = arrange_actions_by_methods(options.delete(:collection))
|
257
|
+
@member_methods = arrange_actions_by_methods(options.delete(:member))
|
258
|
+
@new_methods = arrange_actions_by_methods(options.delete(:new))
|
259
|
+
end
|
260
|
+
|
261
|
+
def add_default_actions
|
262
|
+
add_default_action(member_methods, :get, :edit)
|
263
|
+
add_default_action(new_methods, :get, :new)
|
264
|
+
end
|
265
|
+
|
266
|
+
def set_allowed_actions
|
267
|
+
only, except = @options.values_at(:only, :except)
|
268
|
+
@allowed_actions ||= {}
|
269
|
+
|
270
|
+
if only == :all || except == :none
|
271
|
+
only = nil
|
272
|
+
except = []
|
273
|
+
elsif only == :none || except == :all
|
274
|
+
only = []
|
275
|
+
except = nil
|
276
|
+
end
|
277
|
+
|
278
|
+
if only
|
279
|
+
@allowed_actions[:only] = Array(only).map {|a| a.to_sym }
|
280
|
+
elsif except
|
281
|
+
@allowed_actions[:except] = Array(except).map {|a| a.to_sym }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def action_allowed?(action)
|
286
|
+
only, except = @allowed_actions.values_at(:only, :except)
|
287
|
+
(!only || only.include?(action)) && (!except || !except.include?(action))
|
288
|
+
end
|
289
|
+
|
290
|
+
def set_prefixes
|
291
|
+
@path_prefix = options.delete(:path_prefix)
|
292
|
+
@name_prefix = options.delete(:name_prefix)
|
293
|
+
end
|
294
|
+
|
295
|
+
def arrange_actions_by_methods(actions)
|
296
|
+
(actions || {}).inject({}) do |flipped_hash, (key, value)|
|
297
|
+
(flipped_hash[value] ||= []) << key
|
298
|
+
flipped_hash
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def add_default_action(collection, method, action)
|
303
|
+
(collection[method] ||= []).unshift(action)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class SingletonResource < Resource #:nodoc:
|
308
|
+
def initialize(entity, options, defaults)
|
309
|
+
@singular = @plural = entity
|
310
|
+
options[:controller] ||= @singular.to_s.pluralize
|
311
|
+
super
|
312
|
+
end
|
313
|
+
|
314
|
+
alias_method :shallow_path_prefix, :path_prefix
|
315
|
+
alias_method :shallow_name_prefix, :name_prefix
|
316
|
+
alias_method :member_path, :path
|
317
|
+
alias_method :nesting_path_prefix, :path
|
318
|
+
end
|
319
|
+
|
320
|
+
def resources(*entities, &block)
|
321
|
+
options = entities.extract_options!
|
322
|
+
entities.each { |entity| map_resource(entity, options.dup, &block) }
|
323
|
+
end
|
324
|
+
|
325
|
+
def resource(*entities, &block)
|
326
|
+
options = entities.extract_options!
|
327
|
+
entities.each { |entity| map_singleton_resource(entity, options.dup, &block) }
|
328
|
+
end
|
329
|
+
|
330
|
+
private
|
331
|
+
def map_resource(entities, options = {}, &block)
|
332
|
+
resource = Resource.new(entities, options, :path_names => @set.resources_path_names)
|
333
|
+
|
334
|
+
with_options :controller => resource.controller do |map|
|
335
|
+
map_associations(resource, options)
|
336
|
+
|
337
|
+
if block_given?
|
338
|
+
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
|
339
|
+
end
|
340
|
+
|
341
|
+
map_collection_actions(map, resource)
|
342
|
+
map_default_collection_actions(map, resource)
|
343
|
+
map_new_actions(map, resource)
|
344
|
+
map_member_actions(map, resource)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def map_singleton_resource(entities, options = {}, &block)
|
349
|
+
resource = SingletonResource.new(entities, options, :path_names => @set.resources_path_names)
|
350
|
+
|
351
|
+
with_options :controller => resource.controller do |map|
|
352
|
+
map_associations(resource, options)
|
353
|
+
|
354
|
+
if block_given?
|
355
|
+
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
|
356
|
+
end
|
357
|
+
|
358
|
+
map_collection_actions(map, resource)
|
359
|
+
map_new_actions(map, resource)
|
360
|
+
map_member_actions(map, resource)
|
361
|
+
map_default_singleton_actions(map, resource)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def map_associations(resource, options)
|
366
|
+
map_has_many_associations(resource, options.delete(:has_many), options) if options[:has_many]
|
367
|
+
|
368
|
+
path_prefix = "#{options.delete(:path_prefix)}#{resource.nesting_path_prefix}"
|
369
|
+
name_prefix = "#{options.delete(:name_prefix)}#{resource.nesting_name_prefix}"
|
370
|
+
|
371
|
+
Array(options[:has_one]).each do |association|
|
372
|
+
resource(association, options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => path_prefix, :name_prefix => name_prefix))
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def map_has_many_associations(resource, associations, options)
|
377
|
+
case associations
|
378
|
+
when Hash
|
379
|
+
associations.each do |association,has_many|
|
380
|
+
map_has_many_associations(resource, association, options.merge(:has_many => has_many))
|
381
|
+
end
|
382
|
+
when Array
|
383
|
+
associations.each do |association|
|
384
|
+
map_has_many_associations(resource, association, options)
|
385
|
+
end
|
386
|
+
when Symbol, String
|
387
|
+
resources(associations, options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :has_many => options[:has_many]))
|
388
|
+
else
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def map_collection_actions(map, resource)
|
393
|
+
resource.collection_methods.each do |method, actions|
|
394
|
+
actions.each do |action|
|
395
|
+
[method].flatten.each do |m|
|
396
|
+
action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
|
397
|
+
action_path ||= action
|
398
|
+
|
399
|
+
map_resource_routes(map, resource, action, "#{resource.path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.name_prefix}#{resource.plural}", m)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def map_default_collection_actions(map, resource)
|
406
|
+
index_route_name = "#{resource.name_prefix}#{resource.plural}"
|
407
|
+
|
408
|
+
if resource.uncountable?
|
409
|
+
index_route_name << "_index"
|
410
|
+
end
|
411
|
+
|
412
|
+
map_resource_routes(map, resource, :index, resource.path, index_route_name)
|
413
|
+
map_resource_routes(map, resource, :create, resource.path, index_route_name)
|
414
|
+
end
|
415
|
+
|
416
|
+
def map_default_singleton_actions(map, resource)
|
417
|
+
map_resource_routes(map, resource, :create, resource.path, "#{resource.shallow_name_prefix}#{resource.singular}")
|
418
|
+
end
|
419
|
+
|
420
|
+
def map_new_actions(map, resource)
|
421
|
+
resource.new_methods.each do |method, actions|
|
422
|
+
actions.each do |action|
|
423
|
+
route_path = resource.new_path
|
424
|
+
route_name = "new_#{resource.name_prefix}#{resource.singular}"
|
425
|
+
|
426
|
+
unless action == :new
|
427
|
+
route_path = "#{route_path}#{resource.action_separator}#{action}"
|
428
|
+
route_name = "#{action}_#{route_name}"
|
429
|
+
end
|
430
|
+
|
431
|
+
map_resource_routes(map, resource, action, route_path, route_name, method)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def map_member_actions(map, resource)
|
437
|
+
resource.member_methods.each do |method, actions|
|
438
|
+
actions.each do |action|
|
439
|
+
[method].flatten.each do |m|
|
440
|
+
action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
|
441
|
+
action_path ||= @set.resources_path_names[action] || action
|
442
|
+
|
443
|
+
map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m, { :force_id => true })
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
route_path = "#{resource.shallow_name_prefix}#{resource.singular}"
|
449
|
+
map_resource_routes(map, resource, :show, resource.member_path, route_path)
|
450
|
+
map_resource_routes(map, resource, :update, resource.member_path, route_path)
|
451
|
+
map_resource_routes(map, resource, :destroy, resource.member_path, route_path)
|
452
|
+
end
|
453
|
+
|
454
|
+
def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil, resource_options = {} )
|
455
|
+
if resource.has_action?(action)
|
456
|
+
action_options = action_options_for(action, resource, method, resource_options)
|
457
|
+
formatted_route_path = "#{route_path}.:format"
|
458
|
+
|
459
|
+
if route_name && @set.named_routes[route_name.to_sym].nil?
|
460
|
+
map.named_route(route_name, formatted_route_path, action_options)
|
461
|
+
else
|
462
|
+
map.connect(formatted_route_path, action_options)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def add_conditions_for(conditions, method)
|
468
|
+
{:conditions => conditions.dup}.tap do |options|
|
469
|
+
options[:conditions][:method] = method unless method == :any
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def action_options_for(action, resource, method = nil, resource_options = {})
|
474
|
+
default_options = { :action => action.to_s }
|
475
|
+
require_id = !resource.kind_of?(SingletonResource)
|
476
|
+
force_id = resource_options[:force_id] && !resource.kind_of?(SingletonResource)
|
477
|
+
|
478
|
+
case default_options[:action]
|
479
|
+
when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements)
|
480
|
+
when "create"; default_options.merge(add_conditions_for(resource.conditions, method || :post)).merge(resource.requirements)
|
481
|
+
when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id))
|
482
|
+
when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id))
|
483
|
+
when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id))
|
484
|
+
else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(force_id))
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|