merb 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/README +138 -56
  2. data/Rakefile +23 -8
  3. data/app_generators/merb/templates/Rakefile +13 -0
  4. data/app_generators/merb/templates/app/helpers/global_helper.rb +1 -1
  5. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +12 -3
  6. data/app_generators/merb/templates/config/merb.yml +14 -1
  7. data/app_generators/merb/templates/spec/spec_helper.rb +6 -0
  8. data/app_generators/merb/templates/test/test_helper.rb +1 -0
  9. data/lib/merb.rb +27 -7
  10. data/lib/merb/abstract_controller.rb +76 -36
  11. data/lib/merb/caching/store/memcache.rb +20 -0
  12. data/lib/merb/constants.rb +2 -4
  13. data/lib/merb/controller.rb +44 -2
  14. data/lib/merb/core_ext/get_args.rb +23 -4
  15. data/lib/merb/core_ext/hash.rb +16 -11
  16. data/lib/merb/core_ext/inflections.rb +1 -1
  17. data/lib/merb/core_ext/kernel.rb +106 -26
  18. data/lib/merb/core_ext/numeric.rb +1 -1
  19. data/lib/merb/core_ext/string.rb +10 -13
  20. data/lib/merb/dispatcher.rb +2 -2
  21. data/lib/merb/exceptions.rb +3 -1
  22. data/lib/merb/logger.rb +15 -6
  23. data/lib/merb/mail_controller.rb +18 -2
  24. data/lib/merb/mailer.rb +1 -1
  25. data/lib/merb/mixins/controller.rb +64 -228
  26. data/lib/merb/mixins/erubis_capture.rb +1 -1
  27. data/lib/merb/mixins/general_controller.rb +258 -0
  28. data/lib/merb/mixins/render.rb +45 -24
  29. data/lib/merb/mixins/responder.rb +89 -18
  30. data/lib/merb/mixins/view_context.rb +32 -5
  31. data/lib/merb/mixins/web_controller.rb +8 -1
  32. data/lib/merb/mongrel_handler.rb +27 -17
  33. data/lib/merb/part_controller.rb +10 -0
  34. data/lib/merb/request.rb +34 -14
  35. data/lib/merb/router.rb +77 -45
  36. data/lib/merb/server.rb +116 -72
  37. data/lib/merb/session/cookie_store.rb +14 -22
  38. data/lib/merb/session/mem_cache_session.rb +2 -2
  39. data/lib/merb/session/memory_session.rb +12 -1
  40. data/lib/merb/template/erubis.rb +31 -0
  41. data/lib/merb/template/haml.rb +4 -14
  42. data/lib/merb/template/xml_builder.rb +1 -1
  43. data/lib/merb/test/helper.rb +90 -18
  44. data/lib/merb/test/rspec.rb +145 -74
  45. data/lib/merb/version.rb +11 -0
  46. data/lib/merb/view_context.rb +3 -6
  47. data/lib/patch +69 -0
  48. data/lib/tasks/merb.rake +1 -1
  49. data/spec/fixtures/config/environments/environment_config_test.yml +1 -0
  50. data/spec/fixtures/controllers/render_spec_controllers.rb +63 -4
  51. data/spec/fixtures/views/examples/template_throw_content_without_block.html.erb +3 -0
  52. data/spec/fixtures/views/partials/_erubis.html.erb +1 -1
  53. data/spec/merb/abstract_controller_spec.rb +1 -0
  54. data/spec/merb/controller_filters_spec.rb +68 -3
  55. data/spec/merb/controller_spec.rb +35 -68
  56. data/spec/merb/cookie_store_spec.rb +7 -20
  57. data/spec/merb/core_ext_spec.rb +35 -1
  58. data/spec/merb/dispatch_spec.rb +8 -2
  59. data/spec/merb/generator_spec.rb +12 -4
  60. data/spec/merb/mail_controller_spec.rb +33 -0
  61. data/spec/merb/part_controller_spec.rb +33 -1
  62. data/spec/merb/render_spec.rb +74 -0
  63. data/spec/merb/request_spec.rb +43 -0
  64. data/spec/merb/responder_spec.rb +1 -0
  65. data/spec/merb/router_spec.rb +118 -13
  66. data/spec/merb/server_spec.rb +19 -0
  67. data/spec/merb/view_context_spec.rb +31 -3
  68. data/spec/spec_helper.rb +8 -0
  69. data/spec/spec_helpers/url_shared_behaviour.rb +112 -0
  70. metadata +124 -87
