ki 0.4.11 → 0.4.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +9 -0
  4. data/.ruby-gemset +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +10 -2
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +95 -85
  9. data/Guardfile +20 -14
  10. data/MIDDLEWARE.md +2 -2
  11. data/README.md +29 -1
  12. data/Rakefile +3 -1
  13. data/bin/ki +1 -0
  14. data/ki.gemspec +15 -14
  15. data/lib/ki.rb +8 -1
  16. data/lib/ki/base_request.rb +7 -5
  17. data/lib/ki/channel_manager.rb +2 -0
  18. data/lib/ki/helpers.rb +4 -5
  19. data/lib/ki/ki.rb +11 -2
  20. data/lib/ki/ki_app.rb +2 -0
  21. data/lib/ki/ki_cli.rb +9 -2
  22. data/lib/ki/ki_config.rb +5 -2
  23. data/lib/ki/ki_logger.rb +15 -0
  24. data/lib/ki/middleware/admin_interface_generator.rb +3 -1
  25. data/lib/ki/middleware/api_handler.rb +3 -1
  26. data/lib/ki/middleware/base_middleware.rb +2 -0
  27. data/lib/ki/middleware/coffee_compiler.rb +2 -0
  28. data/lib/ki/middleware/haml_compiler.rb +2 -0
  29. data/lib/ki/middleware/helpers/format_of_helper.rb +3 -1
  30. data/lib/ki/middleware/helpers/haml_compiler_helper.rb +7 -5
  31. data/lib/ki/middleware/helpers/public_file_helper.rb +2 -0
  32. data/lib/ki/middleware/helpers/redirect_to_helper.rb +2 -0
  33. data/lib/ki/middleware/helpers/view_helper.rb +2 -0
  34. data/lib/ki/middleware/init_middleware.rb +2 -0
  35. data/lib/ki/middleware/{doc_generator.rb → insta_doc.rb} +8 -6
  36. data/lib/ki/middleware/public_file_server.rb +2 -0
  37. data/lib/ki/middleware/realtime.rb +3 -1
  38. data/lib/ki/middleware/sass_compiler.rb +2 -0
  39. data/lib/ki/model.rb +8 -7
  40. data/lib/ki/modules/callbacks.rb +12 -20
  41. data/lib/ki/modules/model_helper.rb +2 -0
  42. data/lib/ki/modules/query_interface.rb +2 -0
  43. data/lib/ki/modules/restrictions.rb +5 -2
  44. data/lib/ki/orm.rb +20 -13
  45. data/lib/ki/utils/annotations.rb +33 -0
  46. data/lib/ki/utils/api_error.rb +14 -4
  47. data/lib/ki/utils/descendants.rb +9 -0
  48. data/lib/ki/utils/extra_irb.rb +3 -1
  49. data/lib/ki/utils/extra_ruby.rb +12 -0
  50. data/lib/ki/utils/indifferent_hash.rb +2 -0
  51. data/lib/ki/utils/logger.rb +5 -0
  52. data/lib/ki/version.rb +3 -1
  53. data/lib/ki/views/instadoc.haml +49 -9
  54. data/spec/config.yml.example +1 -1
  55. data/spec/examples/base/client.rb +20 -0
  56. data/spec/examples/base/logs/.keep +0 -0
  57. data/spec/examples/base/public/javascripts/app.js +12 -0
  58. data/spec/examples/json.northpole.ro/.ruby-version +1 -1
  59. data/spec/examples/json.northpole.ro/public/javascripts/app.coffee +1 -0
  60. data/spec/functional_spec.rb +2 -0
  61. data/spec/lib/ki/base_request_spec.rb +25 -23
  62. data/spec/lib/ki/channel_manager_spec.rb +2 -0
  63. data/spec/lib/ki/helpers_spec.rb +4 -2
  64. data/spec/lib/ki/indifferent_hash_spec.rb +2 -0
  65. data/spec/lib/ki/ki_app_spec.rb +2 -0
  66. data/spec/lib/ki/ki_config_spec.rb +5 -3
  67. data/spec/lib/ki/ki_spec.rb +2 -0
  68. data/spec/lib/ki/middleware/admin_generator_spec.rb +2 -0
  69. data/spec/lib/ki/middleware/haml_compiler_spec.rb +6 -3
  70. data/spec/lib/ki/middleware/helpers/format_of_helper_spec.rb +4 -2
  71. data/spec/lib/ki/middleware/init_middleware_spec.rb +3 -1
  72. data/spec/lib/ki/middleware/{doc_generator_spec.rb → insta_doc_spec.rb} +3 -1
  73. data/spec/lib/ki/middleware/realtime_spec.rb +12 -6
  74. data/spec/lib/ki/middleware_spec.rb +3 -1
  75. data/spec/lib/ki/model_spec.rb +26 -22
  76. data/spec/lib/ki/modules/model_helper_spec.rb +5 -3
  77. data/spec/lib/ki/modules/restrictions_spec.rb +16 -0
  78. data/spec/lib/ki/orm_spec.rb +18 -15
  79. data/spec/lib/ki/utils/api_error_spec.rb +9 -0
  80. data/spec/spec_helper.rb +13 -7
  81. data/spec/util_spec.rb +3 -1
  82. metadata +44 -30
