ki 0.4.10 → 0.4.11

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +16 -8
  3. data/MIDDLEWARE.md +27 -7
  4. data/README.md +45 -2
  5. data/REALTIME.md +48 -0
  6. data/TODO.md +19 -0
  7. data/ki.gemspec +1 -0
  8. data/lib/ki.rb +5 -0
  9. data/lib/ki/base_request.rb +7 -0
  10. data/lib/ki/channel_manager.rb +58 -0
  11. data/lib/ki/ki.rb +1 -0
  12. data/lib/ki/ki_cli.rb +1 -1
  13. data/lib/ki/ki_config.rb +18 -2
  14. data/lib/ki/middleware/api_handler.rb +11 -16
  15. data/lib/ki/middleware/helpers/redirect_to_helper.rb +13 -0
  16. data/lib/ki/middleware/realtime.rb +81 -0
  17. data/lib/ki/model.rb +6 -4
  18. data/lib/ki/modules/restrictions.rb +4 -7
  19. data/lib/ki/orm.rb +38 -2
  20. data/lib/ki/utils/redirect_to_helper.rb +0 -0
  21. data/lib/ki/version.rb +1 -1
  22. data/spec/examples/json.northpole.ro/.bowerrc +3 -0
  23. data/spec/examples/json.northpole.ro/Gemfile +1 -0
  24. data/spec/examples/json.northpole.ro/bower.json +17 -0
  25. data/spec/examples/json.northpole.ro/config.ru +3 -0
  26. data/spec/examples/json.northpole.ro/config.yml +4 -0
  27. data/spec/examples/json.northpole.ro/config.yml.backup +18 -0
  28. data/spec/examples/json.northpole.ro/config/deploy.rb +2 -1
  29. data/spec/examples/json.northpole.ro/config/deploy/production.rb +4 -38
  30. data/spec/examples/json.northpole.ro/public/app/.bowerrc +3 -0
  31. data/spec/examples/json.northpole.ro/public/app/.gitignore +9 -0
  32. data/spec/examples/json.northpole.ro/public/app/.jshintrc +13 -0
  33. data/spec/examples/json.northpole.ro/public/app/.travis.yml +14 -0
  34. data/spec/examples/json.northpole.ro/public/app/LICENSE +22 -0
  35. data/spec/examples/json.northpole.ro/public/app/README.md +82 -0
  36. data/spec/examples/json.northpole.ro/public/app/bower.json +20 -0
  37. data/spec/examples/json.northpole.ro/public/app/e2e/pages/ContactUser.js +22 -0
  38. data/spec/examples/json.northpole.ro/public/app/e2e/pages/UserDetails.js +11 -0
  39. data/spec/examples/json.northpole.ro/public/app/e2e/pages/UserList.js +12 -0
  40. data/spec/examples/json.northpole.ro/public/app/e2e/protractor.conf.js +26 -0
  41. data/spec/examples/json.northpole.ro/public/app/e2e/scenarios/users.js +34 -0
  42. data/spec/examples/json.northpole.ro/public/app/gulpfile.js +104 -0
  43. data/spec/examples/json.northpole.ro/public/app/karma.conf.js +35 -0
  44. data/spec/examples/json.northpole.ro/public/app/package.json +30 -0
  45. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-1.svg +11 -0
  46. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-4.svg +16 -0
  47. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatars.svg +244 -0
  48. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/google_plus.svg +1 -0
  49. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/hangouts.svg +1 -0
  50. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_48px.svg +4 -0
  51. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_exit_48px.svg +4 -0
  52. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_music_note_48px.svg +1 -0
  53. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_note_add_48px.svg +1 -0
  54. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_view_list_48px.svg +1 -0
  55. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/icon.svg +1 -0
  56. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/mail.svg +1 -0
  57. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/manggo.svg +1095 -0
  58. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/menu.svg +4 -0
  59. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/phone.svg +1 -0
  60. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/share.svg +3 -0
  61. data/spec/examples/json.northpole.ro/public/app/src/assets/svg/twitter.svg +1 -0
  62. data/spec/examples/json.northpole.ro/public/app/src/css/app.css +138 -0
  63. data/spec/examples/json.northpole.ro/public/app/src/css/app.css.map +7 -0
  64. data/spec/examples/json.northpole.ro/public/app/src/css/app.sass +145 -0
  65. data/spec/examples/json.northpole.ro/public/app/src/index.html +157 -0
  66. data/spec/examples/json.northpole.ro/public/app/src/js/MainController.coffee +167 -0
  67. data/spec/examples/json.northpole.ro/public/app/src/js/app.coffee +58 -0
  68. data/spec/examples/json.northpole.ro/public/app/src/js/blobs/BlobsController.coffee +115 -0
  69. data/spec/examples/json.northpole.ro/public/app/src/js/blobs/blobs.html +48 -0
  70. data/spec/examples/json.northpole.ro/public/app/src/js/tutorial/tutorial.html +15 -0
  71. data/spec/examples/json.northpole.ro/public/app/src/js/users/UserService.coffee +12 -0
  72. data/spec/examples/json.northpole.ro/public/app/src/js/users/Users.coffee +1 -0
  73. data/spec/examples/json.northpole.ro/public/app/src/js/users/users.html +8 -0
  74. data/spec/examples/json.northpole.ro/public/javascripts/jnorthpole.coffee +40 -7
  75. data/spec/examples/json.northpole.ro/public/javascripts/realtime.coffee +28 -0
  76. data/spec/examples/json.northpole.ro/public/{javascripts/music → music}/angular-youtube-embed.js +0 -0
  77. data/spec/examples/json.northpole.ro/public/music/index.html +126 -0
  78. data/spec/examples/json.northpole.ro/public/music/music.coffee +99 -0
  79. data/spec/examples/json.northpole.ro/public/music/music.sass +63 -0
  80. data/spec/examples/json.northpole.ro/public/stylesheets/app.sass +3 -0
  81. data/spec/examples/json.northpole.ro/views/faq.haml +7 -0
  82. data/spec/examples/json.northpole.ro/views/layout.haml +1 -0
  83. data/spec/examples/json.northpole.ro/views/music.haml +2 -0
  84. data/spec/examples/json.northpole.ro/views/websocket.haml +7 -0
  85. data/spec/lib/ki/channel_manager_spec.rb +82 -0
  86. data/spec/lib/ki/helpers_spec.rb +11 -0
  87. data/spec/lib/ki/ki_config_spec.rb +28 -0
  88. data/spec/lib/ki/middleware/admin_generator_spec.rb +8 -0
  89. data/spec/lib/ki/middleware/init_middleware_spec.rb +21 -0
  90. data/spec/lib/ki/middleware/realtime_spec.rb +96 -0
  91. data/spec/lib/ki/model_spec.rb +28 -7
  92. data/spec/lib/ki/modules/model_helper_spec.rb +31 -0
  93. data/spec/lib/ki/orm_spec.rb +26 -0
  94. metadata +211 -9
  95. data/spec/examples/json.northpole.ro/public/javascripts/docs.min.js +0 -16
  96. data/spec/examples/json.northpole.ro/views/awsum.haml +0 -108
