kawaii-core 0.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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +42 -0
- data/LICENSE.txt +21 -0
- data/README.md +372 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/examples/controller.ru +30 -0
- data/examples/hello_world.rb +5 -0
- data/examples/hello_world.ru +4 -0
- data/examples/modular.ru +11 -0
- data/examples/modular/first_app.rb +6 -0
- data/examples/modular/second_app.rb +6 -0
- data/examples/nested_routes.rb +11 -0
- data/examples/views.ru +10 -0
- data/examples/views/index.html.erb +1 -0
- data/kawaii-core.gemspec +34 -0
- data/lib/kawaii.rb +17 -0
- data/lib/kawaii/base.rb +48 -0
- data/lib/kawaii/controller.rb +32 -0
- data/lib/kawaii/core_ext/hash.rb +23 -0
- data/lib/kawaii/core_ext/string.rb +6 -0
- data/lib/kawaii/matchers.rb +135 -0
- data/lib/kawaii/method_chain.rb +15 -0
- data/lib/kawaii/render_methods.rb +14 -0
- data/lib/kawaii/route.rb +27 -0
- data/lib/kawaii/route_context.rb +49 -0
- data/lib/kawaii/route_handler.rb +54 -0
- data/lib/kawaii/route_mapping.rb +35 -0
- data/lib/kawaii/routing_methods.rb +120 -0
- data/lib/kawaii/server_methods.rb +33 -0
- data/lib/kawaii/singleton_app.rb +58 -0
- data/lib/kawaii/version.rb +4 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 95acd16e37137a291448035f6d07d4e57fd176a8
|
4
|
+
data.tar.gz: 59e1181f5923fe52949358ef933b54979fd9e97c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 82bc0bf00758bfc60a1659c6cf97e7de0a9252a1538a43ea8060b5742cc7d90dc6a146342c51c4fc1a046fd146904ae10c141f74d2a3d3bfbab090c8b24d0c1b
|
7
|
+
data.tar.gz: aae617e17cbc4c848d24c02f9d0aadfc6840d3986fcc79934f2811686d40843386d9a5d246aced280736cc29e20f02966ab892c2a02fa2229a4e7e4443970e42
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
28
|
+
require 'guard/rspec/dsl'
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Martin Bilski
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,372 @@
|
|
1
|
+
|
2
|
+
# Kawaii
|
3
|
+
|
4
|
+
Kawaii is a simple web framework based on Rack.
|
5
|
+
|
6
|
+
** This is work in progress. The API is subject to change. **
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'kawaii-core'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install kawaii-core
|
23
|
+
|
24
|
+
## Running examples
|
25
|
+
|
26
|
+
The `/examples` directory contains various basic usage examples.
|
27
|
+
|
28
|
+
Run the examples using rackup or directly:
|
29
|
+
|
30
|
+
```
|
31
|
+
$ cd examples
|
32
|
+
$ rackup -r kawaii modular.ru
|
33
|
+
```
|
34
|
+
|
35
|
+
Many examples can also be run directly without rackup, e.g.:
|
36
|
+
|
37
|
+
```
|
38
|
+
$ cd examples
|
39
|
+
$ ruby -r kawaii hello_world.rb
|
40
|
+
|
41
|
+
## Getting started
|
42
|
+
|
43
|
+
Kawaii's basic usage is very similar how you'd use Sinatra. You can define route handlers at the file scope. Here's an example:
|
44
|
+
|
45
|
+
```
|
46
|
+
require 'kawaii'
|
47
|
+
|
48
|
+
get '/' do
|
49
|
+
'Hello, world!'
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Save it to `hello.rb` and start the server like this:
|
54
|
+
|
55
|
+
```
|
56
|
+
$ rackup -r kawaii hello.rb --port 8088
|
57
|
+
```
|
58
|
+
|
59
|
+
Then navigate to `http://localhost:8088` to see the greeting.
|
60
|
+
|
61
|
+
## Using rackup
|
62
|
+
|
63
|
+
To run the app you created in the "Getting started" section above using rackup, create the following `hello.ru` file:
|
64
|
+
|
65
|
+
```
|
66
|
+
require 'kawaii'
|
67
|
+
require_relative 'hello'
|
68
|
+
|
69
|
+
run Kawaii::SingletonApp
|
70
|
+
```
|
71
|
+
|
72
|
+
`SingletonApp` contains all routes defined at the file scope.
|
73
|
+
|
74
|
+
## Defining routes
|
75
|
+
|
76
|
+
There are several methods you can use to build your routes, handle passed parameters and so on.
|
77
|
+
|
78
|
+
### Supported HTTP methods
|
79
|
+
|
80
|
+
The basic way to add a route handler is to invoke a method corresponding to the given HTTP verb, e.g.:
|
81
|
+
|
82
|
+
```
|
83
|
+
post '/users' do
|
84
|
+
# Some response
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
Here, the `post` method corresponds to the `POST` HTTP verb.
|
89
|
+
|
90
|
+
Here's a list of supported HTTP verbs:
|
91
|
+
|
92
|
+
- get
|
93
|
+
- post
|
94
|
+
- put
|
95
|
+
- patch
|
96
|
+
- delete
|
97
|
+
- head
|
98
|
+
- options
|
99
|
+
- link
|
100
|
+
- unlink
|
101
|
+
- trace
|
102
|
+
|
103
|
+
### Wildcard matching
|
104
|
+
|
105
|
+
Patterns in route definitions may contain wildcard characters `*` and `?`.
|
106
|
+
|
107
|
+
For example `get '/users/?'` matches both `/users/` and `/users` while `get '/users/*'` will match any path starting with '/users/' e.g. '/users/foo/bar'.
|
108
|
+
|
109
|
+
### Parameters
|
110
|
+
|
111
|
+
Route patterns may contain named parameters, prefixed with a colon. Parameters are accessible through the `params` hash in handler:
|
112
|
+
|
113
|
+
```
|
114
|
+
get '/users/:id' do
|
115
|
+
params[:id]
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
(When requested with `/users/123`, the above route handler will render `"123"`.)
|
120
|
+
|
121
|
+
### Regular expressions
|
122
|
+
|
123
|
+
Route patterns may contain regular expressions. Example:
|
124
|
+
|
125
|
+
```
|
126
|
+
get %r{/users/.*} do
|
127
|
+
'Hello, world'
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
### Nested routes
|
132
|
+
|
133
|
+
Routes may be nested using the `context` method. Example:
|
134
|
+
|
135
|
+
```
|
136
|
+
context '/api' do
|
137
|
+
get '/users' do
|
138
|
+
'Hello'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
Will above handler will be accessible through `/api/users`.
|
144
|
+
|
145
|
+
### Custom matchers
|
146
|
+
|
147
|
+
If string patterns and regular expression are not flexible enough, you can create a custom matcher.
|
148
|
+
|
149
|
+
A matcher instance responds to `match` method and returns either a `Match` instance or nil if there's no match. See documentation for {Matcher#match} for more details.
|
150
|
+
|
151
|
+
### Request object
|
152
|
+
|
153
|
+
Handlers can access the `Rack::Request` instance corresponding to the current request:
|
154
|
+
|
155
|
+
```
|
156
|
+
get '/' do
|
157
|
+
request.host
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### View templates
|
162
|
+
|
163
|
+
View templates must currently be stored in `views/` directory of the project using Kawaii. They can be rendered using the `render` method:
|
164
|
+
|
165
|
+
```
|
166
|
+
get '/' do
|
167
|
+
render('index.html.erb')
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
You can set instance variables and use them in the templates.
|
172
|
+
|
173
|
+
```
|
174
|
+
get '/' do
|
175
|
+
@title = 'Hello, world'
|
176
|
+
render('index.html.erb')
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
Let's say `views/index.html.erb` looks like this:
|
181
|
+
|
182
|
+
```
|
183
|
+
<h1><%= @title %></h1>
|
184
|
+
```
|
185
|
+
|
186
|
+
In that case, when you visit the page, you'll see **Hello, world**.
|
187
|
+
|
188
|
+
Supported templating engines include: ERB, Haml, Liquid, Builder, Kramdown and others. Note that you may need to include the specific gem implementing the given templating engine as inferred from the file name of the template.
|
189
|
+
|
190
|
+
## Modular apps
|
191
|
+
|
192
|
+
For building more complex applications, you can split them into separate classes, each implementing a subset of functionality (e.g. website and an API).
|
193
|
+
|
194
|
+
To create an application, inherit from `Kawaii::Base` and define your routes inside the class.
|
195
|
+
|
196
|
+
Let's create `website.rb`:
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
require 'kawaii'
|
200
|
+
|
201
|
+
class Website < Kawaii::Base
|
202
|
+
get '/' do
|
203
|
+
'Hello, world'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
Now here's how `api.rb` may look like:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
require 'kawaii'
|
212
|
+
|
213
|
+
class API < Kawaii::Base
|
214
|
+
get '/info' do
|
215
|
+
'This is some information'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
Let's use the apps in a `config.ru`:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
require 'kawaii'
|
224
|
+
require_relative 'website'
|
225
|
+
require_relative 'api'
|
226
|
+
|
227
|
+
map '/' do
|
228
|
+
run Website
|
229
|
+
end
|
230
|
+
|
231
|
+
map '/api' do
|
232
|
+
run API
|
233
|
+
end
|
234
|
+
```
|
235
|
+
|
236
|
+
## Model-view-controller apps
|
237
|
+
|
238
|
+
Kawaii supports routing to controllers by either specifying the specific controller + action for a given route or by creating automatic Restful resources (via `route`).
|
239
|
+
|
240
|
+
Let's suppose we have a controller in `hello_world.rb` has typical CRUD methods that mimick Rails controllers:
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
class HelloWorld < Kawaii::Controller
|
244
|
+
def index
|
245
|
+
'Hello, world'
|
246
|
+
end
|
247
|
+
end
|
248
|
+
```
|
249
|
+
|
250
|
+
An in `users.rb`:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
class Users < Kawaii::Controller
|
254
|
+
def index
|
255
|
+
'GET /users'
|
256
|
+
end
|
257
|
+
|
258
|
+
def show
|
259
|
+
"GET /users/#{params[:id]}"
|
260
|
+
end
|
261
|
+
|
262
|
+
def create
|
263
|
+
'POST /users'
|
264
|
+
end
|
265
|
+
|
266
|
+
def update
|
267
|
+
"PATCH /users/#{params[:id]}"
|
268
|
+
end
|
269
|
+
|
270
|
+
def destroy
|
271
|
+
"DELETE /users/#{params[:id]}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
276
|
+
Here's how we can define routes (in `app.rb`):
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
require 'kawaii'
|
280
|
+
require_relative 'hello_world'
|
281
|
+
require_relative 'users'
|
282
|
+
|
283
|
+
get '/', 'hello_world#index' # Explicitly route to `HelloWorld#index` to show the welcome page
|
284
|
+
|
285
|
+
route '/users', 'users'
|
286
|
+
```
|
287
|
+
|
288
|
+
You can run the app directly using `ruby` or create `config.ru`:
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
require_relative 'app.rb'
|
292
|
+
|
293
|
+
run Kawaii::SingletonApp
|
294
|
+
```
|
295
|
+
|
296
|
+
Of course, you can
|
297
|
+
|
298
|
+
## Testing
|
299
|
+
|
300
|
+
I recommend using `Rack::Test` for testing (see [here](https://github.com/brynary/rack-test)). Look at specs in `spec/` to see how you can use it.
|
301
|
+
|
302
|
+
To make a long story short, a class deriving from `Kawaii::Base` containing your routes is `app`. Let's suppose, your app class is `MyApp`, here's how you could test it:
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
describe MyApp
|
306
|
+
let(:app) { MyApp }
|
307
|
+
it 'renders home page' do
|
308
|
+
get '/'
|
309
|
+
expect(last_response).to be_ok
|
310
|
+
end
|
311
|
+
end
|
312
|
+
```
|
313
|
+
|
314
|
+
## Resources
|
315
|
+
|
316
|
+
See `/examples`
|
317
|
+
### Reference
|
318
|
+
|
319
|
+
## Contributing
|
320
|
+
|
321
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bilus/kawaii.
|
322
|
+
|
323
|
+
|
324
|
+
## License
|
325
|
+
|
326
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
327
|
+
|
328
|
+
|
329
|
+
## TODO
|
330
|
+
|
331
|
+
+ Hello world app.
|
332
|
+
+ Specs for the app.
|
333
|
+
+ GET routes inside a class deriving from Base.
|
334
|
+
+ Support for running apps without config.ru (ruby -I ./lib examples/hello_world.rb
|
335
|
+
+ Top-level routes.
|
336
|
+
+ Example for top-level routes.
|
337
|
+
+ Nested routes.
|
338
|
+
+ Modular apps (multiple modules via config.ru).
|
339
|
+
+ Matchers.
|
340
|
+
+ Wildcard regex routes, e.g. '/foo/bar/?'.
|
341
|
+
+ Parameter-based routes. Unsupported in 'context'.
|
342
|
+
+ Request object.
|
343
|
+
+ Merge Rack Request params.
|
344
|
+
+ String responses.
|
345
|
+
+ Other HTTP verbs.
|
346
|
+
+ Refactor & create individual files.
|
347
|
+
+ Views (via `render` method in handlers) using Tilt.
|
348
|
+
+ Rack route test helpers work.
|
349
|
+
+ API reference.
|
350
|
+
+ Check: References to methods defined in contexts and at class scope.
|
351
|
+
+ Controllers - 'hello_world#index'
|
352
|
+
+ 'route' to controllers (via class name or symbol references).
|
353
|
+
+ Controllers - render.
|
354
|
+
|
355
|
+
- Readme - description and tutorial.
|
356
|
+
- Rubocop-compliant.
|
357
|
+
- Push gem.
|
358
|
+
|
359
|
+
- Example project using the gem and controllers (with views).
|
360
|
+
|
361
|
+
- Rack/custom global middleware.
|
362
|
+
- Route-specific middleware.
|
363
|
+
- Custom error handling (intercept exceptions, 404 what else?).
|
364
|
+
- Code review
|
365
|
+
|
366
|
+
## Known issues
|
367
|
+
|
368
|
+
### Rubocop
|
369
|
+
|
370
|
+
`lib/kawaii/routing_methods.rb:46:1: C: Extra blank line detected.`
|
371
|
+
|
372
|
+
The extra line is necessary for Yard to ignore the comment. Adjust Rubocop settings.
|