tynn 1.4.0 → 2.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4814f92f9f4fc3914fd79a2b2756caae11b6dcf3
4
- data.tar.gz: 24e79b0a795e4abc44ffe65d43ee49cb6e3af3a8
3
+ metadata.gz: 3428a8bf437b03bf9e9dc2d2568143010f5a8be7
4
+ data.tar.gz: 9a36c6091a73ced16b4b5a5e9f8cec60fa6fd39e
5
5
  SHA512:
6
- metadata.gz: 69fa5b9b8a69a5709b58435287e90c8a547e2dc98c80ded0b1dc7c46ac306e4f02b77819ee52619ff6c8cfae27ef4bbaa57a36b18ad2e815928cb49bbb9d4f9c
7
- data.tar.gz: 4e6b16cd569034ecbaf6f9b671b5327264035988480659d21154e7694b64ccebfcabc05deee3acf80dc25c16b3232feadaa4e256701b72e8576e8672fedd2e12
6
+ metadata.gz: 25196be28e4b69d4d0ea609bcdfa7fa08276716c6e94753347ac17c8dfad6d6c9f9b390559b79ca9c9f67fbec78dec2379a481c21497460768502649bc95c63e
7
+ data.tar.gz: a5bdf9e80a0d95d9d172264a00612dc0c86666a1c25c761598363e100279f6c32d09d20235d3d1a0216a0ed29f2890a80da263e431c9e30f125aaa3081a418fc
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Francesco Rodríguez and contributors
3
+ Copyright (c) 2015-2016 Francesco Rodríguez and contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,50 +1,565 @@
1
- Tynn [![Build Status](https://travis-ci.org/frodsan/tynn.svg)](https://travis-ci.org/frodsan/tynn)
2
- ====
1
+ # Tynn
3
2
 
4
- A thin library for web development.
3
+ [![Build Status](https://travis-ci.org/frodsan/tynn.svg?branch=master)](https://travis-ci.org/frodsan/tynn)
4
+ [![Dependency Status](https://gemnasium.com/badges/github.com/frodsan/tynn.svg)](https://gemnasium.com/github.com/frodsan/tynn)
5
+ [![Code Climate](https://codeclimate.com/github/frodsan/tynn/badges/gpa.svg)](https://codeclimate.com/github/frodsan/tynn)
6
+ [![Join the chat at https://gitter.im/frodsan/tynn](https://badges.gitter.im/frodsan/tynn.svg)](https://gitter.im/frodsan/tynn?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
7
 
6
- Description
7
- -----------
8
+ A thin library for web development in Ruby.
8
9
 
9
- Tynn is a thin abstraction on top of [Syro][syro], a very simple and fast
10
- router for web applications.
10
+ * [Getting Started](#getting-started)
11
+ * [Assumptions](#assumptions)
12
+ * [Installation](#installation)
13
+ * [Hello World!](#hello-world)
14
+ * [Under the Hood](#under-the-hood)
15
+ * [Tynn on Rack](#tynn-on-rack)
16
+ * [Routing Basics](#routing-basics)
17
+ * [Managing Request and Response](#managing-request-and-response)
18
+ * [Redirecting a Request](#redirecting-a-request)
19
+ * [Halting a Request](#halting-a-request)
20
+ * [Extending Tynn](#extending-tynn)
21
+ * [Middleware](#middleware)
22
+ * [Plugins](#plugins)
23
+ * [Settings](#settings)
24
+ * [Default Plugins](#default-plugins)
25
+ * [Environments](#environments)
26
+ * [Method Override](#method-override)
27
+ * [Static Files](#static-files)
28
+ * [Security](#security)
29
+ * [Testing](#testing)
30
+ * [API Reference](http://api.tynn.xyz/2.0.0)
31
+ * [Changelog](#changelog)
32
+ * [Development](#development)
33
+ * [Contributing](#contributing)
34
+ * [Build History](#build-history)
35
+ * [License](#license)
11
36
 
12
- Usage
13
- -----
37
+ **NOTE. There is an online version of this README at http://tynn.xyz/.**
14
38
 
15
- Here's a minimal application:
39
+ ## Getting Started
40
+
41
+ Tynn is a minimal and flexible library for building JSON web services and web applications in Ruby. It's designed with two main goals: simplicity and extensibility.
42
+
43
+ Tynn offers the essentials to handle HTTP requests and also includes mechanisms to easily extend its functionality through [plugins](#plugins) and [middleware][middleware]. Tynn ships with a set of [default plugins](#default-plugins) that you can combine to meet your needs.
44
+
45
+ Tynn is not a framework. There is no built-in support for connecting to databases or a common application architecture. This gives you the freedom to choose the appropiate tools for the job at hand.
46
+
47
+ Like most web libraries in Ruby, Tynn is built on top of [Rack], a Ruby webserver interface. Because of this, it has the benefits of using existing libraries and a variety of web servers for free.
48
+
49
+ Tynn takes design cues from other web libraries like [Rails], [Sinatra], and [Cuba]. Under the hood, it uses [Syro], a fast router for web applications.
50
+
51
+ ### Assumptions
52
+
53
+ This section serves as a high-level introduction to the core features of Tynn. It also covers installation and walks through the creation of a simple application. To get the most out of it, it's recommended to have a basic knowledge about Ruby and HTTP.
54
+
55
+ ### Installation
56
+
57
+ Installing Tynn is pretty straightforward. From the command line, use the `gem` command:
58
+
59
+ ```
60
+ $ gem install tynn
61
+ ```
62
+
63
+ If you prefer to use [Bundler] instead, set up the environment with:
64
+
65
+ ```
66
+ $ bundle init
67
+ ```
68
+
69
+ Then, update the contents of the generated Gemfile to:
70
+
71
+ ```ruby
72
+ source "https://rubygems.org"
73
+
74
+ gem "tynn", "~> 2.0"
75
+ ```
76
+
77
+ Finally, install the dependencies with:
78
+
79
+ ```
80
+ $ bundle install
81
+ ```
82
+
83
+ Now you can create your first Tynn app!
84
+
85
+ ### Hello World!
86
+
87
+ Let's start with a minimal application. Open your preferred text editor and enter the following code:
16
88
 
17
89
  ```ruby
18
- # config.ru
19
90
  require "tynn"
20
91
 
21
92
  Tynn.define do
22
- root do
93
+ on root? do
94
+ get do
95
+ res.write("Hello World!")
96
+ end
97
+ end
98
+ end
99
+ ```
100
+
101
+ Save this file as `app.rb`. Once you've done so, create another file called `config.ru` with the contents shown below:
102
+
103
+ ```ruby
104
+ require File.expand_path("app", __dir__)
105
+
106
+ run(Tynn)
107
+ ```
108
+
109
+ You already have a functional application! The syntax is very readable, but we'll discuss the details in a moment. To see it in action, you need to start a web server. You can do this by typing `rackup` in the command line.
110
+
111
+ ![Starting a Web Server](https://raw.githubusercontent.com/frodsan/tynn/master/docs/images/rackup.png)
112
+
113
+ > **NOTE:** To stop the web server, hit `Ctrl+C` in the terminal window where it's running. To verify that the server has stopped you should see your command prompt cursor again.
114
+
115
+ Now open a browser window and navigate to http://localhost:9292 to see the greeting message.
116
+
117
+ ![Hello World!](https://raw.githubusercontent.com/frodsan/tynn/master/docs/images/hello-world.png)
118
+
119
+ ### Under the hood
120
+
121
+ Tynn is all about routing. Routing determines how an application should respond to a client request to a URI (or path) and a specific HTTP request method. In our previous example, that would be the root path (`/`) and the HTTP GET method.
122
+
123
+ To get a look on what's happening under the hood, let's see line 4:
124
+
125
+ ```ruby
126
+ on root? do
127
+ # ...
128
+ end
129
+ ```
130
+
131
+ That's a little taste of what we call routing matchers in Tynn. The purpose of the `on` matcher is to execute the given block only if the given argument returns `true`. In our case, `root?` returns `true` because we are accessing the root path (`/`) from our browser.
132
+
133
+ One line below there is another type of matcher:
134
+
135
+ ```ruby
136
+ get do
137
+ res.write("Hello World!")
138
+ end
139
+ ```
140
+
141
+ Tynn also includes methods for matching all the HTTP verbs (GET, POST, etc.). By default, if there are no other matchers before a verb matcher, it automatically checks that the current request is for the root path. The above example can be written as:
142
+
143
+ ```ruby
144
+ Tynn.define do
145
+ get do
23
146
  res.write("Hello World!")
24
147
  end
25
148
  end
149
+ ```
150
+
151
+ > **Note.** If you're not familiar with the HTTP methods, check out this [Wikipedia page](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods).
152
+
153
+ ### Tynn on Rack
154
+
155
+ The last part of the puzzle is the `config.ru` file. As we mentioned earlier, Tynn is built on top of Rack ... but what is Rack?
156
+
157
+ Rack deals with HTTP requests. It provides a minimal interface between web servers supporting Ruby and Ruby web frameworks. Without Rack, Tynn would have to implement its own handler for each Ruby web server.
26
158
 
159
+ To run the hello world application you used `rackup`, one of the tools that comes with Rack. To use `rackup`, you need to supply a `config.ru` file. This file connects the Rack interface with our Tynn application through the `run` method.
160
+
161
+ ```ruby
27
162
  run(Tynn)
28
163
  ```
29
164
 
30
- Check [Getting Started][start] for more information.
165
+ Rack also figures out which server you have available in your system. When we used `rackup`, it fired up WEBrick, a web server built into Ruby by default.
166
+
167
+ ```
168
+ $ rackup
169
+ [2016-05-14 00:25:11] INFO WEBrick 1.3.1
170
+ ```
171
+
172
+ Most popular web servers, like [Puma], [Unicorn] or [Thin], have built-in support for Rack, and thus support Tynn too. You can read more about Rack visiting their home page: http://rack.github.io/.
173
+
174
+ ## Routing basics
175
+
176
+ This section covers the routing features of Tynn, such as route definitions, composing applications, and so on.
177
+
178
+ ## Managing Request and Response
179
+
180
+ This section covers the many features Tynn provides to handle requests and responses.
181
+
182
+ ### Redirecting a Request
183
+
184
+ To redirect a request to a different location, use `res.redirect`.
185
+
186
+ ```ruby
187
+ res.redirect("/pricing")
188
+ ```
189
+
190
+ To redirect to a different site, use a fully-qualified URL.
191
+
192
+ ```ruby
193
+ res.redirect("https://google.com")
194
+ ```
195
+
196
+ By default, the status code is set to `302` (Found). To set a different status code, pass an integer as a second parameter.
197
+
198
+ ```ruby
199
+ res.redirect("/projects/1", 301)
200
+ ```
201
+
202
+ ### Halting a Request
203
+
204
+ To immediately stop a request within a route, you can use the `halt` method.
205
+
206
+ ```ruby
207
+ halt([status, headers, body])
208
+ ```
209
+
210
+ Use `res.finish` to return a response as per Rack's specification.
211
+
212
+ ```ruby
213
+ if current_user.nil?
214
+ res.redirect("/login")
215
+
216
+ halt(res.finish)
217
+ end
218
+
219
+ # This won't be reached if current_user is nil
220
+ ```
221
+
222
+ ## Extending Tynn
223
+
224
+ ### Middleware
225
+
226
+ Tynn runs on [Rack](https://github.com/rack/rack). Therefore it is possible
227
+ to use Rack middleware in Tynn. This is how you add a middleware (for example
228
+ `YourMiddleware`) to your app:
229
+
230
+ ```ruby
231
+ Tynn.use(YourMiddleware)
232
+ ```
233
+
234
+ You can use any Rack middleware to your app, it is not specific to Tynn. You
235
+ can find a list of Rack middleware [here][middleware].
236
+
237
+ [middleware]: https://github.com/rack/rack/wiki/list-of-middleware
238
+
239
+ ### Plugins
240
+
241
+ A way to extend Tynn is to use the plugin API. A plugin is just a module which can contain any of the following rules:
242
+
243
+ - If a `ClassMethods` module is defined, it extends the application class.
244
+
245
+ - If a `InstanceMethods` module is defined, it's included in the application.
246
+
247
+ - If a `setup` method is defined, it will be called last. This method can be used to configure the plugin.
248
+
249
+ The following is a complete example of the plugin API.
250
+
251
+ ```ruby
252
+ require "valuta"
253
+
254
+ module CurrencyHelper
255
+ def self.setup(app, currency: "$")
256
+ self.currency = currency
257
+ end
258
+
259
+ module ClassMethods
260
+ def currency
261
+ @currency
262
+ end
263
+
264
+ def currency=(currency)
265
+ @currency = currency
266
+ end
267
+ end
268
+
269
+ module InstanceMethods
270
+ def to_currency(value)
271
+ Valuta.convert(value, prefix: self.class.currency)
272
+ end
273
+ end
274
+ end
275
+ ```
276
+
277
+ To load the plugin into the application, use the `plugin` method.
278
+
279
+ ```ruby
280
+ App.plugin(CurrencyHelper, currency: "$")
281
+ ```
282
+
283
+ Here is the plugin in action:
284
+
285
+ ```ruby
286
+ App.currency # => "$"
287
+
288
+ App.define do
289
+ get do
290
+ res.write(to_currency(4567))
291
+ end
292
+ end
293
+ # GET / => 200 $4,567
294
+ ```
295
+
296
+ ### Settings
297
+
298
+ Each application has a `settings` hash where configuration can be stored. By default, settings are inherited.
299
+
300
+ ```ruby
301
+ Tynn.set(:layout, "layout")
302
+
303
+ class Guests < Tynn; end
304
+ class Users < Tynn; end
305
+ class Adminds < Tynn; end
306
+
307
+ Users.set(:layout, "users/layout")
308
+ Admins.set(:layout, "admins/layout")
309
+
310
+ Guests.settings[:layout] # => "layout"
311
+ Users.settings[:layout] # => "users/layout"
312
+ Admins.settings[:layout] # => "admins/layout"
313
+ ```
314
+
315
+ This features comes in handy when authoring plugins.
316
+
317
+ ```ruby
318
+ module CurrencyHelper
319
+ module ClassMethods
320
+ def currency=(currency)
321
+ set(:currency, currency)
322
+ end
323
+
324
+ def currency
325
+ settings.fetch(:currency, "$")
326
+ end
327
+ end
328
+ end
329
+ ```
330
+
331
+ ## Default Plugins
332
+
333
+ Tynn ships with a set of default plugins:
334
+
335
+ | Name | Description
336
+ | --------------------- | -----------------------------------------------------------------
337
+ | [Tynn::Environment] | Adds helper methods to get and check the current environment.
338
+ | [Tynn::JSON] | Adds helper methods for json generation.
339
+ | [Tynn::Render] | Adds support for rendering templates through different engines.
340
+ | [Tynn::Session] | Adds simple cookie based session management.
341
+ | [Tynn::Static] | Adds support for static files (javascript files, images, etc.).
342
+
343
+ The following sections cover the default plugins and extensions shipped with Tynn.
344
+
345
+ ### Environments
346
+
347
+ Tynn ships with [Tynn::Environment] to set and check the current environment for the application.
348
+
349
+ ```ruby
350
+ require "tynn"
351
+ require "tynn/environment"
352
+
353
+ Tynn.plugin(Tynn::Environment)
354
+ ```
355
+
356
+ The default environment is based on the `RACK_ENV` environment variable.
357
+
358
+ ```ruby
359
+ ENV["RACK_ENV"]
360
+ # => "test"
361
+
362
+ Tynn.environment
363
+ # => :test
364
+ ```
365
+
366
+ If `ENV["RACK_ENV"]` is `nil`, the default value is `:development`.
367
+
368
+ ```ruby
369
+ Tynn.environment
370
+ # => :development
371
+ ```
372
+
373
+ To change the current environment, use the `environment=` method.
374
+
375
+ ```ruby
376
+ Tynn.environment = :development
377
+
378
+ Tynn.environment
379
+ # => :development
380
+ ```
381
+
382
+ To check the current environment, use: `development?`, `test?`,
383
+ `production?` or `staging?`.
384
+
385
+ ```ruby
386
+ Tynn.plugin(Tynn::SSL) if Tynn.production?
387
+ ```
388
+
389
+ Perform operations on specific environments with the `configure` method.
390
+
391
+ ```ruby
392
+ Tynn.configure(:development) do |app|
393
+ app.use(Tynn::Static, %w(/js /css /images))
394
+ end
395
+
396
+ Tynn.configure(:production) do |app|
397
+ app.use(Tynn::SSL)
398
+ end
399
+ ```
400
+
401
+ ### Method Override
402
+
403
+ HTML Forms only support GET and POST requests. To perform other actions such as PUT, PATCH or DELETE, use the [Rack::MethodOverride] middleware. Note that there is no need to add any new dependencies to the application as it's included in Rack already.
404
+
405
+ ```ruby
406
+ Tynn.use(Rack::MethodOverride)
407
+ ```
408
+
409
+ This uses a POST form to simulate a request with a non-supported method. In order to succeed, a hidden input field, with the name `_method` and the method name as the value, needs to be included. The following example simulates a PUT
410
+ request.
411
+
412
+ ```html
413
+ <form method="POST" action="/posts/1">
414
+ <input type="hidden" name="_method" value="PUT">
415
+ <!-- ... -->
416
+ </form>
417
+ ```
418
+
419
+ Now, this will trigger the `put` matcher in the application.
420
+
421
+ ```ruby
422
+ Posts.define do
423
+ put do
424
+ post.update(req.params["post"])
425
+ end
426
+ end
427
+ ```
428
+
429
+ ### Static Files
430
+
431
+ Tynn ships with [Tynn::Static] to serve static files such as images, CSS, JavaScript and others.
432
+
433
+ ```ruby
434
+ require "tynn"
435
+ require "tynn/static"
436
+
437
+ Tynn.plugin(Tynn::Static, %w(/js /css /images))
438
+ ```
439
+
440
+ By default, static files are served from the folder `public` in the current directory. You can specify a different location by passing the `:root` option:
441
+
442
+ ```ruby
443
+ Tynn.plugin(Tynn::Static, %w(/js /css /images), root: "assets")
444
+ ```
445
+
446
+ As you can see in the table below, the name of static directory is not included in the URL because the files are looked up relative to that directory.
447
+
448
+
449
+ | File | URL |
450
+ | ---------------------------- | -------------------------------------- |
451
+ | ./public/js/application.js | http://example.org/js/application.js |
452
+ | ./public/css/application.css | http://example.org/css/application.css |
453
+ | ./public/images/logo.png | http://example.org/images/logo.png |
454
+
455
+ It's important to mention that the path of the static directory path is relative to the directory where you run the application. If you run the application from another directory, it's safer to use an absolute path:
456
+
457
+ ```ruby
458
+ Tynn.plugin(
459
+ Tynn::Static,
460
+ %w(/js /css /images),
461
+ root: File.expand_path("public", __dir__)
462
+ )
463
+ ```
464
+
465
+ ## Security
466
+
467
+ ## Testing
468
+
469
+ Tynn ships with [Tynn::Test], a simple helper class to simulate requests to your application.
470
+
471
+ ```ruby
472
+ require "tynn"
473
+ require "tynn/test"
474
+
475
+ Tynn.define do
476
+ root do
477
+ res.write("hei")
478
+ end
479
+ end
480
+
481
+ app = Tynn::Test.new
482
+ app.get("/")
483
+
484
+ 200 == app.res.status # => true
485
+ "hei" == app.res.body # => true
486
+ ```
487
+
488
+ [Tynn::Test] is test-framework agnostic. The following example uses [Minitest]:
489
+
490
+ ```ruby
491
+ require "minitest/autorun"
492
+ require "tynn/test"
493
+
494
+ class GuestsRouteTest < Minitest::Test
495
+ def setup
496
+ @app = Tynn::Test.new
497
+ end
498
+
499
+ def test_home
500
+ @app.get("/")
501
+
502
+ assert_equal 200, @app.res.status
503
+ assert_equal "Hello World!", @app.res.body
504
+ assert_equal "text/html", @app.res["Content-Type"]
505
+ end
506
+ end
507
+ ```
508
+
509
+ If this is not of your flavor, you can use any Rack-based testing library or framework, like: [Rack::Test] or [Capybara].
510
+
511
+ ## Changelog
512
+
513
+ To learn about new features, bug fixes, and changes, please refer to the [CHANGELOG](https://github.com/frodsan/tynn/blob/master/CHANGELOG.md).
514
+
515
+ ## Development
516
+
517
+ Fork the project with:
518
+
519
+ ```
520
+ $ git clone git@github.com:frodsan/tynn.git
521
+ ```
522
+
523
+ To install dependencies, use:
524
+
525
+ ```
526
+ $ bundle install
527
+ ```
528
+
529
+ To run the test suite, do:
530
+
531
+ ```
532
+ $ rake test
533
+ ```
31
534
 
32
- Documentation
33
- -------------
535
+ ## Contributing
34
536
 
35
- See our website: <http://tynn.xyz/>.
537
+ Use [GitHub Issues](https://github.com/frodsan/tynn/issues) for reporting bugs, discussing features and general feedback. If you've found a problem in Tynn, be sure to check the [past issues](https://github.com/frodsan/tynn/issues?state=closed) before open a new one.
36
538
 
37
- Contributing
38
- ------------
539
+ ## Build History
39
540
 
40
- Please see the [CONTRIBUTING][contributing] file for more information.
541
+ [![Build History](https://buildstats.info/travisci/chart/frodsan/tynn?branch=master)](https://travis-ci.org/frodsan/tynn/builds)
41
542
 
42
- License
43
- -------
543
+ ## License
44
544
 
45
- Tynn is released under the [MIT License][mit].
545
+ Tynn is released under the [MIT License](http://www.opensource.org/licenses/MIT).
46
546
 
47
- [contributing]: https://github.com/frodsan/tynn/blob/master/CONTRIBUTING.md
48
- [mit]: http://www.opensource.org/licenses/MIT
49
- [start]: http://tynn.xyz/getting-started.html
547
+ [bundler]: http://bundler.io/
548
+ [capybara]: https://github.com/jnicklas/capybara
549
+ [cuba]: http://cuba.is/
550
+ [minitest]: https://github.com/seattlerb/minitest
551
+ [puma]: http://puma.io/
552
+ [rack]: http://rack.github.io/
553
+ [rack::test]: https://github.com/brynary/rack-test
554
+ [rack::methodoverride]: http://www.rubydoc.info/github/rack/rack/Rack/MethodOverride
555
+ [rails]: http://rubyonrails.org/
556
+ [sinatra]: http://www.sinatrarb.com/
50
557
  [syro]: http://soveran.github.io/syro/
558
+ [thin]: http://code.macournoyer.com/thin/
559
+ [tynn::environment]: http://api.tynn.xyz/2.0.0/Tynn/Environment.html
560
+ [tynn::json]: http://api.tynn.xyz/2.0.0/Tynn/JSON.html
561
+ [tynn::render]: http://api.tynn.xyz/2.0.0/Tynn/Render.html
562
+ [tynn::session]: http://api.tynn.xyz/2.0.0/Tynn/Session.html
563
+ [tynn::static]: http://api.tynn.xyz/2.0.0/Tynn/Static.html
564
+ [tynn::test]: http://api.tynn.xyz/2.0.0/Tynn/Test.html
565
+ [unicorn]: https://unicorn.bogomips.org/