@@ -14,4 +14,15 @@ describe Ki::Helpers do
14
14
  it 'renders js tag' do
15
15
  expect(js('asd')).to eq "<script src='asd'></script>\n"
16
16
  end
17
+
18
+ it 'renders 404 if partial not found' do
19
+ expect {
20
+ partial('does_not_exist')
21
+ }.to raise_error Ki::PartialNotFoundError
22
+ end
23
+
24
+ it 'renders haml' do
25
+ File.stub(:join).and_return('lib/ki/views/404.haml')
26
+ expect(partial('404')).to include('h1')
27
+ end
17
28
  end
@@ -23,4 +23,32 @@ describe Ki::KiConfig do
23
23
  it 'has a middleware method' do
24
24
  expect(config.middleware).to_not be_empty
25
25
  end
26
+
27
+ it 'rm_middleware' do
28
+ config.config['rm_middleware'] = 'AdminInterfaceGenerator'
29
+ expect(config.middleware).to_not include(Ki::Middleware::AdminInterfaceGenerator)
30
+ end
31
+
32
+ it 'add_middleware' do
33
+ config.config['rm_middleware'] = 'Realtime'
34
+ config.middleware
35
+ expect(config.middleware).to_not include(Ki::Middleware::Realtime)
36
+ config.config['rm_middleware'] = []
37
+ config.config['add_middleware'] = 'Realtime'
38
+ expect(config.middleware).to include(Ki::Middleware::Realtime)
39
+ end
40
+
41
+ it 'add_middleware/rm_middleware accepts an array' do
42
+ config.config['rm_middleware'] = 'Realtime'
43
+ expect(config.middleware).to_not include(Ki::Middleware::Realtime)
44
+ config.config['rm_middleware'] = []
45
+
46
+ config.config['add_middleware'] = ['Realtime']
47
+ expect(config.middleware).to include(Ki::Middleware::Realtime)
48
+ end
49
+
50
+ it 'does not add duplicate middleware' do
51
+ config.config['add_middleware'] = %w(Realtime Realtime)
52
+ expect(config.middleware.to_s.scan(/Realtime/).count).to eq 1
53
+ end
26
54
  end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ki::Middleware::AdminInterfaceGenerator do
