ki 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +224 -15
- data/ki.gemspec +1 -2
- data/lib/ki.rb +1 -0
- data/lib/ki/api_error.rb +7 -2
- data/lib/ki/indifferent_hash.rb +11 -0
- data/lib/ki/orm.rb +5 -1
- data/lib/ki/version.rb +1 -1
- data/spec/examples/couch-lock/Gemfile.lock +1 -1
- data/spec/examples/couch-lock/app.rb +50 -5
- data/spec/examples/couch-lock/public/fonts/FontAwesome.otf +0 -0
- data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.eot +0 -0
- data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.svg +520 -0
- data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.ttf +0 -0
- data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.woff +0 -0
- data/spec/examples/couch-lock/public/stylesheets/font-awesome.min.css +4 -0
- data/spec/examples/couch-lock/public/stylesheets/main.sass +7 -0
- data/spec/examples/couch-lock/public/stylesheets/pure-min.css +11 -0
- data/spec/examples/couch-lock/views/index.haml +53 -14
- data/spec/examples/json.northpole.ro/Gemfile.lock +1 -1
- data/spec/examples/json.northpole.ro/app.rb +3 -3
- data/spec/examples/todo/.ruby-gemset +1 -0
- data/spec/examples/todo/.ruby-version +1 -0
- data/spec/examples/todo/Gemfile +4 -0
- data/spec/examples/todo/app.rb +11 -0
- data/spec/examples/todo/config.ru +3 -0
- data/spec/examples/todo/config.yml +17 -0
- data/spec/examples/todo/public/favicon.ico +0 -0
- data/spec/examples/todo/public/javascripts/.gitkeep +0 -0
- data/spec/examples/todo/public/stylesheets/.gitkeep +0 -0
- data/spec/examples/todo/views/index.haml +1 -0
- data/spec/examples/todo/views/layout.haml +6 -0
- data/spec/lib/ki/indifferent_hash_spec.rb +10 -0
- metadata +44 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fecab0fa4fb36ca609b3858125f8966cb2c83b24
|
4
|
+
data.tar.gz: 374608a0b13d1bce947ac0e8d42facc78b7fa5dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 142a52569d62b87646811ee4f2ab16d7dc397427f495aaca1a8369d2d3632d7bd4f91fd50623114a94b8d57e265faf142b70fa29a6f1a719f3b1f9d9a8e16681
|
7
|
+
data.tar.gz: a75db7d74e8e7e816efa78ea57a573a613285e8bbea0f844f7006f69256ebc3e9136c46b035fac074d938ff36597ae8271cbcf32a6c68fd61d5ea65af425a074
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,37 @@
|
|
1
1
|
# Ki Framework
|
2
2
|
|
3
|
-
Tiny REST JSON ORM framework
|
3
|
+
Tiny REST JSON ORM framework.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
Ki's goal is to help you protoype your ideas blazing fast. It has a db backend
|
6
|
+
and provides a fullblown REST api on top.
|
7
|
+
|
8
|
+
## TLDR
|
9
|
+
|
10
|
+
To create an api endpoint '/todo.json' with GET/POST/PATCH and restricting
|
11
|
+
DELETE, with title and description as required attributes, with db backend,
|
12
|
+
with a unique title, and before/after filters you would need to write:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
class Todo < Ki::Model
|
16
|
+
requires :title, :description
|
17
|
+
unique :title
|
18
|
+
forbid :delete
|
19
|
+
|
20
|
+
def before_all
|
21
|
+
puts 'hello'
|
22
|
+
end
|
23
|
+
|
24
|
+
def before_create
|
25
|
+
params['created_at'] = Time.now.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def after_find
|
29
|
+
if result['keywords'].include? 'food'
|
30
|
+
puts 'yummy'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
10
35
|
|
11
36
|
## Install
|
12
37
|
|
@@ -16,20 +41,42 @@ gem install ki
|
|
16
41
|
|
17
42
|
## Getting started
|
18
43
|
|
44
|
+
Learn by example. We will create the traditional 'hello world' app for web
|
45
|
+
development: the dreaded TODO app.
|
46
|
+
|
47
|
+
View the [code](https://github.com/mess110/ki/tree/master/spec/examples/todo) for
|
48
|
+
the final webapp.
|
49
|
+
|
19
50
|
### Creating a new app
|
20
51
|
|
21
52
|
```shell
|
22
|
-
ki new
|
23
|
-
cd my-app
|
24
|
-
bundle
|
53
|
+
ki new todo
|
25
54
|
```
|
26
55
|
|
27
|
-
This will create the folder *
|
56
|
+
This will create the folder *todo* containing a bare bones ki application. Your
|
57
|
+
app will look [like this](https://github.com/mess110/ki/tree/master/spec/examples/base).
|
58
|
+
|
59
|
+
App directory structure:
|
60
|
+
|
61
|
+
* public/
|
62
|
+
* javascripts/
|
63
|
+
* stylesheets/
|
64
|
+
* views/
|
65
|
+
* app.rb
|
66
|
+
* config.yml
|
67
|
+
|
68
|
+
The entry point for the app is *app.rb*. You will add most of your code there.
|
69
|
+
Views are in the *views* folder and you can find some database info in
|
70
|
+
*config.yml*.
|
28
71
|
|
29
72
|
```shell
|
73
|
+
cd todo
|
74
|
+
bundle
|
30
75
|
rackup
|
31
76
|
```
|
32
77
|
|
78
|
+
*rackup* is the command which starts the webserver. The port will be displayed.
|
79
|
+
|
33
80
|
### Adding a view
|
34
81
|
|
35
82
|
A view is a html page. By default, a view called 'index.haml' is created for
|
@@ -48,16 +95,178 @@ similar to haml.
|
|
48
95
|
|
49
96
|
### View layout
|
50
97
|
|
51
|
-
|
98
|
+
If the file *views/layout.haml* exists, it will be used as a layout for all the
|
99
|
+
other haml files. The content of the route will be placed in the layout *yield*
|
100
|
+
|
101
|
+
*views/layout.haml*
|
102
|
+
|
103
|
+
```haml
|
104
|
+
!!!
|
105
|
+
%html
|
106
|
+
%head
|
107
|
+
%title Ki Framework
|
108
|
+
%body
|
109
|
+
= yield
|
110
|
+
```
|
111
|
+
|
112
|
+
*views/index.haml*
|
113
|
+
|
114
|
+
```haml
|
115
|
+
%p Hello World!
|
116
|
+
```
|
117
|
+
|
118
|
+
### Helpers
|
119
|
+
|
120
|
+
To reduce complexity in your views, you can use helpers. Here we create a
|
121
|
+
*say_hello* method which we can use in *views/index.haml*.
|
122
|
+
|
123
|
+
*app.rb*
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
module Ki::Helpers
|
127
|
+
def say_hello
|
128
|
+
'hello'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
*views/index.haml*
|
134
|
+
|
135
|
+
```haml
|
136
|
+
%p= say_hello
|
137
|
+
```
|
52
138
|
|
53
139
|
### Adding a resource
|
54
140
|
|
55
|
-
|
141
|
+
Think of resources as the M in MVC. Except they also have routes attached.
|
142
|
+
All resources must inherit from Ki::Model. For example, to create a todo model
|
143
|
+
add the fallowing snippet to *app.rb*
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
class Todo < Ki::Model
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
This will create the Todo resource and its corresponding routes. Each route is
|
151
|
+
mapped to a model method.
|
152
|
+
|
153
|
+
Method name | Verb | HTTP request|Required params|
|
154
|
+
------------|------|-------------|---------------|
|
155
|
+
find |GET | /todo.json | |
|
156
|
+
create |POST | /todo.json | |
|
157
|
+
update |PATCH | /todo.json |id |
|
158
|
+
delete |DELETE| /todo.json |id |
|
159
|
+
|
160
|
+
Below is a curl example for creating a todo item. Notice the data sent in the
|
161
|
+
body request is a JSON string. It can take the shape of any valid JSON object.
|
162
|
+
All json objects will be stored in the database under the resource name. In our
|
163
|
+
case *todo*.
|
164
|
+
|
165
|
+
#### Create
|
166
|
+
|
167
|
+
```shell
|
168
|
+
curl -X POST -d '{"title": "make a todo tutorial"}' http://localhost:9292/todo.json
|
169
|
+
```
|
170
|
+
|
171
|
+
#### Get all
|
172
|
+
|
173
|
+
```shell
|
174
|
+
curl -X GET http://localhost:9292/todo.json
|
175
|
+
```
|
176
|
+
|
177
|
+
#### Get by id
|
178
|
+
|
179
|
+
```shell
|
180
|
+
curl -X GET http://localhost:9292/todo.json?id=ITEM_ID
|
181
|
+
```
|
182
|
+
|
183
|
+
#### Update
|
184
|
+
|
185
|
+
```shell
|
186
|
+
curl -X PATCH -d '{"id": "ITEM_ID", "title": "finish the todo tutorial"}' http://localhost:9292/todo.json
|
187
|
+
```
|
188
|
+
|
189
|
+
#### Delete
|
190
|
+
|
191
|
+
```shell
|
192
|
+
curl -X DELETE -d http://localhost:9292/todo.json?id=ITEM_ID
|
193
|
+
```
|
194
|
+
|
195
|
+
### Required attributes
|
196
|
+
|
197
|
+
You can add mandatory attributes on resources with the *requires* method. It
|
198
|
+
takes one parameter or an array of parameters as an argument.
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
class Todo < Ki::Model
|
202
|
+
requires :title
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
This will make sure a Todo item can not be saved or updated in the database
|
207
|
+
without a title attribute.
|
56
208
|
|
57
209
|
### Restricting resource requests
|
58
210
|
|
59
|
-
|
211
|
+
Let's say you want to forbid access to deleting items. You can do that with
|
212
|
+
the *forbid* method.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
class Todo < Ki::Model
|
216
|
+
forbid :delete
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
### Before/after callbacks
|
221
|
+
|
222
|
+
The framework has [these callbacks](https://github.com/mess110/ki/blob/master/lib/ki/modules/callbacks.rb).
|
223
|
+
Here is an example on how to use them:
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
class Todo < Ki::Model
|
227
|
+
def before_create
|
228
|
+
# do your stuff
|
229
|
+
end
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
#### Accessing the json object within a callback
|
234
|
+
|
235
|
+
Before the request is sent to the client, you can look at the result through
|
236
|
+
the *result* method. Modifying it will change what the client receives.
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
class Todo < Ki::Model
|
240
|
+
def after_find
|
241
|
+
puts result
|
242
|
+
end
|
243
|
+
end
|
244
|
+
```
|
245
|
+
|
246
|
+
### Exceptions
|
247
|
+
|
248
|
+
A list of exceptions can be found [here](https://github.com/mess110/ki/blob/master/lib/ki/api_error.rb)
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
class Todo < Ki::Model
|
252
|
+
def before_all
|
253
|
+
ensure_authroization
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
|
258
|
+
def ensure_authorization
|
259
|
+
if params[:key] = 'secret-key'
|
260
|
+
raise UnauthorizedError.new
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
```
|
265
|
+
|
266
|
+
## Deploy
|
60
267
|
|
61
|
-
|
268
|
+
It has a *config.ru* file. Ki is based on *rack*. You can deploy anywhere (ex:
|
269
|
+
nginx, thin, apache, webrick).
|
62
270
|
|
63
|
-
|
271
|
+
In the webserver config, just remember to point the virtual host to the
|
272
|
+
*public* directory.
|
data/ki.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["mess110@gmail.com"]
|
11
11
|
spec.summary = %q{it said optional}
|
12
12
|
spec.description = %q{it said optional}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/mess110/ki"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -28,7 +28,6 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_runtime_dependency "mongo"
|
29
29
|
spec.add_runtime_dependency "bson_ext"
|
30
30
|
|
31
|
-
|
32
31
|
spec.add_development_dependency "rake"
|
33
32
|
spec.add_development_dependency "rack-test"
|
34
33
|
spec.add_development_dependency "rspec"
|
data/lib/ki.rb
CHANGED
data/lib/ki/api_error.rb
CHANGED
@@ -16,8 +16,13 @@ module Ki
|
|
16
16
|
class RequiredAttributeMissing < ApiError; end
|
17
17
|
class AttributeNotUnique < ApiError; end
|
18
18
|
class ForbiddenAction < ApiError
|
19
|
-
def initialize
|
20
|
-
super
|
19
|
+
def initialize s='forbidden', code=403
|
20
|
+
super s, code
|
21
|
+
end
|
22
|
+
end
|
23
|
+
class UnauthorizedError < ApiError
|
24
|
+
def initialize s='unauthroized', code=401
|
25
|
+
super s, code
|
21
26
|
end
|
22
27
|
end
|
23
28
|
class PartialNotFoundError < ApiError
|
data/lib/ki/orm.rb
CHANGED
@@ -9,7 +9,11 @@ module Ki
|
|
9
9
|
|
10
10
|
def establish_connection
|
11
11
|
@config = KiConfig.instance.database
|
12
|
-
|
12
|
+
if ENV["MONGODB_URI"]
|
13
|
+
@connection = Mongo::Connection.new
|
14
|
+
else
|
15
|
+
@connection = Mongo::Connection.new(@config['host'], @config['port'])
|
16
|
+
end
|
13
17
|
@db = @connection.db(@config['name'])
|
14
18
|
self
|
15
19
|
end
|
data/lib/ki/version.rb
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
require 'ki'
|
2
2
|
|
3
|
+
def run cmd
|
4
|
+
res = `DISPLAY=:0.0 #{cmd}`
|
5
|
+
puts res
|
6
|
+
res
|
7
|
+
end
|
8
|
+
|
9
|
+
module Ki
|
10
|
+
module Helpers
|
11
|
+
def display_status
|
12
|
+
res = run "xrandr | head -n 1 | awk '{ print $8 }'"
|
13
|
+
res.strip.to_i == 1920 ? 'cloned' : 'extended'
|
14
|
+
end
|
15
|
+
|
16
|
+
def vlc_running?
|
17
|
+
res = run "ps -ef | grep vlc | grep -v grep | head -n 1"
|
18
|
+
res.strip != ""
|
19
|
+
end
|
20
|
+
|
21
|
+
def couch_lock_running?
|
22
|
+
res = run "ps -ef | grep lockserver.UDPServer | grep -v grep | head -n 1"
|
23
|
+
res.strip != ""
|
24
|
+
end
|
25
|
+
|
26
|
+
def sound_output
|
27
|
+
res = run "pactl info | grep 'Default Sink' | grep hdmi"
|
28
|
+
res.strip == "" ? 'analog' : 'hdmi'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
3
33
|
class Monitors < Ki::Model
|
4
34
|
forbid :create, :update, :delete
|
5
35
|
|
@@ -7,7 +37,7 @@ class Monitors < Ki::Model
|
|
7
37
|
return if params["q"].nil?
|
8
38
|
return unless ['c', 'e'].include? params["q"]
|
9
39
|
|
10
|
-
|
40
|
+
run "disper -#{params["q"]}"
|
11
41
|
end
|
12
42
|
end
|
13
43
|
|
@@ -19,9 +49,9 @@ class Fireplace < Ki::Model
|
|
19
49
|
return unless ['kill', 'start'].include? params["q"]
|
20
50
|
|
21
51
|
if params["q"] == "kill"
|
22
|
-
|
52
|
+
run "killall -9 vlc"
|
23
53
|
else
|
24
|
-
|
54
|
+
run "vlc https://www.youtube.com/watch?v=rH79BmeeM0o --fullscreen &"
|
25
55
|
end
|
26
56
|
end
|
27
57
|
end
|
@@ -34,9 +64,24 @@ class Sound < Ki::Model
|
|
34
64
|
return unless ['speakers', 'hdmi'].include? params["q"]
|
35
65
|
|
36
66
|
if params["q"] == "speakers"
|
37
|
-
|
67
|
+
run "pactl set-default-sink alsa_output.pci-0000_00_1b.0.analog-stereo"
|
68
|
+
else
|
69
|
+
run "pactl set-default-sink alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Jrobot < Ki::Model
|
75
|
+
forbid :create, :update, :delete
|
76
|
+
|
77
|
+
def after_find
|
78
|
+
return if params["q"].nil?
|
79
|
+
return unless ['listen', 'kill'].include? params["q"]
|
80
|
+
|
81
|
+
if params["q"] == "listen"
|
82
|
+
run `cd ../../../../CouchLockServer/; ./start.sh`
|
38
83
|
else
|
39
|
-
`
|
84
|
+
run `kill \`ps ax | grep lockserver.UDPServer | grep -v grep | awk '{ print $1 }'\``
|
40
85
|
end
|
41
86
|
end
|
42
87
|
end
|