joshbuddy-usher 0.4.3 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,8 @@
1
- require 'set'
2
-
3
1
  class Usher
4
2
  class Route
5
3
  class Path
6
4
 
7
- attr_reader :dynamic_parts, :dynamic_map, :dynamic_indicies, :route, :dynamic_set, :parts
5
+ attr_reader :dynamic_parts, :dynamic_map, :dynamic_indicies, :route, :parts, :dynamic_required_keys, :dynamic_keys
8
6
 
9
7
  def initialize(route, parts)
10
8
  @route = route
@@ -14,9 +12,13 @@ class Usher
14
12
  @dynamic_parts = @parts.values_at(*@dynamic_indicies)
15
13
  @dynamic_map = {}
16
14
  @dynamic_parts.each{|p| @dynamic_map[p.name] = p }
17
- @dynamic_set = Set.new(@dynamic_map.keys)
15
+ @dynamic_keys = @dynamic_map.keys
16
+ @dynamic_required_keys = @dynamic_parts.select{|dp| !dp.default_value}.map{|dp| dp.name}
17
+ end
18
+
19
+ def can_generate_from?(keys)
20
+ (@dynamic_required_keys - keys).size.zero?
18
21
  end
19
-
20
22
  end
21
23
  end
22
24
  end
@@ -2,7 +2,7 @@ class Usher
2
2
  class Route
3
3
  class Variable
4
4
  attr_reader :type, :name, :validator, :regex_matcher
5
- attr_accessor :look_ahead, :globs_capture_separators
5
+ attr_accessor :look_ahead, :globs_capture_separators, :default_value
6
6
 
7
7
  def initialize(type, name, validator = nil, regex_matcher = nil, globs_capture_separators = false)
8
8
  @type = type
@@ -19,14 +19,16 @@ class Usher
19
19
  def valid!(val)
20
20
  case @validator
21
21
  when Proc
22
- @validator.call(val)
22
+ begin
23
+ @validator.call(val)
24
+ rescue Exception => e
25
+ raise ValidationException.new("#{val} does not conform to #{@validator}, root cause #{e.inspect}")
26
+ end
23
27
  else
24
- @validator === val or raise
28
+ @validator === val or raise(ValidationException.new("#{val} does not conform to #{@validator}, root cause #{e.inspect}"))
25
29
  end if @validator
26
- rescue Exception => e
27
- raise ValidationException.new("#{val} does not conform to #{@validator}, root cause #{e.inspect}")
28
30
  end
29
-
31
+
30
32
  def ==(o)
31
33
  o && (o.type == @type && o.name == @name && o.validator == @validator)
32
34
  end
data/lib/usher/route.rb CHANGED
@@ -6,17 +6,27 @@ require 'route/request_method'
6
6
 
7
7
  class Usher
8
8
  class Route
9
- attr_reader :paths, :original_path, :requirements, :conditions, :params, :primary_path
9
+ attr_reader :paths, :original_path, :requirements, :conditions, :destination, :named
10
10
 
11
- def initialize(original_path, router, options = nil) # :nodoc:
11
+ def initialize(original_path, router, conditions, requirements, default_values) # :nodoc:
12
12
  @original_path = original_path
13
13
  @router = router
14
- @requirements = options && options.delete(:requirements)
15
- @conditions = options && options.delete(:conditions)
16
- @paths = @router.splitter.split(@original_path, @requirements).collect {|path| Path.new(self, path)}
17
- @primary_path = @paths.first
18
- #FIXME params is poorly named. this shouldn't be an array
19
- @params = []
14
+ @requirements = requirements
15
+ @conditions = conditions
16
+ @default_values = default_values
17
+ @paths = @router.splitter.split(@original_path, @requirements, @default_values).collect {|path| Path.new(self, path)}
18
+ end
19
+
20
+ def grapher
21
+ unless @grapher
22
+ @grapher = Grapher.new
23
+ @grapher.add_route(self)
24
+ end
25
+ @grapher
26
+ end
27
+
28
+ def find_matching_path(params)
29
+ @paths.size == 1 ? @paths.first : grapher.find_matching_path(params)
20
30
  end