4
+ it 'works' do
5
+ get '/instadmin'
6
+ expect(last_response.body).to include('Ki InstAdmin')
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ki::Middleware::InitMiddleware do
4
+ let(:app) { {} }
5
+ let(:init) { Ki::Middleware::InitMiddleware.new app }
6
+ let(:req) { Ki::BaseRequest }
7
+
8
+ it 'redirects to /index if public/index.html does not exist' do
9
+ env = Rack::MockRequest.env_for('/', { 'REQUEST_METHOD' => 'GET' })
10
+ resp = init.call env
11
+ expect(resp[0]).to eq 302 # redirect
12
+ end
13
+
14
+ it 'renders index.html if it exists' do
15
+ env = Rack::MockRequest.env_for('/', { 'REQUEST_METHOD' => 'GET' })
16
+
17
+ Ki::Middleware::InitMiddleware.any_instance.stub(:public_file_exists?).and_return(true)
18
+ resp = init.call env
19
+ expect(resp[0]).to eq 404 # not found because index.html doesn't exist
20
+ end
21
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: find a way to test
4
+ describe Ki::Middleware::Realtime do
5
+ let(:app) { {} }
6
+ let(:realtime) { Ki::Middleware::Realtime.new app }
7
+ let(:req) { Ki::BaseRequest }
8
+
9
+ it 'returns /realtime/info' do
10
+ env = Rack::MockRequest.env_for('/realtime/info', { 'REQUEST_METHOD' => 'GET' })
11
+ # get '/realtime/info'
12
+ # expect(last_response.body).to include('404')
13
+ resp = realtime.call env
14
+ expect(resp[0]).to eq 200
15
+ # expect(resp[0]).to eq 302 # redirect
16
+ end
17
+
18
+ it 'handle_websocket' do
19
+ env = Rack::MockRequest.env_for('/realtime', { 'REQUEST_METHOD' => 'GET' })
20
+
21
+ Ki::Middleware::Realtime.any_instance.stub(:handle_websocket).and_return('handle_websocket')
22
+ Faye::WebSocket.stub(:websocket?).and_return(true)
23
+
24
+ resp = realtime.call env
25
+ expect(resp).to eq 'handle_websocket'
26
+ end
27
+
28
+ it 'continues call' do
29
+ env = Rack::MockRequest.env_for('/bazinga', { 'REQUEST_METHOD' => 'GET' })
30
+ Hash.any_instance.stub(:call).and_return('continue')
31
+ resp = realtime.call env
32
+ expect(resp).to eq 'continue'
33
+ end
34
+
35
+ it 'has ws_send' do
36
+ ws = {}
37
+ ws.stub(:send).and_return true
38
+ expect(realtime.ws_send(ws, {})).to be_true
39
+ end
40
+
41
+ describe 'on_message' do
42
+ let(:ws) { {} }
43
+ let(:db) { Ki::Orm::Db.instance }
44
+
45
+ before :each do
46
+ realtime.stub(:ws_send) do |_arg1, arg2|
47
+ arg2
48
+ end
49
+ end
50
+
51
+ it 'requires data to be json parsable' do
52
+ result = realtime.on_message(ws, { 'id' => 'id' }, 'asd')
53
+ expect(result[:message]).to include('valid json string')
54
+ end
55
+
56
+ it 'requires a type' do
57
+ result = realtime.on_message(ws, { 'id' => 'id' }, {}.to_s)
58
+ expect(result[:message]).to include('valid type')
59
+ end
60
+
61
+ it 'subscribes to a channel' do
62
+ Ki::ChannelManager.cleanup
63
+ expect {
64
+ result = realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'subscribe' }.to_json.to_s)
65
+ expect(result[:message]).to include('channel_name')
66
+ }.to change { db.count 'realtime_channel_subscriptions' }.by(0)
67
+
68
+ expect {
69
+ result = realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'subscribe', 'channel_name' => 'channel-1' }.to_json.to_s)
70
+ expect(result[0]['channel_name']).to eq 'channel-1'
71
+ }.to change { db.count 'realtime_channel_subscriptions' }.by(1)
72
+ end
73
+
74
+ it 'unsubscribes to a channel' do
75
+ Ki::ChannelManager.cleanup
76
+ result = realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'subscribe', 'channel_name' => 'channel-1' }.to_json.to_s)
77
+ result = realtime.on_message(ws, { 'id' => 'id2' }, { 'type' => 'subscribe', 'channel_name' => 'channel-1' }.to_json.to_s)
78
+
79
+ expect {
80
+ result = realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'unsubscribe' }.to_json.to_s)
81
+ expect(result[:deleted_item_count]).to eq 1
82
+ }.to change { db.count 'realtime_channel_subscriptions' }.by(-1)
83
+ end
84
+
85
+ it 'publishes on a channel' do
86
+ Ki::ChannelManager.cleanup
87
+ expect {
88
+ realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'publish', 'text' => 'text' }.to_json.to_s)
89
+ }.to change { db.count 'realtime_channel_messages' }.by(0)
90
+
91
+ expect {
92
+ realtime.on_message(ws, { 'id' => 'id' }, { 'type' => 'publish', 'channel_name' => 'channel-1', 'text' => 'text' }.to_json.to_s)
93
+ }.to change { db.count 'realtime_channel_messages' }.by(1)
94
+ end
95
+ end
96
+ end
@@ -54,8 +54,12 @@ describe Ki::Model do
54
54
  end
55
55
 
56
56
  it 'should create object' do
57
+ mock_req = {}
58
+ mock_req.stub(:to_action).and_return(:create)
59
+ mock_req.stub(:params).and_return({})
60
+
57
61
  expect {
58
- DefaultProperties.new(:create, { 'name' => 'zim' })
62
+ DefaultProperties.new(mock_req)
59
63
  }.to change { DefaultProperties.count }.by 1
60
64
  end
61
65
  end
@@ -72,28 +76,45 @@ describe Ki::Model do
72
76
  # keep in mind that delete does not call unique/requires/forbid filters
73
77
  # make sure there are no duplicates
74
78
  SpecialProperties.delete({ 'foo' => t })