@@ -30,14 +30,6 @@ end
30
30
 
31
31
  describe Merb::CookieStore do
32
32
 
33
- def cookies(*which)
34
- @cookies.values_at(*which)
35
- end
36
-
37
- def cookie_value(which)
38
- @cookies[which].first
39
- end
40
-
41
33
  before(:each) do
42
34
  @secret = 'Keep it secret; keep it safe.'
43
35
  @cookies = {
@@ -47,15 +39,13 @@ describe Merb::CookieStore do
47
39
  :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }]
48
40
  }
49
41
  end
50
-
51
-
52
-
42
+
53
43
  it "should raise argument error if missing secret key" do
54
44
  lambda { Merb::CookieStore.new(nil, nil) }.should raise_error(ArgumentError)
55
45
  end
56
46
 
57
47
  it "should restore and unmarshal good cookies" do
58
- cookies(:empty, :a_one, :typical).each do |value, expected|
48
+ @cookies.values_at(:empty, :a_one, :typical).each do |value, expected|
59
49
  session = Merb::CookieStore.new(value, @secret)
60
50
  session['lazy loads the data hash'].should be_nil
61
51
  session.data.should == expected
@@ -68,18 +58,15 @@ describe Merb::CookieStore do
68
58
  end
69
59
 
70
60
  it "should raise when data overflows" do
71
- session = Merb::CookieStore.new(cookie_value(:empty), @secret)
61
+ session = Merb::CookieStore.new(@cookies[:empty].first, @secret)
72
62
  session['overflow'] = 'bye!' * 1024
73
63
  lambda { session.read_cookie }.should
74
64
  raise_error(Merb::CookieStore::CookieOverflow)
75
65
  end
76
-
77
- it "should close and marshal cookie data" do
78
- session = Merb::CookieStore.new(cookie_value(:typical), @secret)
79
- session.modified?.should == false
80
- session['flash'] = {}
81
- session.modified?.should == true
82
- session.read_cookie.should == cookie_value(:flashed)
66
+
67
+ it "should delete entries in the session" do
68
+ session = Merb::CookieStore.new(@cookies[:a_one].first, @secret)
69
+ session.delete('a').should == 1
83
70
  end
84
71
 
85
72
  end
@@ -401,9 +401,14 @@ describe "A String" do
401
401
  end.should raise_error(String::InvalidPathConversion)
402
402
  end.should_not raise_error(Timeout::Error)
403
403
  end
404
+
405
+ it "should remove any indentation and add +indentation+ number of spaces" do
406
+ "foo\n bar\n".indent(3).should == " foo\n bar\n"
407
+ " foo\n bar\n".indent(3).should == " foo\n bar\n"
408
+ end
404
409
  end
405
410
 
406
- describe "extracting options form argruments" do
411
+ describe "extracting options from arguments" do
407
412
 
408
413
  def the_method(*args)
409
414
  [extract_options_from_args!(args),args]
@@ -428,3 +433,32 @@ describe "extracting options form argruments" do
428
433
  end
429
434
 
430
435
  end