21
31
 
22
32
 
@@ -28,7 +38,7 @@ class Usher
28
38
  # route.to(:controller => 'testing', :action => 'index')
29
39
  # set.recognize(Request.new('/test')).first.params => {:controller => 'testing', :action => 'index'}
30
40
  def to(options = nil, &block)
31
- @params << (block_given? ? block : options)
41
+ @destination = (block_given? ? block : options)
32
42
  self
33
43
  end
34
44
 
@@ -38,7 +48,9 @@ class Usher
38
48
  # route = set.add_route('/test').name(:route)
39
49
  # set.generate_url(:route) => '/test'
40
50
  def name(name)
51
+ @named = name
41
52
  @router.name(name, self)
53
+ self
42
54
  end
43
55
 
44
56
  end
@@ -8,7 +8,7 @@ class Usher
8
8
  SplitterInstance.new(
9
9
  delimiters,
10
10
  Regexp.new('((:|\*)?' + valid_regex + '|' + delimiters_regex + '|\(|\)|\||\{)'),
11
- Regexp.new(delimiters_regex + '|' + valid_regex)
11
+ Regexp.new("[#{delimiters.collect{|d| Regexp.quote(d)}}]|[^#{delimiters.collect{|d| Regexp.quote(d)}}]+")
12
12
  )
13
13
  end
14
14
 
@@ -16,21 +16,20 @@ class Usher
16
16
 
17
17
  class SplitterInstance
18
18
 
19
+ attr_reader :delimiter_chars
20
+
19
21
  def initialize(delimiters, split_regex, url_split_regex)
20
22
  @delimiters = delimiters
21
23
  @delimiter_chars = delimiters.collect{|d| d[0]}
22
- @delimiter_chars_map = Hash[*@delimiter_chars.map{|c| [c, c.chr.to_sym]}.flatten]
23
24
  @split_regex = split_regex
24
25
  @url_split_regex = url_split_regex
25
26
  end
26
27
 
27
28
  def url_split(path)
28
- parts = path.scan(@url_split_regex)
29
- parts.map!{ |part| @delimiter_chars_map[part[0]] || part}
30
- parts
29
+ path.scan(@url_split_regex)
31
30
  end
32
31
 
33
- def split(path, requirements = nil)
32
+ def split(path, requirements = nil, default_values = nil)
34
33
  parts = Group.new(:all, nil)
35
34
  ss = StringScanner.new(path)
36
35
  current_group = parts
@@ -80,8 +79,6 @@ class Usher
80
79
  end
81
80
  current_group.parent << Group.new(:all, current_group.parent)
82
81
  current_group = current_group.parent.last
83
- when *@delimiter_chars
84
- current_group << part.to_sym
85
82
  else
86
83
  current_group << part
87
84
  end
@@ -90,11 +87,13 @@ class Usher
90
87
  paths.each do |path|
91
88
  path.each_with_index do |part, index|
92
89
  if part.is_a?(Usher::Route::Variable)
90
+ part.default_value = default_values[part.name] if default_values
91
+
93
92
  case part.type
94
93
  when :*
95
- part.look_ahead = path[index + 1, path.size].find{|p| !p.is_a?(Symbol) && !p.is_a?(Usher::Route::Variable)} || nil
94
+ part.look_ahead = path[index + 1, path.size].find{|p| !p.is_a?(Usher::Route::Variable) && !@delimiter_chars.include?(p[0])} || nil
96
95
  when :':'
97
- part.look_ahead = path[index + 1, path.size].find{|p| p.is_a?(Symbol)} || @delimiters.first.to_sym
96
+ part.look_ahead = path[index + 1, path.size].find{|p| @delimiter_chars.include?(p[0])} || @delimiters.first
98
97
  end
99
98
  end
100
99
  end
data/lib/usher.rb CHANGED
@@ -8,9 +8,10 @@ require 'usher/grapher'
8
8
  require 'usher/interface'