79
+
80
+ mock_req = {}
81
+ mock_req.stub(:to_action).and_return(:create)
82
+ mock_req.stub(:params).and_return('name' => 'zim', 'foo' => t)
83
+
75
84
  expect {
76
- SpecialProperties.new(:create, { 'name' => 'zim', 'foo' => t })
85
+ SpecialProperties.new(mock_req)
77
86
  }.to change { SpecialProperties.count }.by 1
78
87
  end
79
88
 
80
89
  it 'should check for required attributes' do
90
+ mock_req = {}
91
+ mock_req.stub(:to_action).and_return(:create)
92
+ mock_req.stub(:params).and_return({})
93
+
81
94
  expect {
82
- SpecialProperties.new(:create, { 'name' => 'zim' })
95
+ SpecialProperties.new(mock_req)
83
96
  }.to raise_error Ki::RequiredAttributeMissing
84
97
  end
85
98
 
86
99
  it 'should check for unique attributes' do
100
+ t = Time.now.to_i
101
+ mock_req = {}
102
+ mock_req.stub(:to_action).and_return(:create)
103
+ mock_req.stub(:params).and_return({ 'name' => 'zim', 'foo' => t })
104
+
87
105
  expect {
88
- t = Time.now.to_i
89
- SpecialProperties.new(:create, { 'name' => 'zim', 'foo' => t })
90
- SpecialProperties.new(:create, { 'name' => 'zim', 'foo' => t })
106
+ SpecialProperties.new(mock_req)
107
+ SpecialProperties.new(mock_req)
91
108
  }.to raise_error Ki::AttributeNotUnique
92
109
  end
93
110
 
94
111
  it 'should not allow forbidden actions' do
112
+ mock_req = {}
113
+ mock_req.stub(:to_action).and_return(:delete)
114
+ mock_req.stub(:params).and_return({})
115
+
95
116
  expect {
96
- SpecialProperties.new(:delete, {})
117
+ SpecialProperties.new(mock_req)
97
118
  }.to raise_error Ki::ForbiddenAction
98
119
  end
99
120
  end
@@ -1,4 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Ki::Model::ModelHelper do
4
+ include Ki::Model::ModelHelper
5
+
6
+ it 'has skipped params' do
7
+ expect(skipped_params).to eq []
8
+ end
9
+
10
+ # TODO: find out if this is a good idea
11
+ it 'tests the request' do
12
+ class TmpClassModelHelper
13
+ def get?
14
+ true
15
+ end
16
+
17
+ def post?
18
+ true
19
+ end
20
+
21
+ def put?
22
+ true
23
+ end
24
+
25
+ def delete?
26
+ true
27
+ end
28
+ end
29
+
30
+ @req = TmpClassModelHelper.new
31
+ expect(post?).to be_true
32
+ expect(put?).to be_true
33
+ expect(delete?).to be_true
34
+ end
4
35
  end
@@ -68,6 +68,32 @@ describe Ki::Orm do
68
68
  expect(r.class).to eq Array
69
69
  expect(r).to be_empty
70
70
  end
71
+
72
+ it 'applies sorting according to __sort key' do
73
+ @db.delete('sort_tests', {})
74
+
75
+ @db.insert('sort_tests', { 'value' => 1 })
76
+ @db.insert('sort_tests', { 'value' => 2 })
77
+
78
+ r = @db.find('sort_tests', { '__sort' => { 'value' => 'desc' } })
79
+ expect(r.size).to eq 2
80
+ expect(r[0]['value']).to eq 2
81
+ expect(r[1]['value']).to eq 1
82
+
83
+ r = @db.find('sort_tests', { '__sort' => { 'value' => 'asc' } })
84
+ expect(r.size).to eq 2
85
+ expect(r[0]['value']).to eq 1
86
+ expect(r[1]['value']).to eq 2
87
+ end
88
+
89
+ it 'applies limiting according to __limit key' do
90
+ 3.times do
91
+ @db.insert('limit_tests', { 'created_at' => Time.now.to_i })
92
+ end
93
+
94
+ r = @db.find('limit_tests', { '__limit' => 2 })
95
+ expect(r.size).to eq 2
96
+ end
71
97
  end
72
98
 
73
99
  it 'should update' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.10
4
+ version: 0.4.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cristian Mircea Messel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-06 00:00:00.000000000 Z
11
+ date: 2017-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: faye-websocket
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: rake
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -254,11 +268,14 @@ files:
254
268
  - LICENSE.md
255
269
  - MIDDLEWARE.md
256
270
  - README.md
271
+ - REALTIME.md
257
272
  - Rakefile
273
+ - TODO.md
258
274
  - bin/ki
259
275
  - ki.gemspec
260
276
  - lib/ki.rb
261
277
  - lib/ki/base_request.rb
278
+ - lib/ki/channel_manager.rb
262
279
  - lib/ki/helpers.rb
263
280
  - lib/ki/ki.rb
264
281
  - lib/ki/ki_app.rb
@@ -273,9 +290,11 @@ files:
273
290
  - lib/ki/middleware/helpers/format_of_helper.rb
274
291
  - lib/ki/middleware/helpers/haml_compiler_helper.rb
275
292
  - lib/ki/middleware/helpers/public_file_helper.rb
