roda 2.0.0 → 2.1.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +26 -0
  3. data/README.rdoc +83 -22
  4. data/Rakefile +1 -1
  5. data/doc/release_notes/2.1.0.txt +124 -0
  6. data/lib/roda/plugins/assets.rb +17 -9
  7. data/lib/roda/plugins/class_level_routing.rb +5 -2
  8. data/lib/roda/plugins/delegate.rb +6 -3
  9. data/lib/roda/plugins/indifferent_params.rb +7 -0
  10. data/lib/roda/plugins/mailer.rb +18 -1
  11. data/lib/roda/plugins/multi_route.rb +2 -1
  12. data/lib/roda/plugins/path.rb +75 -6
  13. data/lib/roda/plugins/render.rb +33 -14
  14. data/lib/roda/plugins/static.rb +35 -0
  15. data/lib/roda/plugins/view_options.rb +161 -0
  16. data/lib/roda/plugins/view_subdirs.rb +6 -63
  17. data/lib/roda/version.rb +1 -1
  18. data/spec/composition_spec.rb +12 -0
  19. data/spec/matchers_spec.rb +34 -0
  20. data/spec/plugin/assets_spec.rb +112 -17
  21. data/spec/plugin/delete_empty_headers_spec.rb +12 -0
  22. data/spec/plugin/mailer_spec.rb +46 -3
  23. data/spec/plugin/module_include_spec.rb +17 -0
  24. data/spec/plugin/multi_route_spec.rb +10 -0
  25. data/spec/plugin/named_templates_spec.rb +6 -0
  26. data/spec/plugin/not_found_spec.rb +1 -1
  27. data/spec/plugin/path_spec.rb +76 -0
  28. data/spec/plugin/render_each_spec.rb +6 -0
  29. data/spec/plugin/render_spec.rb +40 -1
  30. data/spec/plugin/sinatra_helpers_spec.rb +5 -0
  31. data/spec/plugin/static_spec.rb +30 -0
  32. data/spec/plugin/view_options_spec.rb +117 -0
  33. data/spec/spec_helper.rb +5 -1
  34. data/spec/views/multiple-layout.erb +1 -0
  35. data/spec/views/multiple.erb +1 -0
  36. metadata +10 -4
  37. data/spec/plugin/static_path_info_spec.rb +0 -56
  38. data/spec/plugin/view_subdirs_spec.rb +0 -44
@@ -1,5 +1,10 @@
1
1
  require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
2
2
 
3
+ begin
4
+ require 'tilt/erb'
5
+ rescue LoadError
6
+ warn "tilt not installed, skipping named_templates plugin test"
7
+ else
3
8
  describe "named_templates plugin" do
4
9
  it "adds template method method for naming templates, and have render recognize it" do
5
10
  app(:bare) do
@@ -88,3 +93,4 @@ describe "named_templates plugin" do
88
93
  body('/bar').should == 'bar43-barfoo42-baz'
89
94
  end
90
95
  end
96
+ end
@@ -102,7 +102,7 @@ describe "not_found plugin" do
102
102
  end
103
103
 
104
104
  o = Object.new
105
- def o.join() '' end
105
+ def o.each; end
106
106
  route do |r|
107
107
  r.halt [404, {}, o]
108
108
  end
@@ -9,6 +9,15 @@ describe "path plugin" do
9
9
  end
10
10
  end
11
11
 
12
+ def path_script_name_app(*args, &block)
13
+ app(:bare) do
14
+ opts[:add_script_name] = true
15
+ plugin :path
16
+ path *args, &block
17
+ route{|r| send(r.path_info)}
18
+ end
19
+ end
20
+
12
21
  def path_block_app(b, *args, &block)
13
22
  path_app(*args, &block)
14
23
  app.route{|r| send(r.path_info, &b)}
@@ -58,6 +67,16 @@ describe "path plugin" do
58
67
  body("foo_path", 'SCRIPT_NAME'=>'/baz').should == "/baz/bar/foo"
59
68
  end
60
69
 
70
+ it "respects :add_script_name app option for automatically adding the script name" do
71
+ path_script_name_app(:foo){"/bar/foo"}
72
+ body("foo_path", 'SCRIPT_NAME'=>'/baz').should == "/baz/bar/foo"
73
+ end
74
+
75
+ it "supports :add_script_name=>false option for not automatically adding the script name" do
76
+ path_script_name_app(:foo, :add_script_name=>false){"/bar/foo"}
77
+ body("foo_path", 'SCRIPT_NAME'=>'/baz').should == "/bar/foo"
78
+ end
79
+
61
80
  it "supports path method accepting a block when using :add_script_name" do