9
9
  require 'usher/splitter'
10
10
  require 'usher/exceptions'
11
+ require 'usher/generate'
11
12
 
12
13
  class Usher
13
- attr_reader :tree, :named_routes, :route_count, :routes, :splitter
14
+ attr_reader :tree, :named_routes, :route_count, :routes, :splitter, :delimiters
14
15
 
15
16
  SymbolArraySorter = proc {|a,b| a.hash <=> b.hash} #:nodoc:
16
17
 
@@ -75,7 +76,8 @@ class Usher
75
76
  # route = set.add_route('/test')
76
77
  # set.name(:test, route)
77
78
  def name(name, route)
78
- @named_routes[name] = route.primary_path
79
+ @named_routes[name] = route
80
+ route
79
81
  end
80
82
 
81
83
  # Creates a route from +path+ and +options+
@@ -142,6 +144,7 @@ class Usher
142
144
  def add_route(path, options = nil)
143
145
  conditions = options && options.delete(:conditions) || {}
144
146
  requirements = options && options.delete(:requirements) || {}
147
+ default_values = options && options.delete(:default_values) || {}
145
148
  if options
146
149
  options.delete_if do |k, v|
147
150
  if v.is_a?(Regexp) || v.is_a?(Proc)
@@ -150,7 +153,7 @@ class Usher
150
153
  end
151
154
  end
152
155
  end
153
- route = Route.new(path, self, {:conditions => conditions, :requirements => requirements})
156
+ route = Route.new(path, self, conditions, requirements, default_values)
154
157
  route.to(options) if options && !options.empty?
155
158
 
156
159
  @tree.add(route)
@@ -167,87 +170,16 @@ class Usher
167
170
  # route = set.add_route('/test')
168
171
  # set.recognize(Request.new('/test')).path.route == route => true
169
172
  def recognize(request, path = request.path)
170
- @tree.find(request, @splitter.url_split(path))
173
+ @tree.find(self, request, @splitter.url_split(path))
171
174
  end
172
175
 
173
176
  # Recognizes a set of +parameters+ and gets the closest matching Usher::Route::Path or +nil+ if no route exists.
174
177
  #
175
178
  # set = Usher.new
176
179
  # route = set.add_route('/:controller/:action')
177
- # set.route_for_options({:controller => 'test', :action => 'action'}) == path.route => true
178
- def route_for_options(options)
180
+ # set.path_for_options({:controller => 'test', :action => 'action'}) == path.route => true
181
+ def path_for_options(options)
179
182
  @grapher.find_matching_path(options)
180
183
  end
181
184
 