293
+ - lib/ki/middleware/helpers/redirect_to_helper.rb
276
294
  - lib/ki/middleware/helpers/view_helper.rb
277
295
  - lib/ki/middleware/init_middleware.rb
278
296
  - lib/ki/middleware/public_file_server.rb
297
+ - lib/ki/middleware/realtime.rb
279
298
  - lib/ki/middleware/sass_compiler.rb
280
299
  - lib/ki/model.rb
281
300
  - lib/ki/modules/callbacks.rb
@@ -287,6 +306,7 @@ files:
287
306
  - lib/ki/utils/extra_irb.rb
288
307
  - lib/ki/utils/extra_ruby.rb
289
308
  - lib/ki/utils/indifferent_hash.rb
309
+ - lib/ki/utils/redirect_to_helper.rb
290
310
  - lib/ki/version.rb
291
311
  - lib/ki/views/404.haml
292
312
  - lib/ki/views/instadmin.haml
@@ -333,19 +353,102 @@ files:
333
353
  - spec/examples/couch-lock/views/settings.haml
334
354
  - spec/examples/couch-lock/views/shop.haml
335
355
  - spec/examples/couch-lock/views/wiki.haml
356
+ - spec/examples/json.northpole.ro/.bowerrc
336
357
  - spec/examples/json.northpole.ro/.ruby-gemset
337
358
  - spec/examples/json.northpole.ro/.ruby-version
338
359
  - spec/examples/json.northpole.ro/Capfile
339
360
  - spec/examples/json.northpole.ro/Gemfile
340
361
  - spec/examples/json.northpole.ro/Gemfile.lock
341
362
  - spec/examples/json.northpole.ro/app.rb
363
+ - spec/examples/json.northpole.ro/bower.json
342
364
  - spec/examples/json.northpole.ro/client.rb
343
365
  - spec/examples/json.northpole.ro/config.ru
344
366
  - spec/examples/json.northpole.ro/config.yml
367
+ - spec/examples/json.northpole.ro/config.yml.backup
345
368
  - spec/examples/json.northpole.ro/config/deploy.rb
346
369
  - spec/examples/json.northpole.ro/config/deploy/production.rb
347
370
  - spec/examples/json.northpole.ro/foo.rb
348
371
  - spec/examples/json.northpole.ro/public/JNorthPole.jar
372
+ - spec/examples/json.northpole.ro/public/app/.bowerrc
373
+ - spec/examples/json.northpole.ro/public/app/.gitignore
374
+ - spec/examples/json.northpole.ro/public/app/.jshintrc
375
+ - spec/examples/json.northpole.ro/public/app/.travis.yml
376
+ - spec/examples/json.northpole.ro/public/app/LICENSE
377
+ - spec/examples/json.northpole.ro/public/app/README.md
378
+ - spec/examples/json.northpole.ro/public/app/bower.json
379
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatar-1.svg
380
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatar-4.svg
381
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatars.svg
382
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/contact_mail_48px.svg
383
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/google_plus.svg
384
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/hangouts.svg
385
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_adb_48px.svg
386
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_add_48px.svg
387
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_clear_48px.svg
388
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_delete_48px.svg
389
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_lock_48px.svg
390
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_music_note_48px.svg
391
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_note_add_48px.svg
392
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_person_add_48px.svg
393
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_settings_48px.svg
394
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_share_48px.svg
395
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_view_list_48px.svg
396
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/icon.svg
397
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/mail.svg
398
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/manggo.svg
399
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/menu.svg
400
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/phone.svg
401
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/share.svg
402
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/twitter.svg
403
+ - spec/examples/json.northpole.ro/public/app/build/css/app.css
404
+ - spec/examples/json.northpole.ro/public/app/build/css/vendor.css
405
+ - spec/examples/json.northpole.ro/public/app/build/index.html
406
+ - spec/examples/json.northpole.ro/public/app/build/js/MainController.js
407
+ - spec/examples/json.northpole.ro/public/app/build/js/app.js
408
+ - spec/examples/json.northpole.ro/public/app/build/js/blobs/BlobsController.js
409
+ - spec/examples/json.northpole.ro/public/app/build/js/blobs/blobs.html
410
+ - spec/examples/json.northpole.ro/public/app/build/js/tutorial/tutorial.html
411
+ - spec/examples/json.northpole.ro/public/app/build/js/users/UserService.js
412
+ - spec/examples/json.northpole.ro/public/app/build/js/users/Users.js
413
+ - spec/examples/json.northpole.ro/public/app/build/js/users/users.html
414
+ - spec/examples/json.northpole.ro/public/app/build/js/vendor.js
415
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/ContactUser.js
416
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/UserDetails.js
417
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/UserList.js
418
+ - spec/examples/json.northpole.ro/public/app/e2e/protractor.conf.js
419
+ - spec/examples/json.northpole.ro/public/app/e2e/scenarios/users.js
420
+ - spec/examples/json.northpole.ro/public/app/gulpfile.js
421
+ - spec/examples/json.northpole.ro/public/app/karma.conf.js
422
+ - spec/examples/json.northpole.ro/public/app/package.json
423
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-1.svg
424
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-4.svg
425
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatars.svg
426
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/google_plus.svg
427
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/hangouts.svg
428
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_48px.svg
429
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_exit_48px.svg
430
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_music_note_48px.svg
431
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_note_add_48px.svg
432
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_view_list_48px.svg
433
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/icon.svg
434
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/mail.svg
435
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/manggo.svg
436
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/menu.svg
437
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/phone.svg
438
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/share.svg
439
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/twitter.svg
440
+ - spec/examples/json.northpole.ro/public/app/src/css/app.css
441
+ - spec/examples/json.northpole.ro/public/app/src/css/app.css.map
442
+ - spec/examples/json.northpole.ro/public/app/src/css/app.sass
443
+ - spec/examples/json.northpole.ro/public/app/src/index.html
444
+ - spec/examples/json.northpole.ro/public/app/src/js/MainController.coffee
445
+ - spec/examples/json.northpole.ro/public/app/src/js/app.coffee
446
+ - spec/examples/json.northpole.ro/public/app/src/js/blobs/BlobsController.coffee
447
+ - spec/examples/json.northpole.ro/public/app/src/js/blobs/blobs.html
448
+ - spec/examples/json.northpole.ro/public/app/src/js/tutorial/tutorial.html
449
+ - spec/examples/json.northpole.ro/public/app/src/js/users/UserService.coffee
450
+ - spec/examples/json.northpole.ro/public/app/src/js/users/Users.coffee
451
+ - spec/examples/json.northpole.ro/public/app/src/js/users/users.html
349
452
  - spec/examples/json.northpole.ro/public/favicon.ico