62
81
  path_block_app(lambda{"c"}, :foo, :add_script_name=>true){|&block| "/bar/foo/#{block.call}"}
63
82
  body("foo_path", 'SCRIPT_NAME'=>'/baz').should == "/baz/bar/foo/c"
@@ -91,3 +110,60 @@ describe "path plugin" do
91
110
  body("foo_url", 'HTTP_HOST'=>'example.org', "rack.url_scheme"=>'http', 'SERVER_PORT'=>81).should == "http://example.org:81/bar/foo"
92
111
  end
93
112
  end
113
+
114
+ describe "path plugin" do
115
+ before do
116
+ app(:bare) do
117
+ plugin :path
118
+ route{|r| path(*env['path'])}
119
+ end
120
+
121
+
122
+ c = Class.new{attr_accessor :a}
123
+ app.path(c){|obj, *args| "/d/#{obj.a}/#{File.join(*args)}"}
124
+ @obj = c.new
125
+ @obj.a = 1
126
+ end
127
+
128
+ it "Roda#path respects classes and symbols registered via Roda.path" do
129
+ # Strings
130
+ body('path'=>'/foo/bar').should == '/foo/bar'
131
+
132
+ # Classes
133
+ body('path'=>@obj).should == '/d/1/'
134
+ body('path'=>[@obj, 'foo']).should == '/d/1/foo'
135
+ body('path'=>[@obj, 'foo', 'bar']).should == '/d/1/foo/bar'
136
+ end
137
+
138
+ it "Roda#path raises an error for an unrecognized class" do
139
+ # Strings
140
+ proc{body('path'=>:foo)}.should raise_error(Roda::RodaError)
141
+ end
142
+
143
+ it "Roda#path respects :add_script_name app option" do
144
+ app.opts[:add_script_name] = true
145
+
146
+ # Strings
147
+ body('path'=>'/foo/bar', 'SCRIPT_NAME'=>'/baz').should == '/baz/foo/bar'
148
+
149
+ # Classes
150
+ body('path'=>@obj, 'SCRIPT_NAME'=>'/baz').should == '/baz/d/1/'
151
+ body('path'=>[@obj, 'foo'], 'SCRIPT_NAME'=>'/baz').should == '/baz/d/1/foo'
152
+ body('path'=>[@obj, 'foo', 'bar'], 'SCRIPT_NAME'=>'/baz').should == '/baz/d/1/foo/bar'
153
+ end
154
+
155
+ it "Roda.path doesn't work with classes without blocks" do
156
+ proc{app.path(Class.new)}.should raise_error(Roda::RodaError)
157
+ end
158
+
159
+ it "Roda.path doesn't work with classes with paths or options" do
160
+ proc{app.path(Class.new, '/a'){}}.should raise_error(Roda::RodaError)
161
+ proc{app.path(Class.new, nil, :a=>1){}}.should raise_error(Roda::RodaError)
162
+ end
163
+
164
+ it "Roda.path doesn't work after freezing the app" do
165
+ app.freeze
166
+ proc{app.path(Class.new){|obj| ''}}.should raise_error
167
+ end
168
+ end
169
+
@@ -1,5 +1,10 @@
1
1
  require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
2
2
 
3
+ begin
4
+ require 'tilt/erb'
5
+ rescue LoadError
6
+ warn "tilt not installed, skipping render_each plugin test"
7
+ else
3
8
  describe "render_each plugin" do
4
9
  it "calls render with each argument, returning joined string with all results" do
5
10
  app(:bare) do
@@ -33,3 +38,4 @@ describe "render_each plugin" do
33
38
  body("/c").should == 'rbar41 rbar42 rbar43 '
34
39
  end
35
40
  end
41
+ end
@@ -107,6 +107,18 @@ describe "render plugin" do
107
107
  body.strip.should == "<title>Alternative Layout: Home</title>\n<h1>Home</h1>\n<p>Hello Agent Smith</p>"
108
108
  end
109
109
 