182
- # Generates a completed URL based on a +route+ or set of optional +params+
183
- #
184
- # set = Usher.new
185
- # route = set.add_named_route(:test_route, '/:controller/:action')
186
- # set.generate_url(nil, {:controller => 'c', :action => 'a'}) == '/c/a' => true
187
- # set.generate_url(:test_route, {:controller => 'c', :action => 'a'}) == '/c/a' => true
188
- # set.generate_url(route.primary_path, {:controller => 'c', :action => 'a'}) == '/c/a' => true
189
- def generate_url(route, params = nil, options = nil)
190
- check_variables = options && options.key?(:check_variables) ? options.delete(:check_variables) : false
191
- delimiter = options && options.key?(:delimiter) ? options.delete(:delimiter) : @delimiters.first
192
- extra_params = options && options.key?(:extra_params) ? options.delete(:extra_params) : {}
193
-
194
- path = case route
195
- when Symbol
196
- @named_routes[route]
197
- when nil
198
- route_for_options(params)
199
- when Route
200
- route.paths.first
201
- else
202
- route
203
- end
204
- raise UnrecognizedException.new unless path
205
- params_hash = extra_params
206
- param_list = case params
207
- when Hash
208
- params_hash.merge!(params)
209
- path.dynamic_parts.collect{|k| params_hash.delete(k.name) {|el| raise MissingParameterException.new(k.name)} }
210
- when Array
211
- path.dynamic_parts.size == params.size ? params : raise(MissingParameterException.new("got #{params.size} arguments, expected #{path.dynamic_parts.size}"))
212
- when nil
213
- nil
214
- else
215
- Array(params)
216
- end
217
-
218
- generated_path = ''
219
-
220
- path.parts.each do |p|
221
- case p
222
- when Route::Variable
223
- case p.type
224
- when :*
225
- param_list.first.each {|dp| p.valid!(dp.to_s) } if check_variables
226
- generated_path << param_list.shift.collect{|dp| URI.escape(dp.to_s)} * delimiter
227
- else
228
- p.valid!(param_list.first.to_s) if check_variables
229
- if dp = param_list.shift
230
- generated_path << URI.escape(dp.to_s)
231
- end
232
- end
233
- else
234
- generated_path << p.to_s
235
- end
236
- end
237
-
238
- unless params_hash.empty?
239
- has_query = generated_path[??]
240
- params_hash.each do |k,v|
241
- case v
242
- when Array
243
- v.each do |v_part|
244
- generated_path << (has_query ? '&' : has_query = true && '?') << CGI.escape("#{k.to_s}[]") << '=' << CGI.escape(v_part.to_s)
245
- end
246
- else
247
- generated_path << (has_query ? '&' : has_query = true && '?') << CGI.escape(k.to_s) << '=' << CGI.escape(v.to_s)
248
- end
249
- end
250
- end
251
- generated_path
252
- end
253
185
  end
data/rails/init.rb CHANGED
@@ -1,4 +1,8 @@
1
- class Usher::Interface::Rails2Interface::Mapper
2
- include ActionController::Resources
1
+ if Rails::VERSION::MAJOR == 2 && Rails::VERSION::MINOR == 3
2
+ ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails2_3)"
3
+ elsif Rails::VERSION::MAJOR == 2 && Rails::VERSION::MINOR >= 2
4
+ class Usher::Interface::Rails2_2Interface::Mapper
5
+ include ActionController::Resources
6
+ end
7
+ ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails2_2)"
3
8
  end
4
- ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails2);"
@@ -1,107 +1,136 @@
1
1
  require 'lib/usher'
2
2
 
3
- route_set = Usher.new
4
3
 
5
4
  describe "Usher URL generation" do
6
5
 
7
6
  before(:each) do
8
- route_set.reset!
7
+ @route_set = Usher.new
8
+ @route_set.reset!
9
+ @url_generator = Usher::Generators::URL.new(@route_set)
9
10
  end
10
11
 
11
12
  it "should generate a simple URL" do
12
- route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'action')
13
- route_set.generate_url(:sample, {}).should == '/sample'
13
+ @route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'action')
14
+ @url_generator.generate(:sample, {}).should == '/sample'
14
15
  end
15
16
 
16
17
  it "should generate a simple URL with a single variable" do
17
- route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
18
- route_set.generate_url(:sample, {:action => 'action'}).should == '/sample/action'
18
+ @route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
19
+ @url_generator.generate(:sample, {:action => 'action'}).should == '/sample/action'
19
20
  end
20
21
 
21
22
  it "should generate a simple URL with a single variable (and escape)" do
22
- route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
23
- route_set.generate_url(:sample, {:action => 'action time'}).should == '/sample/action%20time'
23
+ @route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
24
+ @url_generator.generate(:sample, {:action => 'action time'}).should == '/sample/action%20time'
24
25
  end
25
26
 
26
27
  it "should generate a simple URL with a single variable (thats not a string)" do
27
- route_set.add_named_route(:sample, '/sample/:action/:id', :controller => 'sample')
28
- route_set.generate_url(:sample, {:action => 'action', :id => 123}).should == '/sample/action/123'
28
+ @route_set.add_named_route(:sample, '/sample/:action/:id', :controller => 'sample')
29
+ @url_generator.generate(:sample, {:action => 'action', :id => 123}).should == '/sample/action/123'
29
30
  end