350
453
  - spec/examples/json.northpole.ro/public/font/FontAwesome.otf
351
454
  - spec/examples/json.northpole.ro/public/font/fontawesome-webfont.eot
@@ -378,11 +481,13 @@ files:
378
481
  - spec/examples/json.northpole.ro/public/images/shell_small.png
379
482
  - spec/examples/json.northpole.ro/public/javascripts/analytics.js
380
483
  - spec/examples/json.northpole.ro/public/javascripts/app.coffee
381
- - spec/examples/json.northpole.ro/public/javascripts/docs.min.js
382
484
  - spec/examples/json.northpole.ro/public/javascripts/jnorthpole.coffee
383
- - spec/examples/json.northpole.ro/public/javascripts/music/angular-youtube-embed.js
485
+ - spec/examples/json.northpole.ro/public/javascripts/realtime.coffee
486
+ - spec/examples/json.northpole.ro/public/music/angular-youtube-embed.js
487
+ - spec/examples/json.northpole.ro/public/music/index.html
488
+ - spec/examples/json.northpole.ro/public/music/music.coffee
489
+ - spec/examples/json.northpole.ro/public/music/music.sass
384
490
  - spec/examples/json.northpole.ro/public/stylesheets/app.sass
385
- - spec/examples/json.northpole.ro/views/awsum.haml
386
491
  - spec/examples/json.northpole.ro/views/curl.haml
387
492
  - spec/examples/json.northpole.ro/views/doc.haml
388
493
  - spec/examples/json.northpole.ro/views/doc_table.haml
@@ -393,12 +498,14 @@ files:
393
498
  - spec/examples/json.northpole.ro/views/java.haml
394
499
  - spec/examples/json.northpole.ro/views/javascript.haml
395
500
  - spec/examples/json.northpole.ro/views/layout.haml
501
+ - spec/examples/json.northpole.ro/views/music.haml
396
502
  - spec/examples/json.northpole.ro/views/php.haml
397
503
  - spec/examples/json.northpole.ro/views/playground.haml
398
504
  - spec/examples/json.northpole.ro/views/python.haml
399
505
  - spec/examples/json.northpole.ro/views/ruby.haml
400
506
  - spec/examples/json.northpole.ro/views/seed.haml
401
507
  - spec/examples/json.northpole.ro/views/thanks.haml
508
+ - spec/examples/json.northpole.ro/views/websocket.haml
402
509
  - spec/examples/tasks-example/.ruby-gemset
403
510
  - spec/examples/tasks-example/.ruby-version
404
511
  - spec/examples/tasks-example/Gemfile
@@ -424,14 +531,18 @@ files:
424
531
  - spec/examples/todo/views/layout.haml
425
532
  - spec/functional_spec.rb
426
533
  - spec/lib/ki/base_request_spec.rb
534
+ - spec/lib/ki/channel_manager_spec.rb
427
535
  - spec/lib/ki/helpers_spec.rb
428
536
  - spec/lib/ki/indifferent_hash_spec.rb
429
537
  - spec/lib/ki/ki_app_spec.rb
430
538
  - spec/lib/ki/ki_config_spec.rb
431
539
  - spec/lib/ki/ki_spec.rb
540
+ - spec/lib/ki/middleware/admin_generator_spec.rb
432
541
  - spec/lib/ki/middleware/doc_generator_spec.rb
433
542
  - spec/lib/ki/middleware/haml_compiler_spec.rb
434
543
  - spec/lib/ki/middleware/helpers/format_of_helper_spec.rb
544
+ - spec/lib/ki/middleware/init_middleware_spec.rb
545
+ - spec/lib/ki/middleware/realtime_spec.rb
435
546
  - spec/lib/ki/middleware_spec.rb