110
+ it "locals overrides" do
111
+ app(:bare) do
112
+ plugin :render, :views=>"./spec/views", :locals=>{:title=>'Home', :b=>'B'}, :layout_opts=>{:template=>'multiple-layout', :locals=>{:title=>'Roda', :a=>'A'}}
113
+
114
+ route do |r|
115
+ view("multiple", :locals=>{:b=>"BB"}, :layout_opts=>{:locals=>{:a=>'AA'}})
116
+ end
117
+ end
118
+
119
+ body.strip.should == "Roda:AA::Home:BB"
120
+ end
121
+
110
122
  it ":layout=>true/false/string/hash/not-present respects plugin layout switch and template" do
111
123
  app(:bare) do
112
124
  plugin :render, :views=>"./spec/views", :layout_opts=>{:template=>'layout-yield', :locals=>{:title=>'a'}}
@@ -149,13 +161,20 @@ describe "render plugin" do
149
161
  body('/h').gsub("\n", '').should == "<title>Roda: a</title>bar"
150
162
 
151
163
  app.plugin :render, :layout=>nil
152
- body.gsub("\n", '').should == "<title>Alternative Layout: a</title>bar"
164
+ body.gsub("\n", '').should == "HeaderbarFooter"
153
165
  body('/a').gsub("\n", '').should == "bar"
154
166
  body('/f').gsub("\n", '').should == "bar"
155
167
  body('/s').gsub("\n", '').should == "<title>Roda: a</title>bar"
156
168
  body('/h').gsub("\n", '').should == "<title>Roda: a</title>bar"
157
169
 
158
170
  app.plugin :render, :layout=>false
171
+ body.gsub("\n", '').should == "HeaderbarFooter"
172
+ body('/a').gsub("\n", '').should == "bar"
173
+ body('/f').gsub("\n", '').should == "bar"
174
+ body('/s').gsub("\n", '').should == "<title>Roda: a</title>bar"
175
+ body('/h').gsub("\n", '').should == "<title>Roda: a</title>bar"
176
+
177
+ app.plugin :render, :layout_opts=>{:template=>'layout-alternative', :locals=>{:title=>'a'}}
159
178
  body.gsub("\n", '').should == "<title>Alternative Layout: a</title>bar"
160
179
  body('/a').gsub("\n", '').should == "bar"
161
180
  body('/f').gsub("\n", '').should == "bar"
@@ -163,6 +182,26 @@ describe "render plugin" do
163
182
  body('/h').gsub("\n", '').should == "<title>Roda: a</title>bar"
164
183
  end
165
184
 
185
+ it "app :root option affects :views default" do
186
+ app
187
+ app.plugin :render
188
+ app.render_opts[:views].should == File.join(Dir.pwd, 'views')
189
+
190
+ app.opts[:root] = '/foo'
191
+ app.plugin :render
192
+ app.render_opts[:views].should == '/foo/views'
193
+
194
+ app.opts[:root] = '/foo/bar'
195
+ app.plugin :render
196
+ app.render_opts[:views].should == '/foo/bar/views'
197
+
198
+ app.opts[:root] = nil
199
+ app.plugin :render
200
+ app.render_opts[:views].should == File.join(Dir.pwd, 'views')
201
+ app.plugin :render, :views=>'bar'
202
+ app.render_opts[:views].should == File.join(Dir.pwd, 'bar')
203
+ end
204
+
166
205
  it "inline layouts and inline views" do
167
206
  app(:render) do
168
207
  view({:inline=>'bar'}, :layout=>{:inline=>'Foo: <%= yield %>'})
@@ -83,6 +83,11 @@ describe "sinatra_helpers plugin" do
83
83
  header('Content-Length').should == '11'
84
84
  end
85
85
 
86
+ it 'supports #join' do
87
+ sin_app{body{'Hello World'}; nil}
88
+ req[2].join.should == 'Hello World'
89
+ end
90
+
86
91
  it 'takes a String, Array, or other object responding to #each' do
87
92
  sin_app{body 'Hello World'; nil}
88
93
  body.should == 'Hello World'