30
31
 
31
32
  it "should generate a simple URL with a glob variable" do
32
- route_set.add_named_route(:sample, '/sample/*action', :controller => 'sample')
33
- route_set.generate_url(:sample, {:action => ['foo', 'baz']}).should == '/sample/foo/baz'
33
+ @route_set.add_named_route(:sample, '/sample/*action', :controller => 'sample')
34
+ @url_generator.generate(:sample, {:action => ['foo', 'baz']}).should == '/sample/foo/baz'
34
35
  end
35
36
 
36
37
  it "should generate a mutliple vairable URL from a hash" do
37
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
38
- route_set.generate_url(:sample, {:first => 'zoo', :second => 'maz'}).should == '/sample/zoo/maz'
38
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
39
+ @url_generator.generate(:sample, {:first => 'zoo', :second => 'maz'}).should == '/sample/zoo/maz'
39
40
  end
40
41
 
41
42
  it "should generate a mutliple vairable URL from an array" do
42
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
43
- route_set.generate_url(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
43
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
44
+ @url_generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
44
45
  end
45
46
 
46
47
  it "should generate append extra hash variables to the end" do
47
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
48
- route_set.generate_url(:sample, {:first => 'maz', :second => 'zoo', :third => 'zanz'}).should == '/sample/maz/zoo?third=zanz'
48
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
49
+ @url_generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => 'zanz'}).should == '/sample/maz/zoo?third=zanz'
49
50
  end
50
51
 
51
52
  it "should generate append extra hash variables to the end (when the first parts are an array)" do
52
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
53
- ['/sample/maz/zoo?four=jane&third=zanz', '/sample/maz/zoo?third=zanz&four=jane'].include?(route_set.generate_url(:sample, ['maz', 'zoo'], :extra_params => {:third => 'zanz', :four => 'jane'})).should == true
53
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
54
+ ['/sample/maz/zoo?four=jane&third=zanz', '/sample/maz/zoo?third=zanz&four=jane'].include?(@url_generator.generate(:sample, ['maz', 'zoo', {:third => 'zanz', :four => 'jane'}])).should == true
54
55
  end
55
56
 
56
57
  it "should generate append extra hash variables to the end using [] syntax if its an array" do
57
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
58
- route_set.generate_url(:sample, {:first => 'maz', :second => 'zoo', :third => ['zanz', 'susie']}).should == '/sample/maz/zoo?third%5B%5D=zanz&third%5B%5D=susie'
58
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
59
+ @url_generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => ['zanz', 'susie']}).should == '/sample/maz/zoo?third%5B%5D=zanz&third%5B%5D=susie'
59
60
  end
60
61
 
61
62
  it "should generate a mutliple vairable URL from an array" do