436
+
437
+ describe Inflector do
438
+ it "should transform words from singular to plural" do
439
+ "post".pluralize.should == "posts"
440
+ "octopus".pluralize.should =="octopi"
441
+ "the blue mailman".pluralize.should == "the blue mailmen"
442
+ "CamelOctopus".pluralize.should == "CamelOctopi"
443
+ end
444
+ it "should transform words from plural to singular" do
445
+ "posts".singularize.should == "post"
446
+ "octopi".singularize.should == "octopus"
447
+ "the blue mailmen".singularize.should == "the blue mailman"
448
+ "CamelOctopi".singularize.should == "CamelOctopus"
449
+ end
450
+ it "should transform class names to table names" do
451
+ "RawScaledScorer".tableize.should == "raw_scaled_scorers"
452
+ "egg_and_ham".tableize.should == "egg_and_hams"
453
+ "fancyCategory".tableize.should == "fancy_categories"
454
+ end
455
+ it "should tranform table names to class names" do
456
+ "egg_and_hams".classify.should == "EggAndHam"
457
+ "post".classify.should == "Post"
458
+ end
459
+ it "should create a foreign key name from a class name" do
460
+ "Message".foreign_key.should == "message_id"
461
+ "Message".foreign_key(false).should == "messageid"
462
+ "Admin::Post".foreign_key.should == "post_id"
463
+ end
464
+ end
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + '/../fixtures/controllers/dispatch_spec_control
4
4
  $TESTING = true
5
5
 
6
6
  describe Merb::Dispatcher do
7
-
7
+
8
8
  before(:all) do
9
9
  Merb::Server.config[:allow_reloading] = false
10
10
  Merb::Router.prepare do |r|
@@ -24,9 +24,15 @@ describe Merb::Dispatcher do
24
24
  end
25
25
  r.default_routes
26
26
  end
27
- puts Merb::Router.named_routes[:new_comment].generate(:post_id => 1)
28
27
  end
29
28
 
29
+ it "should not overwrite url params with query string params" do
30
+ controller, action = request(:get, '/foo/bar/42?id=24')
31
+ controller.class.should == Foo
32
+ action.should == "bar"
33
+ controller.params[:id].should == '42'
34
+ end
35
+
30
36
  it "should not allow private and protected methods to be called" do
31
37
  controller, action = request(:get, '/foo/call_filters')
32
38
  controller.status.should == Merb::ControllerExceptions::ActionNotFound::STATUS
@@ -25,7 +25,9 @@ describe "an app generator" do
25
25
  end
26
26
 
27
27
  it "should create directory structure" do