@@ -0,0 +1,30 @@
1
+ require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
2
+
3
+ describe "static plugin" do
4
+ it "adds support for serving static files" do
5
+ app(:bare) do
6
+ plugin :static, ['/about'], :root=>'spec/views'
7
+
8
+ route do
9
+ 'a'
10
+ end
11
+ end
12
+
13
+ body.should == 'a'
14
+ body('/about/_test.erb').should == File.read('spec/views/about/_test.erb')
15
+ end
16
+
17
+ it "respects the application's :root option" do
18
+ app(:bare) do
19
+ opts[:root] = File.expand_path('../../', __FILE__)
20
+ plugin :static, ['/about'], :root=>'views'
21
+
22
+ route do
23
+ 'a'
24
+ end
25
+ end
26
+
27
+ body.should == 'a'
28
+ body('/about/_test.erb').should == File.read('spec/views/about/_test.erb')
29
+ end
30
+ end
@@ -0,0 +1,117 @@
1
+ require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
2
+
3
+ begin
4
+ require 'tilt/erb'
5
+ rescue LoadError
6
+ warn "tilt not installed, skipping view_options plugin test"
7
+ else
8
+ describe "view_options plugin view subdirs" do
9
+ before do
10
+ app(:bare) do
11
+ plugin :render, :views=>"."
12
+ plugin :view_options
13
+
14
+ route do |r|
15
+ append_view_subdir 'spec'
16
+
17
+ r.on "home" do
18
+ set_view_subdir 'spec/views'
19
+ view("home", :locals=>{:name => "Agent Smith", :title => "Home"}, :layout_opts=>{:locals=>{:title=>"Home"}})
20
+ end
21
+
22
+ r.on "about" do
23
+ append_view_subdir 'views'
24
+ render("about", :locals=>{:title => "About Roda"})
25
+ end
26
+
27
+ r.on "path" do
28
+ render('spec/views/about', :locals=>{:title => "Path"}, :layout_opts=>{:locals=>{:title=>"Home"}})
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ it "should use set subdir if template name does not contain a slash" do
35
+ body("/home").strip.should == "<title>Roda: Home</title>\n<h1>Home</h1>\n<p>Hello Agent Smith</p>"
36
+ end
37
+
38
+ it "should not use set subdir if template name contains a slash" do
39
+ body("/about").strip.should == "<h1>About Roda</h1>"
40
+ end
41
+
42
+ it "should not change behavior when subdir is not set" do
43
+ body("/path").strip.should == "<h1>Path</h1>"
44
+ end
45
+ end
46
+
47
+ describe "view_options plugin" do
48
+ it "should set view and layout options and locals to use" do
49
+ app(:view_options) do
50
+ set_view_options :views=>'spec/views'
51
+ set_view_locals :title=>'About Roda'
52
+ set_layout_options :views=>'spec/views', :template=>'layout-alternative'
53
+ set_layout_locals :title=>'Home'
54
+ view('about')
55
+ end
56
+
57
+ body.strip.should == "<title>Alternative Layout: Home</title>\n<h1>About Roda</h1>"
58
+ end
59
+
60
+ it "should merge multiple calls to set view and layout options and locals" do
61
+ app(:view_options) do
62
+ set_layout_options :views=>'spec/views', :template=>'multiple-layout', :ext=>'str'
63
+ set_view_options :views=>'spec/views', :ext=>'str'
64
+ set_layout_locals :title=>'About Roda'
65
+ set_view_locals :title=>'Home'
66
+
67
+ set_layout_options :ext=>'erb'
68
+ set_view_options :ext=>'erb'
69
+ set_layout_locals :a=>'A'
70
+ set_view_locals :b=>'B'
71
+
72
+ view('multiple')
73
+ end
74
+
75
+ body.strip.should == "About Roda:A::Home:B"
76
+ end
77
+
78
+ it "should have set_view_locals have more precedence than plugin options, but less than view/render method options" do
79
+ app(:bare) do
80
+ plugin :render, :views=>"./spec/views", :locals=>{:title=>'Home', :b=>'B'}, :layout_opts=>{:template=>'multiple-layout', :locals=>{:title=>'About Roda', :a=>'A'}}
81
+ plugin :view_options
82
+
83
+ route do |r|
84
+ r.is 'c' do
85
+ view(:multiple)
86
+ end
87
+
88
+ set_view_locals :b=>'BB'
89
+ set_layout_locals :a=>'AA'
90
+
91
+ r.on 'b' do
92
+ set_view_locals :title=>'About'
93
+ set_layout_locals :title=>'Roda'
94
+
95
+ r.is 'a' do
96
+ view(:multiple)
97
+ end
98
+
99
+ view("multiple", :locals=>{:b => "BBB"}, :layout_opts=>{:locals=>{:a=>'AAA'}})
100
+ end
101
+
102
+ r.is 'a' do
103
+ view(:multiple)
104
+ end
105
+
106
+ view("multiple", :locals=>{:b => "BBB"}, :layout_opts=>{:locals=>{:a=>'AAA'}})
107
+ end
108
+ end
109
+
110
+ body('/c').strip.should == "About Roda:A::Home:B"
111
+ body('/b/a').strip.should == "Roda:AA::About:BB"
112
+ body('/b').strip.should == "Roda:AAA::About:BBB"
113
+ body('/a').strip.should == "About Roda:AA::Home:BB"
114
+ body.strip.should == "About Roda:AAA::Home:BBB"
115
+ end
116
+ end
117
+ end
data/spec/spec_helper.rb CHANGED
@@ -80,7 +80,11 @@ class RSPEC_EXAMPLE_GROUP
80
80
  end