436
547
  - spec/lib/ki/model_spec.rb
437
548
  - spec/lib/ki/modules/model_helper_spec.rb
@@ -459,7 +570,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
459
570
  version: '0'
460
571
  requirements: []
461
572
  rubyforge_project:
462
- rubygems_version: 2.4.7
573
+ rubygems_version: 2.4.8
463
574
  signing_key:
464
575
  specification_version: 4
465
576
  summary: it said optional
@@ -506,19 +617,102 @@ test_files:
506
617
  - spec/examples/couch-lock/views/settings.haml
507
618
  - spec/examples/couch-lock/views/shop.haml
508
619
  - spec/examples/couch-lock/views/wiki.haml
620
+ - spec/examples/json.northpole.ro/.bowerrc
509
621
  - spec/examples/json.northpole.ro/.ruby-gemset
510
622
  - spec/examples/json.northpole.ro/.ruby-version
511
623
  - spec/examples/json.northpole.ro/Capfile
512
624
  - spec/examples/json.northpole.ro/Gemfile
513
625
  - spec/examples/json.northpole.ro/Gemfile.lock
514
626
  - spec/examples/json.northpole.ro/app.rb
627
+ - spec/examples/json.northpole.ro/bower.json
515
628
  - spec/examples/json.northpole.ro/client.rb
516
629
  - spec/examples/json.northpole.ro/config.ru
517
630
  - spec/examples/json.northpole.ro/config.yml
631
+ - spec/examples/json.northpole.ro/config.yml.backup
518
632
  - spec/examples/json.northpole.ro/config/deploy.rb
519
633
  - spec/examples/json.northpole.ro/config/deploy/production.rb
520
634
  - spec/examples/json.northpole.ro/foo.rb
521
635
  - spec/examples/json.northpole.ro/public/JNorthPole.jar
636
+ - spec/examples/json.northpole.ro/public/app/.bowerrc
637
+ - spec/examples/json.northpole.ro/public/app/.gitignore
638
+ - spec/examples/json.northpole.ro/public/app/.jshintrc
639
+ - spec/examples/json.northpole.ro/public/app/.travis.yml
640
+ - spec/examples/json.northpole.ro/public/app/LICENSE
641
+ - spec/examples/json.northpole.ro/public/app/README.md
642
+ - spec/examples/json.northpole.ro/public/app/bower.json
643
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatar-1.svg
644
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatar-4.svg
645
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/avatars.svg
646
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/contact_mail_48px.svg
647
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/google_plus.svg
648
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/hangouts.svg
649
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_adb_48px.svg
650
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_add_48px.svg
651
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_clear_48px.svg
652
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_delete_48px.svg
653
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_lock_48px.svg
654
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_music_note_48px.svg
655
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_note_add_48px.svg
656
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_person_add_48px.svg
657
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_settings_48px.svg
658
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_share_48px.svg
659
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/ic_view_list_48px.svg
660
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/icon.svg
661
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/mail.svg
662
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/manggo.svg
663
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/menu.svg
664
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/phone.svg
665
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/share.svg
666
+ - spec/examples/json.northpole.ro/public/app/build/assets/svg/twitter.svg
667
+ - spec/examples/json.northpole.ro/public/app/build/css/app.css
668
+ - spec/examples/json.northpole.ro/public/app/build/css/vendor.css
669
+ - spec/examples/json.northpole.ro/public/app/build/index.html
670
+ - spec/examples/json.northpole.ro/public/app/build/js/MainController.js
671
+ - spec/examples/json.northpole.ro/public/app/build/js/app.js
672
+ - spec/examples/json.northpole.ro/public/app/build/js/blobs/BlobsController.js
673
+ - spec/examples/json.northpole.ro/public/app/build/js/blobs/blobs.html
674
+ - spec/examples/json.northpole.ro/public/app/build/js/tutorial/tutorial.html
675
+ - spec/examples/json.northpole.ro/public/app/build/js/users/UserService.js
676
+ - spec/examples/json.northpole.ro/public/app/build/js/users/Users.js
677
+ - spec/examples/json.northpole.ro/public/app/build/js/users/users.html
678
+ - spec/examples/json.northpole.ro/public/app/build/js/vendor.js
679
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/ContactUser.js
680
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/UserDetails.js
681
+ - spec/examples/json.northpole.ro/public/app/e2e/pages/UserList.js
682
+ - spec/examples/json.northpole.ro/public/app/e2e/protractor.conf.js
683
+ - spec/examples/json.northpole.ro/public/app/e2e/scenarios/users.js
684
+ - spec/examples/json.northpole.ro/public/app/gulpfile.js
685
+ - spec/examples/json.northpole.ro/public/app/karma.conf.js
686
+ - spec/examples/json.northpole.ro/public/app/package.json
687
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-1.svg
688
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-4.svg
689
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/avatars.svg
690
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/google_plus.svg
691
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/hangouts.svg
692
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_48px.svg
693
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_exit_48px.svg
694
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_music_note_48px.svg
695
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_note_add_48px.svg
696
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_view_list_48px.svg
697
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/icon.svg
698
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/mail.svg
699
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/manggo.svg
700
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/menu.svg
701
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/phone.svg
702
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/share.svg
703
+ - spec/examples/json.northpole.ro/public/app/src/assets/svg/twitter.svg
704
+ - spec/examples/json.northpole.ro/public/app/src/css/app.css
705
+ - spec/examples/json.northpole.ro/public/app/src/css/app.css.map
706
+ - spec/examples/json.northpole.ro/public/app/src/css/app.sass
707
+ - spec/examples/json.northpole.ro/public/app/src/index.html
708
+ - spec/examples/json.northpole.ro/public/app/src/js/MainController.coffee
709
+ - spec/examples/json.northpole.ro/public/app/src/js/app.coffee
710
+ - spec/examples/json.northpole.ro/public/app/src/js/blobs/BlobsController.coffee
711
+ - spec/examples/json.northpole.ro/public/app/src/js/blobs/blobs.html
712
+ - spec/examples/json.northpole.ro/public/app/src/js/tutorial/tutorial.html
713
+ - spec/examples/json.northpole.ro/public/app/src/js/users/UserService.coffee
714
+ - spec/examples/json.northpole.ro/public/app/src/js/users/Users.coffee
715
+ - spec/examples/json.northpole.ro/public/app/src/js/users/users.html
522
716
  - spec/examples/json.northpole.ro/public/favicon.ico
