ki 0.4.1 → 0.4.2

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +224 -15
  4. data/ki.gemspec +1 -2
  5. data/lib/ki.rb +1 -0
  6. data/lib/ki/api_error.rb +7 -2
  7. data/lib/ki/indifferent_hash.rb +11 -0
  8. data/lib/ki/orm.rb +5 -1
  9. data/lib/ki/version.rb +1 -1
  10. data/spec/examples/couch-lock/Gemfile.lock +1 -1
  11. data/spec/examples/couch-lock/app.rb +50 -5
  12. data/spec/examples/couch-lock/public/fonts/FontAwesome.otf +0 -0
  13. data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.eot +0 -0
  14. data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.svg +520 -0
  15. data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.ttf +0 -0
  16. data/spec/examples/couch-lock/public/fonts/fontawesome-webfont.woff +0 -0
  17. data/spec/examples/couch-lock/public/stylesheets/font-awesome.min.css +4 -0
  18. data/spec/examples/couch-lock/public/stylesheets/main.sass +7 -0
  19. data/spec/examples/couch-lock/public/stylesheets/pure-min.css +11 -0
  20. data/spec/examples/couch-lock/views/index.haml +53 -14
  21. data/spec/examples/json.northpole.ro/Gemfile.lock +1 -1
  22. data/spec/examples/json.northpole.ro/app.rb +3 -3
  23. data/spec/examples/todo/.ruby-gemset +1 -0
  24. data/spec/examples/todo/.ruby-version +1 -0
  25. data/spec/examples/todo/Gemfile +4 -0
  26. data/spec/examples/todo/app.rb +11 -0
  27. data/spec/examples/todo/config.ru +3 -0
  28. data/spec/examples/todo/config.yml +17 -0
  29. data/spec/examples/todo/public/favicon.ico +0 -0
  30. data/spec/examples/todo/public/javascripts/.gitkeep +0 -0
  31. data/spec/examples/todo/public/stylesheets/.gitkeep +0 -0
  32. data/spec/examples/todo/views/index.haml +1 -0
  33. data/spec/examples/todo/views/layout.haml +6 -0
  34. data/spec/lib/ki/indifferent_hash_spec.rb +10 -0
  35. metadata +44 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d3882f219cbe5267ace949b299161f8d7088de4
4
- data.tar.gz: dbd684f59faf3cb6ed83dcce014f7f6c024bd4b9
3
+ metadata.gz: fecab0fa4fb36ca609b3858125f8966cb2c83b24
4
+ data.tar.gz: 374608a0b13d1bce947ac0e8d42facc78b7fa5dd
5
5
  SHA512:
6
- metadata.gz: 906832115b4f414a7c78d00ca31bc9bcd4b1a1eb5f7e18e5f341a7794c364b6caf2738b9ae123b6a4afbca4d0328342512c66e3e38e920cacdf4fc34806015db
7
- data.tar.gz: 54f9f057d005f7ce0697b4584b3af94ceb5f0bcfdccb5d14282d19f1eeaa61dc9ceeb70a0c0179ded589898ca015f02b5ecc59b78e0e3628b9a8ce47e737af53
6
+ metadata.gz: 142a52569d62b87646811ee4f2ab16d7dc397427f495aaca1a8369d2d3632d7bd4f91fd50623114a94b8d57e265faf142b70fa29a6f1a719f3b1f9d9a8e16681
7
+ data.tar.gz: a75db7d74e8e7e816efa78ea57a573a613285e8bbea0f844f7006f69256ebc3e9136c46b035fac074d938ff36597ae8271cbcf32a6c68fd61d5ea65af425a074
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ki (0.4.1)
4
+ ki (0.4.2)
5
5
  bson_ext
6
6
  bundler (~> 1.5)
7
7
  coffee-script
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
- * rvm
6
- * mongodb
7
- * haml
8
- * sass
9
- * coffee
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 my-app
23
- cd my-app
24
- bundle
53
+ ki new todo
25
54
  ```
26
55
 
27
- This will create the folder *my-app* containing a bare bones ki application.
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
- TODO
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
- TODO
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
- TODO
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
- ### Before/after filters
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
- TODO
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
@@ -19,6 +19,7 @@ require 'ki/modules/view_helper'
19
19
  require 'ki/modules/format_of'
20
20
  require 'ki/modules/public_file_helper'
21
21
 
22
+ require 'ki/indifferent_hash'
22
23
  require 'ki/ki_config'
23
24
  require 'ki/helpers'
24
25
  require 'ki/orm'
@@ -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 'action forbidden', 400
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
@@ -0,0 +1,11 @@
1
+ class IndifferentHash < Hash
2
+ def []=(key,val)
3
+ key = key.to_sym
4
+ super(key, val)
5
+ end
6
+
7
+ def [](*args)
8
+ args[0] = args[0].to_sym
9
+ super(*args)
10
+ end
11
+ end
@@ -9,7 +9,11 @@ module Ki
9
9
 
10
10
  def establish_connection
11
11
  @config = KiConfig.instance.database
12
- @connection = Mongo::Connection.new(@config['host'], @config['port'])
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
@@ -1,3 +1,3 @@
1
1
  module Ki
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../../..
3
3
  specs:
4
- ki (0.4.0)
4
+ ki (0.4.1)
5
5
  bson_ext
6
6
  bundler (~> 1.5)
7
7
  coffee-script
@@ -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
- `disper -#{params["q"]}`
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
- `killall -9 vlc`
52
+ run "killall -9 vlc"
23
53
  else
24
- `vlc https://www.youtube.com/watch?v=rH79BmeeM0o --fullscreen`
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
- `pacmd set-default-sink alsa_output.pci-0000_00_1b.0.analog-stereo`
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
- `pacmd set-default-sink alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1`
84
+ run `kill \`ps ax | grep lockserver.UDPServer | grep -v grep | awk '{ print $1 }'\``
40
85
  end
41
86
  end
42
87
  end