cuba 3.1.0 → 3.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b881a2c6bb3396ac4515bea4b2a9745933f071b2
4
+ data.tar.gz: dad770ec883f93c34cd0f0bb55a0fb5f8a782096
5
+ SHA512:
6
+ metadata.gz: 16ff53505523c87084f283005ad9819e06d87676d08663ebe430c15924beb7265a55c88328a7b71dd04fb3c13af5035b590e620319c3752b8da7515aa054d9d4
7
+ data.tar.gz: 5e1ef15fa6595a48050e3fbdf1fbd71cba9615a509631a5724445bb20bd37e6f5b1b9eb40d8295c0474c8e533a22f3bf14387a7443e4440133fbe97a917beaf1
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 3.1.1
2
+
3
+ * Add support for custom default layouts.
4
+
1
5
  3.1.0
2
6
 
3
7
  * Do a deep clone of the settings object during inheritance.
data/README.md CHANGED
@@ -8,13 +8,17 @@ _n_. a microframework for web development.
8
8
  Community
9
9
  ---------
10
10
 
11
- Meet us on IRC: [#cuba.rb](irc://chat.freenode.net/#cuba.rb) on [freenode.net](http://freenode.net/)
11
+ Meet us on IRC: [#cuba.rb][irc] on [freenode.net][freenode].
12
+
13
+ [irc]: irc://chat.freenode.net/#cuba.rb
14
+ [freenode]: http://freenode.net/
12
15
 
13
16
  Description
14
17
  -----------
15
18
 
16
- Cuba is a microframework for web development originally inspired by [Rum][rum],
17
- a tiny but powerful mapper for [Rack][rack] applications.
19
+ Cuba is a microframework for web development originally inspired
20
+ by [Rum][rum], a tiny but powerful mapper for [Rack][rack]
21
+ applications.
18
22
 
19
23
  It integrates many templates via [Tilt][tilt], and testing via
20
24
  [Cutest][cutest] and [Capybara][capybara].
@@ -24,6 +28,14 @@ It integrates many templates via [Tilt][tilt], and testing via
24
28
  [tilt]: http://github.com/rtomayko/tilt
25
29
  [cutest]: http://github.com/djanowski/cutest
26
30
  [capybara]: http://github.com/jnicklas/capybara
31
+ [rack-test]: https://github.com/brynary/rack-test
32
+
33
+ Installation
34
+ ------------
35
+
36
+ ``` console
37
+ $ gem install cuba
38
+ ```
27
39
 
28
40
  Usage
29
41
  -----
@@ -33,8 +45,10 @@ Here's a simple application:
33
45
  ``` ruby
34
46
  # cat hello_world.rb
35
47
  require "cuba"
48
+ require "rack/protection"
36
49
 
37
- Cuba.use Rack::Session::Cookie
50
+ Cuba.use Rack::Session::Cookie, :secret => "__a_very_long_string__"
51
+ Cuba.use Rack::Protection
38
52
 
39
53
  Cuba.define do
40
54
  on get do
@@ -47,14 +61,22 @@ Cuba.define do
47
61
  end
48
62
  end
49
63
  end
64
+ ```
65
+
66
+ And the test file:
50
67
 
68
+ ``` ruby
51
69
  # cat hello_world_test.rb
52
70
  require "cuba/test"
71
+ require "./hello_world"
53
72
 
54
73
  scope do
55
74
  test "Homepage" do
56
- visit "/"
57
- assert has_content?("Hello world!")
75
+ get "/"
76
+
77
+ follow_redirect!
78
+
79
+ assert_equal "Hello world!", last_response.body
58
80
  end
59
81
  end
60
82
  ```
@@ -77,8 +99,10 @@ Here's an example showcasing how different matchers work:
77
99
 
78
100
  ``` ruby
79
101
  require "cuba"
102
+ require "rack/protection"
80
103
 
81
- Cuba.use Rack::Session::Cookie
104
+ Cuba.use Rack::Session::Cookie, :secret => "__a_very_long_string__"
105
+ Cuba.use Rack::Protection
82
106
 
83
107
  Cuba.define do
84
108
 
@@ -148,23 +172,194 @@ Cuba.define do
148
172
  end
149
173
  ```
150
174
 
175
+ Status codes
176
+ ------------
177
+
178
+ As soon as an `on` block is executed, the status code for the
179
+ response is changed to 200. The default status code is 404, and it
180
+ is returned if no `on` block succeeds inside a Cuba app.
181
+
182
+ As this behavior can be tricky, let's look at some examples:
183
+
184
+ ``` ruby
185
+ Cuba.define do
186
+ on get do
187
+ on "hello" do
188
+ res.write "hello world"
189
+ end
190
+ end
191
+ end
192
+
193
+ # Requests:
194
+ #
195
+ # GET / # 200, ""
196
+ # GET /hello # 200, "hello world"
197
+ # GET /hello/world # 200, "hello world"
198
+ ```
199
+
200
+ As you can see, as soon as `on get` matched, the status code was
201
+ changed to 200. If you expected some of those requests to return a
202
+ 404 status code, you may be surprised by this behavior.
203
+
204
+ In the following example, as both arguments to `on` must match,
205
+ the requests to `/` return 404.
206
+
207
+ ``` ruby
208
+ Cuba.define do
209
+ on get, "hello" do
210
+ res.write "hello world"
211
+ end
212
+ end
213
+
214
+ # Requests:
215
+ #
216
+ # GET / # 404, ""
217
+ # GET /hello # 200, "hello world"
218
+ # GET /hello/world # 200, "hello world"
219
+ ```
220
+
221
+ Another way is to add a default block:
222
+
223
+ ``` ruby
224
+ Cuba.define do
225
+ on get do
226
+ on "hello" do
227
+ res.write "hello world"
228
+ end
229
+
230
+ on default do
231
+ res.status = 404
232
+ end
233
+ end
234
+ end
235
+
236
+ # Requests:
237
+ #
238
+ # GET / # 404, ""
239
+ # GET /hello # 200, "hello world"
240
+ # GET /hello/world # 200, "hello world"
241
+ ```
242
+
243
+ Yet another way is to mount an application with routes that don't
244
+ match the request:
245
+
246
+ ``` ruby
247
+ SomeApp = Cuba.new do
248
+ on "bye" do
249
+ res.write "bye!"
250
+ end
251
+ end
252
+
253
+ Cuba.define do
254
+ on get do
255
+ run SomeApp
256
+ end
257
+ end
258
+
259
+ # Requests:
260
+ #
261
+ # GET / # 404, ""
262
+ # GET /hello # 404, ""
263
+ # GET /hello/world # 404, ""
264
+ ```
265
+
266
+ As Cuba encourages the composition of applications, this last
267
+ example is a very common pattern.
268
+
269
+ You can also change the status code at any point inside the define
270
+ block. That way you can change the default status, as shown in the
271
+ following example:
272
+
273
+ ``` ruby
274
+ Cuba.define do
275
+ res.status = 404
276
+
277
+ on get do
278
+ on "hello" do
279
+ res.status = 200
280
+ res.write "hello world"
281
+ end
282
+ end
283
+ end
284
+
285
+ # Requests:
286
+ #
287
+ # GET / # 404, ""
288
+ # GET /hello # 200, "hello world"
289
+ # GET /hello/world # 200, "hello world"
290
+ ```
291
+
292
+ If you really want to return 404 for everything under "hello", you
293
+ can match the end of line:
294
+
295
+ ``` ruby
296
+ Cuba.define do
297
+ res.status = 404
298
+
299
+ on get do
300
+ on /hello\/?\z/ do
301
+ res.status = 200
302
+ res.write "hello world"
303
+ end
304
+ end
305
+ end
306
+
307
+ # Requests:
308
+ #
309
+ # GET / # 404, ""
310
+ # GET /hello # 200, "hello world"
311
+ # GET /hello/world # 404, ""
312
+ ```
313
+
314
+ This last example is not a common usage pattern. It's here only to
315
+ illustrate how Cuba can be adapted for different use cases.
316
+
317
+ If you need this behavior, you can create a helper:
318
+
319
+ ``` ruby
320
+ module TerminalMatcher
321
+ def terminal(path)
322
+ /#{path}\/?\z/
323
+ end
324
+ end
325
+
326
+ Cuba.plugin TerminalMatcher
327
+
328
+ Cuba.define do
329
+ res.status = 404
330
+
331
+ on get do
332
+ on terminal("hello") do
333
+ res.status = 200
334
+ res.write "hello world"
335
+ end
336
+ end
337
+ end
338
+ ```
339
+
151
340
  Security
152
341
  --------
153
342
 
154
343
  The favorite security layer for Cuba is
155
- [Rack::Protection](https://github.com/rkh/rack-protection). It is not
156
- included by default because there are legitimate uses for plain Cuba
157
- (for instance, when designing an API).
344
+ [Rack::Protection][rack-protection]. It is not included by default
345
+ because there are legitimate uses for plain Cuba (for instance,
346
+ when designing an API).
158
347
 
159
- If you are building a web application, by all means make sure to
160
- include a security layer. As it is the convention for unsafe
348
+ If you are building a web application, by all means make sure
349
+ to include a security layer. As it is the convention for unsafe
161
350
  operations, only POST, PUT and DELETE requests are monitored.
162
351
 
352
+ You should also always set a session secret to some undisclosed
353
+ value. Keep in mind that the content in the session cookie is
354
+ *not* encrypted.
355
+
356
+ [rack-protection]: https://github.com/rkh/rack-protection
357
+
163
358
  ``` ruby
164
359
  require "cuba"
165
360
  require "rack/protection"
166
361
 
167
- Cuba.use Rack::Session::Cookie
362
+ Cuba.use Rack::Session::Cookie, :secret => "__a_very_long_string__"
168
363
  Cuba.use Rack::Protection
169
364
  Cuba.use Rack::Protection::RemoteReferrer
170
365
 
@@ -210,7 +405,7 @@ instances of [Rack::Request][request] and `Cuba::Response` respectively, and
210
405
  [response]: http://rack.rubyforge.org/doc/classes/Rack/Response.html
211
406
 
212
407
  Those objects are helpers for accessing the request and for building
213
- the response. Most of the time, you will just use `req.write`.
408
+ the response. Most of the time, you will just use `res.write`.
214
409
 
215
410
  If you want to use custom `Request` or `Response` objects, you can
216
411
  set the new values as follows:
@@ -276,15 +471,32 @@ end
276
471
  Testing
277
472
  -------
278
473
 
279
- Given that Cuba is essentially Rack, it is very easy to test with `Webrat` or
280
- `Capybara`. Cuba's own tests are written with a combination of [Cutest][cutest]
281
- and [Capybara][capybara], and if you want to use the same for your tests it is
282
- as easy as requiring `cuba/test`:
474
+ Given that Cuba is essentially Rack, it is very easy to test with
475
+ `Rack::Test`, `Webrat` or `Capybara`. Cuba's own tests are written
476
+ with a combination of [Cutest][cutest] and [Rack::Test][rack-test],
477
+ and if you want to use the same for your tests it is as easy as
478
+ requiring `cuba/test`:
283
479
 
284
480
  ``` ruby
285
481
  require "cuba/test"
286
482
  require "your/app"
287
483
 
484
+ scope do
485
+ test "Homepage" do
486
+ get "/"
487
+
488
+ assert_equal "Hello world!", last_response.body
489
+ end
490
+ end
491
+ ```
492
+
493
+ If you prefer to use [Capybara][capybara], instead of requiring
494
+ `cuba/test` you can require `cuba/capybara`:
495
+
496
+ ``` ruby
497
+ require "cuba/capybara"
498
+ require "your/app"
499
+
288
500
  scope do
289
501
  test "Homepage" do
290
502
  visit "/"
@@ -294,8 +506,8 @@ scope do
294
506
  end
295
507
  ```
296
508
 
297
- To read more about testing, check the documentation for [Cutest][cutest] and
298
- [Capybara][capybara].
509
+ To read more about testing, check the documentation for
510
+ [Cutest][cutest], [Rack::Test][rack-test] and [Capybara][capybara].
299
511
 
300
512
  Settings
301
513
  --------
@@ -341,6 +553,26 @@ end
341
553
  Note that in order to use this plugin you need to have [Tilt][tilt] installed, along
342
554
  with the templating engines you want to use.
343
555
 
556
+ You can also configure the template engine in the app's settings,
557
+ and that will allow you to skip the file extension when rendering a
558
+ file:
559
+
560
+ ``` ruby
561
+ require "cuba/render"
562
+
563
+ Cuba.plugin Cuba::Render
564
+ Cuba.settings[:render][:template_engine] = "slim"
565
+
566
+ Cuba.define do
567
+ on default do
568
+
569
+ # Now we can use the `view` helper, which guesses the file
570
+ # extension based on the configured template_engine.
571
+ res.write view("home", content: "hello, world")
572
+ end
573
+ end
574
+ ```
575
+
344
576
  Plugins
345
577
  -------
346
578
 
@@ -364,7 +596,7 @@ That's the simplest kind of plugin you'll write. In fact, that's exactly how
364
596
  the `markdown` helper is written in `Cuba::TextHelpers`.
365
597
 
366
598
  A more complicated plugin can make use of `Cuba.settings` to provide default
367
- values. In the following example, note that if the module has a `setup` method it will
599
+ values. In the following example, note that if the module has a `setup` method, it will
368
600
  be called as soon as it is included:
369
601
 
370
602
  ``` ruby
@@ -406,10 +638,3 @@ Cuba.set(:foo, "bar")
406
638
  assert_equal "bar", Cuba.get(:foo)
407
639
  assert_equal "bar", Cuba.settings[:foo]
408
640
  ```
409
-
410
- Installation
411
- ------------
412
-
413
- ``` ruby
414
- $ gem install cuba
415
- ```
data/cuba.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cuba"
3
- s.version = "3.1.0"
3
+ s.version = "3.1.1"
4
4
  s.summary = "Microframework for web applications."
5
5
  s.description = "Cuba is a microframework for web applications."
6
6
  s.authors = ["Michel Martens"]
data/lib/cuba.rb CHANGED
@@ -147,7 +147,7 @@ class Cuba
147
147
  # end
148
148
  #
149
149
  # on get, "signup" do
150
- # res.write "Signup
150
+ # res.write "Signup"
151
151
  # end
152
152
  #
153
153
  # on "user/:id" do |uid|
@@ -197,7 +197,7 @@ class Cuba
197
197
  private :try
198
198
 
199
199
  def consume(pattern)
200
- matchdata = env["PATH_INFO"].match(/\A\/(#{pattern})((?:\/|\z))/)
200
+ matchdata = env["PATH_INFO"].match(/\A\/(#{pattern})(\/|\z)/)
201
201
 
202
202
  return false unless matchdata
203
203
 
data/lib/cuba/render.rb CHANGED
@@ -5,13 +5,14 @@ class Cuba
5
5
  def self.setup(app)
6
6
  app.settings[:render] ||= {}
7
7
  app.settings[:render][:template_engine] ||= "erb"
8
+ app.settings[:render][:layout] ||= "layout"
8
9
  app.settings[:render][:views] ||= File.expand_path("views", Dir.pwd)
9
10
  app.settings[:render][:options] ||= {
10
11
  default_encoding: Encoding.default_external
11
12
  }
12
13
  end
13
14
 
14
- def view(template, locals = {}, layout = "layout")
15
+ def view(template, locals = {}, layout = settings[:render][:layout])
15
16
  partial(layout, { content: partial(template, locals) }.merge(locals))
16
17
  end
17
18
 
data/test/cookie.rb CHANGED
@@ -29,6 +29,6 @@ test "delete cookie" do
29
29
 
30
30
  _, headers, body = Cuba.call(env)
31
31
 
32
- assert_equal "foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT",
32
+ assert_equal "foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
33
33
  headers["Set-Cookie"]
34
34
  end
data/test/render.rb CHANGED
@@ -58,6 +58,14 @@ scope do
58
58
 
59
59
  assert_response body, ["<title>Cuba: Home</title>\n<h1>Home</h1>\n<p>Hello Agent Smith</p>\n\n"]
60
60
  end
61
+
62
+ test "custom default layout support" do
63
+ Cuba.settings[:render][:layout] = "layout-alternative"
64
+
65
+ _, _, body = Cuba.call({ "PATH_INFO" => "/home", "SCRIPT_NAME" => "/" })
66
+
67
+ assert_response body, ["<title>Alternative Layout: Home</title>\n<h1>Home</h1>\n<p>Hello Agent Smith</p>\n"]
68
+ end
61
69
  end
62
70
 
63
71
  test "caching behavior" do
@@ -94,3 +102,18 @@ test "simple layout support" do
94
102
 
95
103
  assert_response resp, ["Header\nThis is the actual content.\nFooter\n"]
96
104
  end
105
+
106
+ test "overrides layout" do
107
+ Cuba.plugin Cuba::Render
108
+ Cuba.settings[:render][:views] = "./test/views"
109
+
110
+ Cuba.define do
111
+ on true do
112
+ res.write view("home", { name: "Agent Smith", title: "Home" }, "layout-alternative")
113
+ end
114
+ end
115
+
116
+ _, _, body = Cuba.call({})
117
+
118
+ assert_response body, ["<title>Alternative Layout: Home</title>\n<h1>Home</h1>\n<p>Hello Agent Smith</p>\n"]
119
+ end
metadata CHANGED
@@ -1,60 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuba
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
5
- prerelease:
4
+ version: 3.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michel Martens
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-24 00:00:00.000000000 Z
11
+ date: 2014-03-09 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rack
16
- requirement: &2152188260 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *2152188260
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: cutest
27
- requirement: &2152187440 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
- - - ! '>='
31
+ - - '>='
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0'
33
34
  type: :development
34
35
  prerelease: false
35
- version_requirements: *2152187440
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: rack-test
38
- requirement: &2152186360 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
- - - ! '>='
45
+ - - '>='
42
46
  - !ruby/object:Gem::Version
43
47
  version: '0'
44
48
  type: :development
45
49
  prerelease: false
46
- version_requirements: *2152186360
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: tilt
49
- requirement: &2152185380 !ruby/object:Gem::Requirement
50
- none: false
57
+ requirement: !ruby/object:Gem::Requirement
51
58
  requirements:
52
- - - ! '>='
59
+ - - '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '0'
55
62
  type: :development
56
63
  prerelease: false
57
- version_requirements: *2152185380
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
58
69
  description: Cuba is a microframework for web applications.
59
70
  email:
60
71
  - michel@soveran.com
@@ -96,26 +107,25 @@ files:
96
107
  - test/settings.rb
97
108
  homepage: http://github.com/soveran/cuba
98
109
  licenses: []
110
+ metadata: {}
99
111
  post_install_message:
100
112
  rdoc_options: []
101
113
  require_paths:
102
114
  - lib
103
115
  required_ruby_version: !ruby/object:Gem::Requirement
104
- none: false
105
116
  requirements:
106
- - - ! '>='
117
+ - - '>='
107
118
  - !ruby/object:Gem::Version
108
119
  version: '0'
109
120
  required_rubygems_version: !ruby/object:Gem::Requirement
110
- none: false
111
121
  requirements:
112
- - - ! '>='
122
+ - - '>='
113
123
  - !ruby/object:Gem::Version
114
124
  version: '0'
115
125
  requirements: []
116
126
  rubyforge_project:
117
- rubygems_version: 1.8.11
127
+ rubygems_version: 2.0.3
118
128
  signing_key:
119
- specification_version: 3
129
+ specification_version: 4
120
130
  summary: Microframework for web applications.
121
131
  test_files: []