62
- route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
63
- route_set.generate_url(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
63
+ @route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
64
+ @url_generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
64
65
  end
65
66
 
66
67
  it "should generate a simple URL with a format" do
67
- route_set.add_named_route(:sample, '/sample/:action.:format', :controller => 'sample')
68
- route_set.generate_url(:sample, {:action => 'action', :format => 'html'}).should == '/sample/action.html'
68
+ @route_set.add_named_route(:sample, '/sample/:action.:format', :controller => 'sample')
69
+ @url_generator.generate(:sample, {:action => 'action', :format => 'html'}).should == '/sample/action.html'
69
70
  end
70
71
 
71
72
  it "should generate from parameters" do
72
- caf = route_set.add_route('/:controller/:action.:format')
73
- ca = route_set.add_route('/:controller/:action')
74
- route_set.generate_url(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
75
- route_set.generate_url(nil, {:controller => 'controller', :action => 'action', :format => 'html'}).should == '/controller/action.html'
73
+ caf = @route_set.add_route('/:controller/:action.:format')
74
+ ca = @route_set.add_route('/:controller/:action')
75
+ @url_generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
76
+ @url_generator.generate(nil, {:controller => 'controller', :action => 'action', :format => 'html'}).should == '/controller/action.html'
76
77
  end
77
78
 
78
79
  it "should use the first route when generating a URL from two ambiguous routes" do
79
- route_set.add_route('/:controller/:action')
80
- route_set.add_route('/:action/:controller')
81
- route_set.generate_url(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
80
+ @route_set.add_route('/:controller/:action')
81
+ @route_set.add_route('/:action/:controller')
82
+ @url_generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
82
83
  end
83
84
 
84
85
  it "should accept an array of parameters" do
85
- caf = route_set.add_named_route(:name, '/:controller/:action.:format')
86
- route_set.generate_url(:name, ['controller', 'action', 'html']).should == '/controller/action.html'
86
+ caf = @route_set.add_named_route(:name, '/:controller/:action.:format')
87
+ @url_generator.generate(:name, ['controller', 'action', 'html']).should == '/controller/action.html'
87
88
  end
88
89
 
89
90
  it "should require all the parameters (hash) to generate a route" do
90
- proc {route_set.generate_url(route_set.add_route('/:controller/:action').primary_path, {:controller => 'controller'})}.should raise_error Usher::MissingParameterException
91
+ proc {@url_generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller'})}.should raise_error Usher::MissingParameterException
91
92
  end
92
93
 
93
94
  it "should generate from a route" do
94
- route_set.generate_url(route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
95
+ @url_generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
95
96
  end
96
97
 
97
98
  it "should require all the parameters (array) to generate a route" do
98
- route_set.add_named_route(:name, '/:controller/:action.:format')
99
- proc {route_set.generate_url(:name, ['controller', 'action'])}.should raise_error Usher::MissingParameterException
99
+ @route_set.add_named_route(:name, '/:controller/:action.:format')
100
+ proc {@url_generator.generate(:name, ['controller', 'action'])}.should raise_error Usher::MissingParameterException
100
101
  end
101
102
 
102
103
  it "should generate a route when only one parameter is given" do
103
- route_set.add_named_route(:name, '/:controller')
104
- route_set.generate_url(:name, 'controller').should == '/controller'
104
+ @route_set.add_named_route(:name, '/:controller')
105
+ @url_generator.generate(:name, 'controller').should == '/controller'
105
106
  end
106
107
 
108
+ it "should generate the correct route from a route containing optional parts" do
109
+ @route_set.add_named_route(:name, '/:controller(/:action(/:id))')
110
+ @url_generator.generate(:name, {:controller => 'controller'}).should == '/controller'
111
+ @url_generator.generate(:name, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
112
+ @url_generator.generate(:name, {:controller => 'controller', :action => 'action', :id => 'id'}).should == '/controller/action/id'
113
+ end
114
+
115
+ it "should generate a route using defaults for everything but the first parameter" do
116
+ @route_set.add_named_route(:name, '/:one/:two/:three', {:default_values => {:one => 'one', :two => 'two', :three => 'three'}})
117
+ @url_generator.generate(:name, {:one => "1"}).should == '/1/two/three'
118
+ end
119
+
120
+ it "should generate a route using defaults for everything" do
121
+ @route_set.add_named_route(:name, '/:one/:two/:three', {:default_values => {:one => 'one', :two => 'two', :three => 'three'}})
122
+ @url_generator.generate(:name).should == '/one/two/three'
123
+ end
124
+
125
+ it "should generate a route using defaults and optionals using the last parameter" do
126
+ @route_set.add_named_route(:opts_with_defaults, '/:one(/:two(/:three))', {:default_values => {:one => '1', :two => '2', :three => '3'}})
127
+ @url_generator.generate(:opts_with_defaults, {:three => 'three'}).should == '/1/2/three'
128
+ end
129
+
130
+ it "should generate a route with optional segments given two nested optional parameters" do
131
+ @route_set.add_named_route(:optionals, '/:controller(/:action(/:id))(.:format)')
132
+ @url_generator.generate(:optionals, {:controller => "foo", :action => "bar"}).should == '/foo/bar'
133
+ end
134
+
135
+
107
136
  end