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.
- checksums.yaml +4 -4
- data/CHANGELOG +26 -0
- data/README.rdoc +83 -22
- data/Rakefile +1 -1
- data/doc/release_notes/2.1.0.txt +124 -0
- data/lib/roda/plugins/assets.rb +17 -9
- data/lib/roda/plugins/class_level_routing.rb +5 -2
- data/lib/roda/plugins/delegate.rb +6 -3
- data/lib/roda/plugins/indifferent_params.rb +7 -0
- data/lib/roda/plugins/mailer.rb +18 -1
- data/lib/roda/plugins/multi_route.rb +2 -1
- data/lib/roda/plugins/path.rb +75 -6
- data/lib/roda/plugins/render.rb +33 -14
- data/lib/roda/plugins/static.rb +35 -0
- data/lib/roda/plugins/view_options.rb +161 -0
- data/lib/roda/plugins/view_subdirs.rb +6 -63
- data/lib/roda/version.rb +1 -1
- data/spec/composition_spec.rb +12 -0
- data/spec/matchers_spec.rb +34 -0
- data/spec/plugin/assets_spec.rb +112 -17
- data/spec/plugin/delete_empty_headers_spec.rb +12 -0
- data/spec/plugin/mailer_spec.rb +46 -3
- data/spec/plugin/module_include_spec.rb +17 -0
- data/spec/plugin/multi_route_spec.rb +10 -0
- data/spec/plugin/named_templates_spec.rb +6 -0
- data/spec/plugin/not_found_spec.rb +1 -1
- data/spec/plugin/path_spec.rb +76 -0
- data/spec/plugin/render_each_spec.rb +6 -0
- data/spec/plugin/render_spec.rb +40 -1
- data/spec/plugin/sinatra_helpers_spec.rb +5 -0
- data/spec/plugin/static_spec.rb +30 -0
- data/spec/plugin/view_options_spec.rb +117 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/views/multiple-layout.erb +1 -0
- data/spec/views/multiple.erb +1 -0
- metadata +10 -4
- data/spec/plugin/static_path_info_spec.rb +0 -56
- 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
|
data/spec/plugin/path_spec.rb
CHANGED
@@ -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
|
data/spec/plugin/render_spec.rb
CHANGED
@@ -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 == "
|
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
@@ -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.
|
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-
|
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/
|
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/
|
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
|