data/lib/ki.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ruby stdlib
2
4
  require 'yaml'
3
5
  require 'uri'
@@ -12,10 +14,14 @@ require 'coffee-script'
12
14
  require 'mongo'
13
15
  require 'faye/websocket'
14
16
  require 'eventmachine'
17
+ require 'logger'
15
18
 
16
19
  # code
20
+ require 'ki/utils/annotations'
21
+ require 'ki/utils/descendants'
17
22
  require 'ki/utils/api_error'
18
23
  require 'ki/utils/extra_ruby'
24
+ require 'ki/utils/logger'
19
25
  require 'ki/utils/indifferent_hash'
20
26
 
21
27
  require 'ki/modules/query_interface'
@@ -36,11 +42,12 @@ require 'ki/middleware/public_file_server'
36
42
  require 'ki/middleware/sass_compiler'
37
43
  require 'ki/middleware/haml_compiler'
38
44
  require 'ki/middleware/coffee_compiler'
39
- require 'ki/middleware/doc_generator'
45
+ require 'ki/middleware/insta_doc'
40
46
  require 'ki/middleware/admin_interface_generator'
41
47
  require 'ki/middleware/realtime'
42
48
 
43
49
  require 'ki/ki_config'
50
+ require 'ki/ki_logger'
44
51
  require 'ki/helpers'
45
52
  require 'ki/orm'
46
53
  require 'ki/model'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class BaseRequest < Rack::Request
3
5
  include Middleware::Helpers::FormatOf
@@ -20,13 +22,13 @@ module Ki
20
22
 
21
23
  def headers
22
24
  Hash[*env.select { |k, _v| k.start_with? 'HTTP_' }
23
- .collect { |k, v| [k.sub(/^HTTP_/, ''), v] }
24
- .sort
25
- .flatten]
25
+ .collect { |k, v| [k.sub(/^HTTP_/, ''), v] }
26
+ .sort
27
+ .flatten]
26
28
  end
27
29
 
28
30
  def to_ki_model_class
29
- path.to_s.gsub('/', '').gsub(format_of(path), '').gsub('.', '').to_class
31
+ path.to_s.delete('/').gsub(format_of(path), '').delete('.').to_class
30
32
  end
31
33
 
32
34
  def to_action
@@ -42,7 +44,7 @@ module Ki
42
44
  when 'SEARCH'
43
45
  :find
44
46
  else
45
- fail 'unkown action'
47
+ raise 'unkown action'
46
48
  end
47
49
  end
48
50
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class ChannelManager
3
5
  def self.connect
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Helpers
3
5
  include Middleware::Helpers::View
@@ -16,11 +18,8 @@ module Ki
16
18
 
17
19
  def partial(s)
18
20
  path = view_path(s)
19
- if File.file?(path)
20
- haml(File.read(path))
21
- else
22
- fail PartialNotFoundError, path
23
- end
21
+ raise PartialNotFoundError, path unless File.file?(path)
22
+ haml(File.read(path))
24
23
  end
25
24
  end
26
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class Ki
3
5
  PUBLIC_PATH = 'public'
@@ -8,6 +10,14 @@ module Ki
8
10
 
9
11
  @app = Rack::Builder.new do
10
12
  use Middleware::InitMiddleware