81
81
 
82
82
  def body(path='/', env={})
83
- req(path, env)[2].join
83
+ s = ''
84
+ b = req(path, env)[2]
85
+ b.each{|x| s << x}
86
+ b.close if b.respond_to?(:close)
87
+ s
84
88
  end
85
89
 
86
90
  def _app(&block)
@@ -0,0 +1 @@
1
+ <%= title %>:<%= a %>::<%= yield %>
@@ -0,0 +1 @@
1
+ <%= title %>:<%= b %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-13 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -137,6 +137,7 @@ extra_rdoc_files:
137
137
  - doc/release_notes/1.2.0.txt
138
138
  - doc/release_notes/1.3.0.txt
139
139
  - doc/release_notes/2.0.0.txt
140
+ - doc/release_notes/2.1.0.txt
140
141
  files:
141
142
  - CHANGELOG
142
143
  - MIT-LICENSE
@@ -148,6 +149,7 @@ files:
148
149
  - doc/release_notes/1.2.0.txt
149
150
  - doc/release_notes/1.3.0.txt
150
151
  - doc/release_notes/2.0.0.txt
152
+ - doc/release_notes/2.1.0.txt
151
153
  - lib/roda.rb
152
154
  - lib/roda/plugins/_erubis_escaping.rb
153
155
  - lib/roda/plugins/all_verbs.rb
@@ -196,10 +198,12 @@ files:
196
198
  - lib/roda/plugins/render_each.rb
197
199
  - lib/roda/plugins/sinatra_helpers.rb
198
200
  - lib/roda/plugins/slash_path_empty.rb
201
+ - lib/roda/plugins/static.rb
199
202
  - lib/roda/plugins/static_path_info.rb
200
203
  - lib/roda/plugins/streaming.rb
201
204
  - lib/roda/plugins/symbol_matchers.rb
202
205
  - lib/roda/plugins/symbol_views.rb
206
+ - lib/roda/plugins/view_options.rb
203
207
  - lib/roda/plugins/view_subdirs.rb
204
208
  - lib/roda/version.rb
205
209
  - spec/assets/css/app.scss
@@ -259,11 +263,11 @@ files:
259
263
  - spec/plugin/render_spec.rb
260
264
  - spec/plugin/sinatra_helpers_spec.rb
261
265
  - spec/plugin/slash_path_empty_spec.rb
262
- - spec/plugin/static_path_info_spec.rb
266
+ - spec/plugin/static_spec.rb
263
267
  - spec/plugin/streaming_spec.rb
264
268
  - spec/plugin/symbol_matchers_spec.rb
265
269
  - spec/plugin/symbol_views_spec.rb
266
- - spec/plugin/view_subdirs_spec.rb
270
+ - spec/plugin/view_options_spec.rb
267
271
  - spec/plugin_spec.rb
268
272
  - spec/redirect_spec.rb
269
273
  - spec/request_spec.rb
@@ -281,6 +285,8 @@ files:
281
285
  - spec/views/layout-yield.erb
282
286
  - spec/views/layout.erb
283
287
  - spec/views/layout.str
288
+ - spec/views/multiple-layout.erb
289
+ - spec/views/multiple.erb
284
290
  homepage: http://roda.jeremyevans.net
285
291
  licenses:
286
292
  - MIT