523
717
  - spec/examples/json.northpole.ro/public/font/FontAwesome.otf
524
718
  - spec/examples/json.northpole.ro/public/font/fontawesome-webfont.eot
@@ -551,11 +745,13 @@ test_files:
551
745
  - spec/examples/json.northpole.ro/public/images/shell_small.png
552
746
  - spec/examples/json.northpole.ro/public/javascripts/analytics.js
553
747
  - spec/examples/json.northpole.ro/public/javascripts/app.coffee
554
- - spec/examples/json.northpole.ro/public/javascripts/docs.min.js
555
748
  - spec/examples/json.northpole.ro/public/javascripts/jnorthpole.coffee
556
- - spec/examples/json.northpole.ro/public/javascripts/music/angular-youtube-embed.js
749
+ - spec/examples/json.northpole.ro/public/javascripts/realtime.coffee
750
+ - spec/examples/json.northpole.ro/public/music/angular-youtube-embed.js
751
+ - spec/examples/json.northpole.ro/public/music/index.html
752
+ - spec/examples/json.northpole.ro/public/music/music.coffee
753
+ - spec/examples/json.northpole.ro/public/music/music.sass
557
754
  - spec/examples/json.northpole.ro/public/stylesheets/app.sass
558
- - spec/examples/json.northpole.ro/views/awsum.haml
559
755
  - spec/examples/json.northpole.ro/views/curl.haml
560
756
  - spec/examples/json.northpole.ro/views/doc.haml
561
757
  - spec/examples/json.northpole.ro/views/doc_table.haml
@@ -566,12 +762,14 @@ test_files:
566
762
  - spec/examples/json.northpole.ro/views/java.haml
567
763
  - spec/examples/json.northpole.ro/views/javascript.haml
568
764
  - spec/examples/json.northpole.ro/views/layout.haml
765
+ - spec/examples/json.northpole.ro/views/music.haml
569
766
  - spec/examples/json.northpole.ro/views/php.haml
570
767
  - spec/examples/json.northpole.ro/views/playground.haml
571
768
  - spec/examples/json.northpole.ro/views/python.haml
572
769
  - spec/examples/json.northpole.ro/views/ruby.haml
573
770
  - spec/examples/json.northpole.ro/views/seed.haml
574
771
  - spec/examples/json.northpole.ro/views/thanks.haml
772
+ - spec/examples/json.northpole.ro/views/websocket.haml
575
773
  - spec/examples/tasks-example/.ruby-gemset
576
774
  - spec/examples/tasks-example/.ruby-version
577
775
  - spec/examples/tasks-example/Gemfile
@@ -597,14 +795,18 @@ test_files:
597
795
  - spec/examples/todo/views/layout.haml
598
796
  - spec/functional_spec.rb
599
797
  - spec/lib/ki/base_request_spec.rb
798
+ - spec/lib/ki/channel_manager_spec.rb
600
799
  - spec/lib/ki/helpers_spec.rb
601
800
  - spec/lib/ki/indifferent_hash_spec.rb
602
801
  - spec/lib/ki/ki_app_spec.rb
603
802
  - spec/lib/ki/ki_config_spec.rb
604
803
  - spec/lib/ki/ki_spec.rb
804
+ - spec/lib/ki/middleware/admin_generator_spec.rb
605
805
  - spec/lib/ki/middleware/doc_generator_spec.rb
606
806
  - spec/lib/ki/middleware/haml_compiler_spec.rb
607
807
  - spec/lib/ki/middleware/helpers/format_of_helper_spec.rb
808
+ - spec/lib/ki/middleware/init_middleware_spec.rb
809
+ - spec/lib/ki/middleware/realtime_spec.rb
608
810
  - spec/lib/ki/middleware_spec.rb
609
811
  - spec/lib/ki/model_spec.rb
610
812
  - spec/lib/ki/modules/model_helper_spec.rb