28
- @generator.command(:create).invoke!
28
+ silence_generator do
29
+ @generator.command(:create).invoke!
30
+ end
29
31
  %w{
30
32
  app
31
33
  app/controllers
@@ -51,7 +53,9 @@ describe "an app generator" do
51
53
  end
52
54
 
53
55
  it "should create files from templates" do
54
- @generator.command(:create).invoke!
56
+ silence_generator do
57
+ @generator.command(:create).invoke!
58
+ end
55
59
  %w{
56
60
  app/controllers/application.rb
57
61
  app/helpers/global_helper.rb
@@ -73,7 +77,9 @@ describe "an app generator" do
73
77
  end
74
78
 
75
79
  it "should create files from rubigen dependency" do
76
- @generator.command(:create).invoke!
80
+ silence_generator do
81
+ @generator.command(:create).invoke!
82
+ end
77
83
  %w{
78
84
  script/generate
79
85
  script/destroy
@@ -81,7 +87,9 @@ describe "an app generator" do
81
87
  end
82
88
 
83
89
  it "should make script files executable" do
84
- @generator.command(:create).invoke!
90
+ silence_generator do
91
+ @generator.command(:create).invoke!
92
+ end
85
93
 
86
94
  %w{
87
95
  script/stop_merb
@@ -6,6 +6,7 @@ module Merb
6
6
  end
7
7
  end
8
8
  Merb::Server.load_controller_template_path_cache
9
+ Merb::Server.load_erubis_inline_helpers
9
10
 
10
11
  class Merb::Mailer
11
12
  self.delivery_method = :test_send
@@ -141,4 +142,36 @@ describe "A Merb Mail controller" do
141
142
  deliver :tenth
142
143
  end
143
144
 
145
+ end
146
+
147
+ describe "Merb::MailController with url generation" do
148
+
149
+ it_should_behave_like "class with general url generation"
150
+ it_should_behave_like "non routeable controller with url mixin"
151
+
152
+ def new_url_controller(route, params = {:action => 'show', :controller => 'Test'})
153
+ request = OpenStruct.new
154
+ request.route = route
155
+ request.params = params
156
+ response = OpenStruct.new
157
+ response.read = ""
158
+
159
+ @controller = Merb::Controller.build(request, response)
160
+ TestMailController.new(params, @controller)
161
+ end
162
+
163
+ it "should raise an error if no controller is specified and the base controller is not set" do
164
+ c = new_url_controller(@default_route, {})
165
+ lambda do
166
+ the_url = c.url(:action => "bar")
167
+ end.should raise_error
168
+ end
169
+
170
+ it "should use the base controller when it is set to generate a url when no :controller option is specified" do
171
+ c = new_url_controller(@defualt_route, :controller => "foo")
172
+ lambda do
173
+ the_url = c.url(:action => "bar")
174
+ the_url.should == "/foo/bar"
175
+ end.should_not raise_error
176
+ end
144
177
  end
@@ -89,4 +89,36 @@ describe "A Merb PartController" do
89
89
  controller.body.should match(/part_js_format/m)
90
90
  end
91
91
 
92
- end
92
+ end
93
+
94
+ describe "A Merb Part Controller with urls" do
95
+
96
+ it_should_behave_like "class with general url generation"
97
+ it_should_behave_like "non routeable controller with url mixin"
98
+
99
+ def new_url_controller(route, params = {:action => 'show', :controller => 'Test'})
100
+ request = OpenStruct.new
101
+ request.route = route
102
+ request.params = params
103
+ response = OpenStruct.new
104
+ response.read = ""
105
+
106
+ @controller = Merb::Controller.build(request, response)
107
+ TodoPart.new(@controller)
108
+ end
109
+
110
+ it "should use the web_controllers type if no controller is specified" do
111
+ c = new_url_controller(@default_route, :controller => "my_controller")
112
+ the_url = c.url(:action => "bar")
113
+ the_url.should == "/my_controller/bar"
114
+ end
115
+
116
+ it "should raise an error if the web_controller's params[:controller] is not set" do
117
+ c = new_url_controller(@default_route, {})
118
+ lambda do
119
+ the_url = c.url(:action => "bar")
120
+ the_url.should == "/my_controller/bar"
121
+ end.should raise_error
122
+ end
123
+
124
+ end
@@ -21,6 +21,12 @@ describe "rendering engines except XMLBuilder", :shared => true do
21
21
  content.clean.should == "Locals!"
22
22
  end
23
23
 
24
+ it "should render a partial with nil locals" do
25
+ c = new_controller
26
+ content = c.partial "partials/#{@engine}", :yo => nil
27
+ content.clean.should == "No Locals!"
28
+ end
29
+
24
30
  it "should render a partial using the :partial method" do
25
31
  c = new_controller
26
32
  content = c.partial("partials/#{@engine}")
@@ -108,6 +114,14 @@ describe "rendering engines except XMLBuilder", :shared => true do
108
114
  content.should match( /Start Tester Block\s*In Tester Block\s*Finish Tester Block/m)
109
115
  end
110
116
 
117
+ it "should bind the concat to independent render buffers" do
118
+ c = new_controller
119
+ content = c.render :template => "template_views/interface_concat_#{@engine}", :layout => :none
120
+ content.should match( /Start Tester Block\s*In Tester Block\s*Finish Tester Block/m)
121
+ content = c.render :template => "template_views/interface_concat_#{@engine}", :layout => :none
122
+ content.should match( /Start Tester Block\s*In Tester Block\s*Finish Tester Block/m)
123
+ end
124
+
111
125
  it "should implement a capture( &block ) method" do
112
126
  c = new_controller
113
127
  content = c.render :template => "template_views/interface_capture_#{@engine}", :layout => :none
@@ -368,6 +382,66 @@ describe "Merb rendering with an object calls to_json or to_xml on the object" d
368
382
 
369
383
  end
370
384
 
385
+ describe "Merb rendering with an object calls to_json or to_xml on the object (using specified arguments)" do
386
+
387
+ it "render @foo should call @foo.to_json when json is requested (using default options)" do
388
+ c = new_spec_controller(:format => 'json', :controller => 'RenderObjectWithArgumentsController')
389
+ c.provided_format_arguments_for(:json).should == ["foo", "bar"]
390
+ c.dispatch(:render_standard)
391
+ c.body.should == "['foo','bar']"
392
+ end
393
+
394
+ it "render @foo should call @foo.to_json when json is requested (using action options)" do
395
+ c = new_spec_controller(:format => 'json', :controller => 'RenderObjectWithArgumentsController')
396
+ c.dispatch(:render_specific)
397
+ c.body.should == "['foo','bar','baz']"
398
+ end
399
+
400
+ it "render @foo should call @foo.to_xml when xml is requested (using default options)" do
401
+ c = new_spec_controller(:format => 'xml', :controller => 'RenderObjectWithArgumentsController')
402
+ c.provided_format_arguments_for(:xml).should == [{:foo=>"bar"}]
403
+ c.dispatch(:render_standard)
404
+ c.body.should == "<foo>bar</foo>"
405
+ end
406
+
407
+ it "render @foo should call @foo.to_xml when xml is requested (using action options)" do
408
+ c = new_spec_controller(:format => 'xml', :controller => 'RenderObjectWithArgumentsController')
409
+ c.dispatch(:render_specific)
410
+ c.body.should == "<biz>baz</biz><foo>bar</foo>"
411
+ end
412
+
413
+ end
414
+
415
+ describe "Merb rendering with an object and using a block/lambda for provides" do
416
+
417
+ it "render @foo should use the default block when xml is requested" do
418
+ c = new_spec_controller(:format => 'xml', :controller => 'RenderObjectWithBlockController')
419
+ c.provided_format_arguments_for(:xml).should be_kind_of(Proc)
420
+ c.dispatch(:render_standard)
421
+ c.body.should == "<foo>RenderObjectWithBlockController</foo>"
422
+ end
423
+
424
+ it "render @foo should use the default block when json is requested" do
425
+ c = new_spec_controller(:format => 'json', :controller => 'RenderObjectWithBlockController')
426
+ c.provided_format_arguments_for(:json).should be_kind_of(Proc)
427
+ c.dispatch(:render_standard)
428
+ c.body.should == "['foo']"
429
+ end
430
+
431
+ it "render @foo should use the specific proc when xml is requested" do
432
+ c = new_spec_controller(:format => 'xml', :controller => 'RenderObjectWithBlockController')
433
+ c.dispatch(:render_specific)
434
+ c.body.should == "<foo>RENDEROBJECTWITHBLOCKCONTROLLER</foo>"
435
+ end
436
+
437
+ it "render @foo should use the specific proc when json is requested" do
438
+ c = new_spec_controller(:format => 'json', :controller => 'RenderObjectWithBlockController')
439
+ c.dispatch(:render_specific)
440
+ c.body.should == "['RenderObjectWithBlockController','foo','bar','baz']"
441
+ end
442
+
443
+ end
444
+
371
445
  def new_spec_controller(options={})
372
446
  params = {:controller => 'ExtensionTemplateController'}
373
447
  params.update(:format => options.delete(:format)) if options[:format]
@@ -132,6 +132,24 @@ describe Merb::Request do
132
132
  Merb::Request::parse_json_params = true
133
133
  end
134
134
 
135
+ it "should parse a JSON body into params when charset provided" do
136
+ @in.post_body = "{\"title\":\"hello there\",\"body\":\"some text\"}"
137
+ @in['REQUEST_METHOD'] = 'POST'
138
+ @in['CONTENT_TYPE'] = "text/x-json; charset=utf-8"
139
+ request = Merb::Request.new(@in)
140
+ request.params[:title].should == "hello there"
141
+ request.params[:body].should == "some text"
142
+ end
143
+
144
+ it "should parse an XML body into params when charset provided" do
145
+ @in.post_body = "<root><title>hello there</title><body>some text</body></root>"
146
+ @in['REQUEST_METHOD'] = 'POST'
147
+ @in['CONTENT_TYPE'] = "text/xml; charset=utf-8"
148
+ request = Merb::Request.new(@in)
149
+ request.params[:root][:title].should == "hello there"
150
+ request.params[:root][:body].should == "some text"
151
+ end
152
+
135
153
  it "should handle hash-style form fields in multipart/form-data" do
136
154
  m = Merb::Test::Multipart::Post.new :foo => 'bario',
137
155
  'files[foo][file]' => File.open(FIXTURES / 'foo.rb'),
@@ -240,4 +258,29 @@ describe Merb::Request do
240
258
  request = Merb::Request.new(@in)
241
259
  request.accept.should == "*/*"
242
260
  end
261
+
262
+ it "should be able to tell you the HTTP method for POST requests without an error" do
263
+ @in['REQUEST_METHOD'] = 'POST'
264
+ request = Merb::Request.new(@in)
265
+ lambda {request.method}.should_not raise_error
266
+ request.method.should == :post
267
+ end
268
+
269
+ it "should be able to tell you the HTTP method for GET requests without an error" do
270
+ @in['REQUEST_METHOD'] = 'GET'
271
+ request = Merb::Request.new(@in)
272
+ lambda {request.method}.should_not raise_error
273
+ request.method.should == :get
274
+ end
275
+
276
+ it "multipart_params should return an empty hash if the request is not multipart" do
277
+ request = Merb::Request.new(@in)
278
+ request.send(:multipart_params).should == {}
279
+ end
280
+
281
+ it "should add namespace to controller name" do
282
+ request = Merb::Request.new(@in)
283
+ request.stubs(:route_params).returns({:controller => 'bar', :namespace => 'foo'})
284
+ request.controller_name.should == "foo/bar"
285
+ end
243
286
  end
@@ -244,6 +244,7 @@ end
244
244
 
245
245
  Merb::Server.load_action_arguments
246
246
  Merb::Server.load_controller_template_path_cache
247
+ Merb::Server.load_erubis_inline_helpers
247
248
 
248
249
  describe "A Merb Responder's Content Negotiation" do
249
250
 
@@ -72,6 +72,15 @@ describe Merb::Router do
72
72
  Merb::Router.routes[0].should == r1
73
73
  Merb::Router.routes[1].should == r2
74
74
  end
75
+
76
+ it "should have a spec helper to match routes" do
77
+ Merb::Router.prepare{ |r| r.default_routes }
78
+ with_route("/pages/show/1", "GET") do |params|
79
+ params[:controller].should == "pages"
80
+ params[:action].should == "show"
81
+ params[:id].should == "1"
82
+ end
83
+ end
75
84
 
76
85
  # it "should be fast" do
77
86
  # Merb::Router.prepare do |r|
@@ -177,13 +186,22 @@ describe Merb::Router, "when doing route matching with a big set of example rout
177
186
  r.match("/::/users/::").
178
187
  to(:controller => "users", :action => "[2]", :id => "[1]")
179
188
 
189
+ # Namespace can be used to specify the module
190
+ r.match('/bar').to(:controller => 'bar', :namespace => 'foo')
191
+
192
+ # Namespace can be used to provide path prefix
193
+ r.match('/admin').to(:namespace => 'admin') do |foo|
194
+ foo.match('/foo').to(:controller => 'foo')
195
+ end
196
+ r.match('/foo').to(:controller => 'foo')
197
+
180
198
  # Putting it all together, and adding the requirement that we use an "admin" prefix on the
181
- # domain (e.g. admin.mysite.com), do some interesting stuff:
182
- r.match(:domain => /^admin\b/) do |admin|
199
+ # host (e.g. admin.mysite.com), do some interesting stuff:
200
+ r.match(:host => /^admin\b/).to(:namespace => 'admin') do |admin|
183
201
  admin.match(%r[/([A-Z]\w+)\+([A-Z]\w+)/::]).
184
- to(:controller => "admin/users", :action => ":path[3]",
202
+ to(:controller => "users", :action => ":path[3]",
185
203
  :first_name => ":path[1]", :last_name => ":path[2]")
186
- end.to(:controller => "admin/users", :action => "default")
204
+ end.to(:controller => "users", :action => "default")
187
205
  # Note that the last line above sends all traffic in the "admin" subdomain to the
188
206
  # Admin::Users#default action if no other route is matched.
189
207
 
@@ -313,25 +331,51 @@ describe Merb::Router, "when doing route matching with a big set of example rout
313
331
  should_only_have_keys(route, :controller, :action, :id)
314
332
  end
315
333
 
334
+ it "should use namespace" do
335
+ index, route = Merb::Router.match(SimpleRequest.new(:path => '/bar', :method => :get), {})
336
+ route[:namespace].should == 'foo'
337
+ route[:controller].should == 'bar'
338
+ route[:action].should == 'index'
339
+ should_only_have_keys(route, :namespace, :controller, :action)
340
+ end
341
+
342
+ it "should have namespace 'admin' if path is '/admin/foo'" do
343
+ index, route = Merb::Router.match(SimpleRequest.new(:path => '/admin/foo', :method => :get), {})
344
+ route[:namespace].should == 'admin'
345
+ route[:controller].should == 'foo'
346
+ route[:action].should == 'index'
347
+ should_only_have_keys(route, :namespace, :controller, :action)
348
+ end
349
+
350
+ it "should not have namespace if path is just '/foo'" do
351
+ index, route = Merb::Router.match(SimpleRequest.new(:path => '/foo', :method => :get), {})
352
+ route[:controller].should == 'foo'
353
+ route[:action].should == 'index'
354
+ should_only_have_keys(route, :controller, :action)
355
+ end
356
+
316
357
  it "should send all admin.* domains to the 'admin/users' controller, and 'default' action" do
317
- index, route = Merb::Router.match(SimpleRequest.new(:domain => "admin.mysite.com", :path => '/welcome', :protocol => "https://"), {})
318
- route[:controller].should == "admin/users"
358
+ index, route = Merb::Router.match(SimpleRequest.new(:host => "admin.mysite.com", :path => '/welcome', :protocol => "https://"), {})
359
+ route[:namespace].should == "admin"
360
+ route[:controller].should == "users"
319
361
  route[:action].should == "default"
320
- should_only_have_keys(route, :controller, :action)
362
+ should_only_have_keys(route, :namespace, :controller, :action)
321
363
 
322
- index, route = Merb::Router.match(SimpleRequest.new(:domain => "admin.another-site.com", :path => '/go/somewhere/else', :protocol => "https://"), {})
323
- route[:controller].should == "admin/users"
364
+ index, route = Merb::Router.match(SimpleRequest.new(:host => "admin.another-site.com", :path => '/go/somewhere/else', :protocol => "https://"), {})
365
+ route[:namespace].should == "admin"
366
+ route[:controller].should == "users"
324
367
  route[:action].should == "default"
325
- should_only_have_keys(route, :controller, :action)
368
+ should_only_have_keys(route, :namespace, :controller, :action)
326
369
  end
327
370
 
328
371
  it "should decipher the first-name / last-name pairs on an admin.* domain" do
329
- index, route = Merb::Router.match(SimpleRequest.new(:domain => "admin.mysite.com", :path => '/Duane+Johnson/edit', :protocol => "https://"), {})
330
- route[:controller].should == "admin/users"
372
+ index, route = Merb::Router.match(SimpleRequest.new(:host => "admin.mysite.com", :path => '/Duane+Johnson/edit', :protocol => "https://"), {})
373
+ route[:namespace].should == "admin"
374
+ route[:controller].should == "users"
331
375
  route[:action].should == "edit"
332
376
  route[:first_name].should == "Duane"
333
377
  route[:last_name].should == "Johnson"
334
- should_only_have_keys(route, :controller, :action, :first_name, :last_name)
378
+ should_only_have_keys(route, :namespace, :controller, :action, :first_name, :last_name)
335
379
  end
336
380
 
337
381
  it "should defer to the Ajax controller for xhr requests" do
@@ -723,4 +767,65 @@ describe Merb::Router::Behavior, "class methods" do
723
767
  @b.array_to_code(["one string"]).should == "\"one string\""
724
768
  @b.array_to_code(["string", :var, :var2, "other"]).should == "\"string\" + var + var2 + \"other\""
725
769
  end
770
+ end
771
+
772
+ describe "Merb::Route", "rendered as a string" do
773
+ before(:all) do
774
+ Merb::Router.prepare do |r|
775
+ r.default_routes
776
+ end
777
+ @routes = Merb::Router.routes
778
+ end
779
+
780
+ it "should show the default route" do
781
+ @routes.last.to_s.should == "/:controller(/:action(/:id)?)?(\\.:format)?"
782
+ end
783
+ end
784
+
785
+ describe Merb::Router, "with resources using namespace 'admin'" do
786
+ before(:each) do
787
+ Merb::Router.prepare do |r|
788
+ #Declare one in the nested style
789
+ r.match(:host => /^.*$/).to(:namespace => 'admin') do |admin|
790
+ admin.resources :oranges
791
+ end
792
+ #Declare one in the non-nested style
793
+ r.resources :ape, :namespace => 'admin'
794
+ #Declare resources without a namespace to make sure it's not overridden
795
+ r.resources :oranges
796
+ r.resource :ape
797
+ end
798
+ end
799
+
800
+ it "should generate admin_oranges path" do
801
+ Merb::Router.generate(:admin_oranges).should == '/oranges'
802
+ end
803
+
804
+ it "should generate admin_orange path" do
805
+ Merb::Router.generate(:admin_orange, {:id => 1}).should == '/oranges/1'
806
+ b = Blogposts.new
807
+ Merb::Router.generate(:admin_orange, b).should == '/oranges/42'
808
+ Merb::Router.generate(:admin_orange, :id => b).should == '/oranges/42'
809
+ end
810
+
811
+ it "should generate new_admin_orange path" do
812
+ Merb::Router.generate(:new_admin_orange).should == '/oranges/new'
813
+ end
814
+
815
+ it "should generate edit_admin_orange path" do
816
+ Merb::Router.generate(:edit_admin_orange, {:id => 1}).should == '/oranges/1/edit'
817
+ end
818
+
819
+ it "should generate admin_ape path" do
820
+ Merb::Router.generate(:admin_ape).should == '/ape'
821
+ end
822
+
823
+ it "should generate new_admin_ape path" do
824
+ Merb::Router.generate(:new_admin_ape).should == '/ape/new'
825
+ end
826
+
827
+ it "should generate edit_admin_ape path" do
828
+ Merb::Router.generate(:edit_admin_ape).should == '/ape/edit'
829
+ end
830
+
726
831
  end