13
+
14
+ if Dir.exist?('logs')
15
+ logfile = ::File.join('logs', 'requests.log')
16
+ logger = ::Logger.new(logfile, 'weekly')
17
+ KiLogger.instance.init(logger)
18
+ use Rack::CommonLogger, logger
19
+ end
20
+
11
21
  use Rack::Parser, content_types: {
12
22
  'application/json' => proc { |body| ::MultiJson.decode body }
13
23
  }
@@ -15,8 +25,7 @@ module Ki
15
25
  use Rack::Cors do
16
26
  allow do
17
27
  origins '*'
18
- resource '*', headers: :any, methods: [:get, :search, :put, :post, :delete]
19
- # resource '*', headers: :any, methods: :any # TODO: find out why :any doesn't work
28
+ resource '*', headers: :any, methods: %i[get search put post delete]
20
29
  end
21
30
  end
22
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class KiApp
3
5
  include Middleware::Helpers::HamlCompiler
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
 
3
5
  require 'ki/utils/extra_irb'
@@ -7,15 +9,20 @@ module Ki
7
9
  class KiGenerator < Thor::Group #:nodoc:
8
10
  include Thor::Actions
9
11
 
12
+ def self.say(s)
13
+ puts s
14
+ end
15
+
10
16
  def self.source_root
11
17
  File.join(File.dirname(__FILE__), '..', '..')
12
18
  end
13
19
 
14
20
  def self.requires_ki_directory
15
- unless File.exist? 'config.ru'
21
+ unless File.exist?('config.ru')
16
22
  say 'Working directory should be a ki app.'
17
23
  exit 3
18
24
  end
25
+ say 'Found config.ru'
19
26
  end
20
27
  end
21
28
 
@@ -23,7 +30,7 @@ module Ki
23
30
  argument :app_name
24
31
 
25
32
  def prepare_dir
26
- unless app_name =~ /^[a-zA-Z0-9-]*$/
33
+ unless app_name.match?(/^[a-zA-Z0-9-]*$/)
27
34
  say 'App name must contain only alphanumeric characters and -'
28
35
  exit 1
29
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
 
3
5
  module Ki
@@ -5,6 +7,7 @@ module Ki
5
7
  include Singleton
6
8
 
7
9
  attr_reader :config, :environment
10
+ attr_accessor :logger
8
11
 
9
12
  def read(environment)
10
13
  @environment = environment
@@ -21,8 +24,8 @@ module Ki
21
24
  end
22
25
 
23
26
  def middleware
24
- used_middleware = %w(ApiHandler CoffeeCompiler SassCompiler HamlCompiler
25
- PublicFileServer)
27
+ used_middleware = %w[ApiHandler CoffeeCompiler SassCompiler HamlCompiler
28
+ PublicFileServer]
26
29
  used_middleware = @config['middleware'] if @config['middleware']
27
30
 
28
31
  used_middleware = add_rm_middleware used_middleware, 'add_middleware', 'push'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ module Ki
6
+ class KiLogger
7
+ include Singleton
8
+
9
+ attr_accessor :logger
10
+
11
+ def init logger
12
+ @logger = logger
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
- class AdminInterfaceGenerator < DocGenerator
5
+ class AdminInterfaceGenerator < InstaDoc
4
6
  def custom_view_path
5
7
  File.join(File.dirname(__FILE__), '..', 'views', 'instadmin.haml')
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  # Handles all API calls
@@ -24,7 +26,7 @@ module Ki
24
26
  klass = req.to_ki_model_class
25
27
 
26
28
  unless Model.descendants.include?(klass)
27
- fail InvalidUrlError.new("invalid url '#{req.path}'", 404)
29
+ raise InvalidUrlError.new("invalid url '#{req.path}'", 404)
28
30
  end
29
31
 
30
32
  model = klass.new(req)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  module BaseMiddleware
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  class CoffeeCompiler
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  class HamlCompiler
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  module Helpers
4
6
  module FormatOf
5
7
  def format_of(uri)
6
8
  uri = uri.path if uri.class == BaseRequest
7
- File.extname(URI.parse(uri).path).gsub('.', '')
9
+ File.extname(URI.parse(uri).path).delete('.')
8
10
  rescue URI::InvalidURIError
9
11
  ''
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  module Helpers
@@ -5,11 +7,11 @@ module Ki
5
7
  def render_haml_file(file_path, layout = true)
6
8
  file_contents = File.read(file_path)
7
9
 
8
- if layout && view_exists?('layout')
9
- layout_contents = File.read(view_path('layout'))
10
- else
11
- layout_contents = '= yield'
12
- end
10
+ layout_contents = if layout && view_exists?('layout')
11
+ File.read(view_path('layout'))
12
+ else
13
+ '= yield'
14
+ end
13
15
 
14
16
  html = render_haml(layout_contents).render do
15
17
  render_haml(file_contents).render
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  module Helpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  module Helpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  module Helpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
5
  class InitMiddleware
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware
3
- class DocGenerator < HamlCompiler
5
+ class InstaDoc < HamlCompiler
4
6
  include BaseMiddleware
5
7
 
6
8
  def call(env)
7
9
  req = BaseRequest.new env
8
10
  if custom_check(req)
9
- if view_exists?(req)
10
- html = render_haml_file view_path(req)
11
- else
12
- html = render_haml_file custom_view_path
13
- end
11
+ html = if view_exists?(req)
12
+ render_haml_file view_path(req)
13
+ else
14
+ render_haml_file custom_view_path
15
+ end
14
16
  Rack::Response.new(html).finish
15
17
  else
16
18
  @app.call env
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  class PublicFileServer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  class Realtime
@@ -39,7 +41,7 @@ module Ki
39
41
 
40
42
  timer = EventMachine::PeriodicTimer.new(1) do
41
43
  msgs = ::Ki::ChannelManager.tick(socket_id: socket['id'])
42
- ws_send(ws, { messages: msgs }) if msgs.count > 0
44
+ ws_send(ws, { messages: msgs }) if msgs.count.positive?
43
45
  end
44
46
 
45
47
  ws.on :close do # |event|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  module Middleware #:nodoc:
3
5
  class SassCompiler
@@ -1,11 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class Model
5
+ extend Descendants
3
6
  extend QueryInterface
4
7
  extend Restrictions
5
8
  include Callbacks
6
9
  include ModelHelper
7
10
  include Middleware::Helpers::RedirectTo
8
11
 
12
+ annotate!
13
+
9
14
  attr_accessor :action, :result, :params, :status, :req
10
15
 
11
16
  def initialize(req)
@@ -14,7 +19,7 @@ module Ki
14
19
  @params = req.params
15
20
  @status = 200
16
21
 
17
- fail ForbiddenAction if forbidden_actions.include? @action
22
+ raise ForbiddenAction if forbidden_actions.include? @action
18
23
 
19
24
  ccall
20
25
  end
@@ -44,7 +49,7 @@ module Ki
44
49
  def check_for_required_attributes
45
50
  required_attributes.each do |ra|
46
51
  unless @params.keys.include?(ra.to_s)
47
- fail RequiredAttributeMissing, "#{ra} missing"
52
+ raise RequiredAttributeMissing, "#{ra} missing"
48
53
  end
49
54
  end
50
55
  end
@@ -52,7 +57,7 @@ module Ki
52
57
  def check_for_unique_attributes
53
58
  unique_attributes.each do |ua|
54
59
  u = self.class.find({ ua.to_s => @params[ua.to_s] })
55
- fail AttributeNotUnique, "#{ua} not unique" unless u.empty?
60
+ raise AttributeNotUnique, "#{ua} not unique" unless u.empty?
56
61
  end
57
62
  end
58
63
 
@@ -63,9 +68,5 @@ module Ki
63
68
  send "after_#{@action}".to_sym
64
69
  after_all
65
70
  end
66
-
67
- def self.descendants
68
- ObjectSpace.each_object(Class).select { |klass| klass < self }
69
- end
70
71
  end
71
72
  end
@@ -1,35 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ki
2
4
  class Model
3
5
  module Callbacks
4
- def before_all
5
- end
6
+ def before_all; end
6
7
 
7
- def before_find
8
- end
8
+ def before_find; end
9
9
 
10
- def after_find
11
- end
10
+ def after_find; end
12
11
 
13
- def before_create
14
- end
12
+ def before_create; end
15
13
 
16
- def after_create
17
- end
14
+ def after_create; end
18
15
 
19
- def before_update
20
- end
16
+ def before_update; end
21
17
 
22
- def after_update
23
- end
18
+ def after_update; end
24
19
 
25
- def before_delete
26
- end
20
+ def before_delete; end
27
21
 
28
- def after_delete
29
- end
22
+ def after_delete; end
30
23
 
31
- def after_all
32
- end
24
+ def after_all; end
33
25
  end
34
26
  end
35
27
  end