lux-fw 0.2.3 → 0.5.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/bin/README.md +33 -0
  4. data/bin/build_gem +76 -0
  5. data/bin/cli/config.rb +44 -0
  6. data/bin/cli/console.rb +61 -0
  7. data/bin/cli/dbconsole.rb +8 -0
  8. data/bin/cli/eval.rb +32 -0
  9. data/bin/cli/generate.rb +88 -0
  10. data/bin/cli/get.rb +12 -0
  11. data/bin/cli/new.rb +22 -0
  12. data/bin/cli/routes.rb +90 -0
  13. data/bin/cli/secrets.rb +40 -0
  14. data/bin/cli/server.rb +24 -0
  15. data/bin/cli/stats.rb +133 -0
  16. data/bin/lux +24 -65
  17. data/lib/common/class_attributes.rb +40 -64
  18. data/lib/common/class_callbacks.rb +34 -51
  19. data/lib/common/crypt.rb +10 -8
  20. data/lib/common/free_struct.rb +42 -0
  21. data/lib/common/hash_with_indifferent_access.rb +1 -1
  22. data/lib/common/html_tag_builder.rb +26 -2
  23. data/lib/common/url.rb +58 -40
  24. data/lib/lux/application/application.rb +290 -117
  25. data/lib/lux/application/lib/nav.rb +64 -38
  26. data/lib/lux/application/lib/render.rb +2 -1
  27. data/lib/lux/cache/cache.rb +87 -62
  28. data/lib/lux/cache/lib/{ram.rb → memory.rb} +5 -7
  29. data/lib/lux/cache/lib/null.rb +6 -8
  30. data/lib/lux/config/config.rb +109 -52
  31. data/lib/lux/config/lib/plugin.rb +65 -0
  32. data/lib/lux/config/lib/secrets.rb +48 -0
  33. data/lib/lux/controller/controller.rb +241 -0
  34. data/lib/lux/current/current.rb +33 -47
  35. data/lib/lux/current/lib/session.rb +72 -0
  36. data/lib/lux/delayed_job/delayed_job.rb +14 -7
  37. data/lib/lux/delayed_job/lib/memory.rb +7 -5
  38. data/lib/lux/delayed_job/lib/redis.rb +1 -1
  39. data/lib/lux/error/error.rb +164 -62
  40. data/lib/lux/event_bus/event_bus.rb +27 -0
  41. data/lib/lux/lux.rb +103 -66
  42. data/lib/lux/mailer/mailer.rb +23 -25
  43. data/lib/lux/response/lib/file.rb +81 -0
  44. data/lib/lux/response/lib/header.rb +14 -1
  45. data/lib/lux/response/response.rb +64 -56
  46. data/lib/lux/view/cell.rb +102 -0
  47. data/lib/lux/{helper → view}/helper.rb +39 -23
  48. data/lib/lux/view/lib/cell_helpers.rb +29 -0
  49. data/lib/lux/{helper/helpers/mailer_helper.rb → view/lib/helper_modules.rb} +7 -1
  50. data/lib/lux/{template/template.rb → view/view.rb} +21 -24
  51. data/lib/lux-fw.rb +4 -2
  52. data/lib/overload/array.rb +12 -6
  53. data/lib/overload/blank.rb +0 -1
  54. data/lib/overload/dir.rb +18 -0
  55. data/lib/overload/file.rb +1 -6
  56. data/lib/overload/hash.rb +56 -13
  57. data/lib/overload/integer.rb +2 -2
  58. data/lib/overload/it.rb +4 -4
  59. data/lib/overload/object.rb +37 -8
  60. data/lib/overload/{r.rb → raise_variants.rb} +23 -4
  61. data/lib/overload/string.rb +22 -6
  62. data/misc/demo/app/cells/demo_cell.rb +12 -0
  63. data/misc/demo/app/controllers/application_controller.rb +7 -0
  64. data/misc/demo/app/controllers/main/root_controller.rb +9 -0
  65. data/misc/demo/app/routes.rb +5 -0
  66. data/misc/demo/config/application.rb +14 -0
  67. data/misc/demo/config/assets.rb +6 -0
  68. data/misc/demo/config/environment.rb +7 -0
  69. data/misc/puma_auto_tune.rb +43 -0
  70. data/misc/unicorn.rb +37 -0
  71. data/{lib/lux → plugins}/api/api.rb +46 -29
  72. data/plugins/api/lib/attr.rb +31 -0
  73. data/{lib/lux → plugins}/api/lib/dsl.rb +3 -6
  74. data/{lib/lux → plugins}/api/lib/error.rb +0 -0
  75. data/{lib/lux → plugins}/api/lib/model_api.rb +51 -12
  76. data/{lib/lux → plugins}/api/lib/response.rb +31 -17
  77. data/{bin/cli/am → plugins/db/auto_migrate/auto_migrate.rb} +18 -35
  78. data/plugins/db/helpers/array_search.rb +27 -0
  79. data/plugins/db/helpers/before_save_filters.rb +32 -0
  80. data/plugins/db/helpers/composite_primary_keys.rb +36 -0
  81. data/plugins/db/helpers/core.rb +94 -0
  82. data/plugins/db/helpers/dataset_methods.rb +138 -0
  83. data/plugins/db/helpers/enums_plugin.rb +52 -0
  84. data/plugins/db/helpers/find_precache.rb +31 -0
  85. data/plugins/db/helpers/link_objects.rb +84 -0
  86. data/plugins/db/helpers/schema_checks.rb +83 -0
  87. data/plugins/db/helpers/typero_adapter.rb +71 -0
  88. data/plugins/db/logger/config.rb +22 -0
  89. data/plugins/db/logger/lux_response_adapter.rb +10 -0
  90. data/plugins/db/paginate/helper.rb +32 -0
  91. data/plugins/db/paginate/sequel_adapter.rb +23 -0
  92. data/plugins/exceptions/simple_exception.rb +64 -0
  93. data/plugins/favicon/favicon.rb +10 -0
  94. data/plugins/html/html_form.rb +118 -0
  95. data/plugins/html/html_input.rb +98 -0
  96. data/plugins/html/html_menu.rb +79 -0
  97. data/plugins/html/input_types.rb +346 -0
  98. data/plugins/js_widgets/js_widgets.rb +15 -0
  99. data/plugins/oauth/lib/facebook.rb +35 -0
  100. data/plugins/oauth/lib/github.rb +38 -0
  101. data/plugins/oauth/lib/google.rb +41 -0
  102. data/plugins/oauth/lib/linkedin.rb +41 -0
  103. data/plugins/oauth/lib/stackexchange.rb +41 -0
  104. data/plugins/oauth/lib/twitter.rb +38 -0
  105. data/plugins/oauth/oauth.rb +42 -0
  106. data/{lib/common → plugins/policy}/policy.rb +6 -7
  107. data/tasks/loader.rb +49 -0
  108. metadata +151 -49
  109. data/bin/cli/assets +0 -41
  110. data/bin/cli/console +0 -51
  111. data/bin/cli/dev +0 -1
  112. data/bin/cli/eval +0 -24
  113. data/bin/cli/exceptions +0 -62
  114. data/bin/cli/generate +0 -86
  115. data/bin/cli/get +0 -5
  116. data/bin/cli/nginx +0 -34
  117. data/bin/cli/production +0 -1
  118. data/bin/cli/render +0 -18
  119. data/bin/cli/routes +0 -14
  120. data/bin/cli/server +0 -4
  121. data/bin/cli/stat +0 -1
  122. data/bin/cli/systemd +0 -36
  123. data/bin/txt/nginx.conf +0 -46
  124. data/bin/txt/siege-and-puma.txt +0 -3
  125. data/lib/common/base32.rb +0 -47
  126. data/lib/common/dynamic_class.rb +0 -28
  127. data/lib/common/folder_model.rb +0 -50
  128. data/lib/common/generic_model.rb +0 -62
  129. data/lib/lux/application/lib/plugs.rb +0 -10
  130. data/lib/lux/application/lib/route_test.rb +0 -64
  131. data/lib/lux/cache/lib/memcached.rb +0 -3
  132. data/lib/lux/cell/cell.rb +0 -261
  133. data/lib/lux/current/lib/static_file.rb +0 -103
  134. data/lib/lux/helper/helpers/application_helper.rb +0 -3
  135. data/lib/lux/helper/helpers/html_helper.rb +0 -3
  136. data/lib/overload/auto_loader.rb +0 -27
  137. data/lib/overload/module.rb +0 -10
  138. data/lib/overload/string_inflections.rb +0 -8
data/lib/overload/file.rb CHANGED
@@ -1,11 +1,6 @@
1
1
  class File
2
2
  class << self
3
- def write(name, data)
4
- File.open(name, 'w') { |f| f.write(data) }
5
- data
6
- end
7
-
8
- def change(name)
3
+ def change name
9
4
  data = File.read(name)
10
5
  data = yield data
11
6
  File.write(name, data)
data/lib/overload/hash.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../common/free_struct'
4
+
3
5
  class Hash
4
6
  def h
5
7
  Hashie::Mash.new(self)
@@ -9,13 +11,57 @@ class Hash
9
11
  HashWithIndifferentAccess.new(self)
10
12
  end
11
13
 
12
- def tag node=nil, text=nil
13
- HtmlTagBuilder.build self, node, text
14
- end
14
+ # readonly hash with .to_h
15
+ def to_readonly name=nil
16
+ Class.new.tap do |c|
17
+ c.define_singleton_method(:to_h) do
18
+ m_list = methods(false) - [:to_h]
19
+ m_list.inject({}) do |h,m|
20
+ h[m] = send(m)
21
+ h[m] = h[m].to_h if h[m].class == Class
22
+ h
23
+ end
24
+ end
25
+
26
+ each do |k, v|
27
+ v = v.to_readonly if v.class == Hash
28
+ c.define_singleton_method(k) { v }
29
+ end
30
+ end
31
+ end
32
+
33
+ # {...}.to_opts :name, :age
34
+ # {...}.to_opts name: String, age: Integer
35
+ def to_opts *keys
36
+ if keys.first.is_a?(Hash)
37
+ # if given Hash check opt class types
38
+ keys.first.each do |key, target_class|
39
+ source = self[key]
40
+
41
+ if target_class && !source.nil? && !source.is_a?(target_class)
42
+ raise ArgumentError.new(%[Expected argument :#{key} to be of type "#{target_class}" not "#{source.class}"])
43
+ end
44
+ end
15
45
 
16
- def to_struct name=nil
17
- name ||= ToStructGeneric
18
- Struct.new(name, *keys).new(*values)
46
+ keys = keys.first.keys
47
+ end
48
+
49
+ not_allowed = self.keys - keys
50
+ raise ArgumentError.new('Key :%s not allowed in option' % not_allowed.first) if not_allowed.first
51
+
52
+ FreeStruct.new keys.inject({}) { |total, key|
53
+ raise 'Hash key :%s is not allowed!' % key unless keys.include?(key)
54
+ total[key] = self[key]
55
+ total
56
+ }
57
+ end
58
+
59
+ def to_struct
60
+ to_opts *keys
61
+ end
62
+
63
+ def tag node=nil, text=nil
64
+ HtmlTagBuilder.build self, node, text
19
65
  end
20
66
 
21
67
  def blank?
@@ -29,6 +75,10 @@ class Hash
29
75
  }.join('&')
30
76
  end
31
77
 
78
+ def data_attributes
79
+ self.keys.sort.map{ |k| 'data-%s="%s"' % [k, self[k].to_s.gsub('"', '&quot;')]}.join(' ')
80
+ end
81
+
32
82
  def pluck *args
33
83
  string_args = args.map(&:to_s)
34
84
  self.select{ |k,v| string_args.index(k.to_s) }
@@ -74,13 +124,6 @@ class Hash
74
124
  omit
75
125
  end
76
126
 
77
- def to_opts! *keys
78
- self.keys.each { |key| raise 'Hash key :%s is not allowed!' % key unless keys.include?(key) }
79
-
80
- DynamicClass.new keys
81
- .inject({}) { |_, key| _[key] = self[key]; _ }
82
- end
83
-
84
127
  def pretty_generate
85
128
  JSON.pretty_generate(self).gsub(/"([\w\-]+)":/) { %["#{$1.yellow}":] }
86
129
  end
@@ -1,11 +1,11 @@
1
1
  class Integer
2
- def pluralize(desc)
2
+ def pluralize desc
3
3
  if self == 0
4
4
  "no #{desc.to_s.pluralize}"
5
5
  elsif self == 1
6
6
  "#{self} #{desc}"
7
7
  else
8
- "#{self} #{desc.to_s.pluralize}"
8
+ "#{self.dotted} #{desc.to_s.pluralize}"
9
9
  end
10
10
  end
11
11
 
data/lib/overload/it.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # class Array
2
+ # def it
3
+ # @_it
4
+ # end
5
+
2
6
  # # list.xeach { it.foo }
3
7
  # def xeach &block
4
- # define_singleton_method(:it) { @_it } unless respond_to?(:it)
5
8
  # each do |_|
6
9
  # @_it = _
7
10
  # instance_eval &block
@@ -10,7 +13,6 @@
10
13
 
11
14
  # # list.xmap { it * 2 }
12
15
  # def xmap &block
13
- # define_singleton_method(:it) { @_it } unless respond_to?(:it)
14
16
  # map do |_|
15
17
  # @_it = _
16
18
  # instance_eval &block
@@ -19,11 +21,9 @@
19
21
 
20
22
  # # list.xselect { it.class != Module }
21
23
  # def xselect &block
22
- # define_singleton_method(:it) { @_it } unless respond_to?(:it)
23
24
  # select do |_|
24
25
  # @_it = _
25
26
  # instance_eval &block
26
27
  # end
27
28
  # end
28
-
29
29
  # end
@@ -1,5 +1,27 @@
1
1
  class Object
2
2
 
3
+ def self.const_missing klass
4
+ file = klass.to_s.tableize.singularize
5
+ paths = [
6
+ 'models',
7
+ 'lib',
8
+ 'lib/vendor',
9
+ 'vendor',
10
+ file.split('_').last.pluralize
11
+ ].map { |it| './app/%s/%s.rb' % [it, file] }
12
+
13
+ klass_file = paths.find { |it| File.exist?(it) } or
14
+ raise NameError.new('Can not find and autoload class "%s", looked in %s' % [klass, paths.map{ |it| "\n#{it}" }.join('')])
15
+
16
+ # puts '* autoload: %s from %s' % [file, klass_file]
17
+
18
+ require klass_file
19
+
20
+ Object.const_get(klass)
21
+ end
22
+
23
+ ###
24
+
3
25
  def or _or
4
26
  self.blank? || self == 0 ? _or : self
5
27
  end
@@ -13,6 +35,7 @@ class Object
13
35
  desc ||= 'died without desc'
14
36
  desc = '%s: %s' % [exp_object.class, desc] if exp_object
15
37
  puts desc.red
38
+ puts caller.slice(0, 10)
16
39
  raise desc
17
40
  end
18
41
 
@@ -49,14 +72,20 @@ class Object
49
72
  self.class == TrueClass || self.class == FalseClass
50
73
  end
51
74
 
52
- end
53
-
54
- # if we dont have awesome print in prodction, define mock
55
- method(:ap) rescue Proc.new do
56
- class Object
57
- def ap(*args)
58
- puts args
75
+ def andand func=nil
76
+ if present?
77
+ if block_given?
78
+ yield(self)
79
+ else
80
+ func ? send(func) : self
81
+ end
82
+ else
83
+ block_given? || func ? nil : {}.h
59
84
  end
60
85
  end
61
- end.call
86
+
87
+ def instance_variables_hash
88
+ Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
89
+ end
90
+ end
62
91
 
@@ -18,7 +18,8 @@ class Object
18
18
 
19
19
  # better console log dump
20
20
  def rr what
21
- ap ['--- START (%s) ---' % what.class, what, '--- END ---']
21
+ src = caller[0].sub(Lux.root.to_s+'/', '').sub(Lux.fw_root.to_s, 'lux-fw').split(':in `').first
22
+ ap ['--- START (%s) %s ---' % [what.class, src], what, '--- END ---']
22
23
  end
23
24
 
24
25
  # unique methods for object
@@ -52,7 +53,25 @@ class Object
52
53
  rr what
53
54
  end
54
55
 
55
- def instance_variables_hash
56
- Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
56
+ # show method info
57
+ # show User, :secure_hash
58
+ def rr? instance, m
59
+ el = instance.class.instance_method(m)
60
+ puts el.source_location.join(':').yellow
61
+ puts '-'
62
+ puts el.source if el.respond_to?(:source)
63
+ nil
57
64
  end
58
- end
65
+ end
66
+
67
+ ###
68
+
69
+ # if we dont have awesome print in prodction, define mock
70
+ method(:ap) rescue Proc.new do
71
+ class Object
72
+ def ap(*args)
73
+ puts args
74
+ end
75
+ end
76
+ end.call
77
+
@@ -1,4 +1,8 @@
1
1
  class String
2
+ def constantize
3
+ Object.const_get('::'+self)
4
+ end
5
+
2
6
  # simple markdown
3
7
  def as_html
4
8
  self.gsub($/, '<br />')
@@ -18,15 +22,15 @@ class String
18
22
  data
19
23
  end
20
24
 
21
- def sanitize
22
- Sanitize.clean(self, :elements=>%w[span ul ol li b bold i italic u underline hr br p], :attributes=>{'span'=>['style']} )
25
+ def first
26
+ self[0,1]
23
27
  end
24
28
 
25
- def tag(node_name, opts={})
26
- opts.tag(node_name, self)
29
+ def sanitize
30
+ Sanitize.clean(self, :elements=>%w[span ul ol li b bold i italic u underline hr br p], :attributes=>{'span'=>['style']} )
27
31
  end
28
32
 
29
- def wrap(node_name, opts={})
33
+ def wrap node_name, opts={}
30
34
  return self unless node_name
31
35
  opts.tag(node_name, self)
32
36
  end
@@ -63,10 +67,14 @@ class String
63
67
  self.split(/\s*,\s*/)
64
68
  end
65
69
 
66
- def starts_with?(prefix)
70
+ def starts_with? prefix
67
71
  prefix.respond_to?(:to_str) && self[0, prefix.length] == prefix
68
72
  end
69
73
 
74
+ def ends_with? suffix
75
+ suffix.is_a?(String) && self[-suffix.length, suffix.length] == suffix && self != suffix
76
+ end
77
+
70
78
  def last(num=1)
71
79
  len = self.length
72
80
  self[len-num, len]
@@ -84,4 +92,12 @@ class String
84
92
  def decolorize
85
93
  self.gsub(/\[0;\d\d;\d\dm([^\[]*)\[0m/) { $1 }
86
94
  end
95
+
96
+ def escape
97
+ CGI::escape self
98
+ end
99
+
100
+ def unescape
101
+ CGI::unescape self
102
+ end
87
103
  end
@@ -0,0 +1,12 @@
1
+ class DemoCell < ViewCell
2
+
3
+ def time
4
+ Time.now
5
+ end
6
+
7
+ def render time
8
+ @time = time.to_i
9
+ template :demo
10
+ end
11
+
12
+ end
@@ -0,0 +1,7 @@
1
+ class ApplicationContrller < Lux::Controller
2
+
3
+ end
4
+
5
+ class Main
6
+
7
+ end
@@ -0,0 +1,9 @@
1
+ class Main::RootController < ApplicationContrller
2
+
3
+ mock :about
4
+
5
+ def index
6
+ @title = 'Yay, you are on Lux'
7
+ end
8
+
9
+ end
@@ -0,0 +1,5 @@
1
+ Lux.app do
2
+ routes do
3
+ root 'main/root#index'
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'environment'
2
+
3
+ ###
4
+
5
+ Lux.config.secret = 'secret'
6
+ Lux.config.host = 'http://localhost:3000'
7
+
8
+ ###
9
+
10
+ Lux.require_all './app'
11
+
12
+ ###
13
+
14
+ Lux.start
@@ -0,0 +1,6 @@
1
+ asset :main do
2
+ css do
3
+ add 'css/main/*'
4
+ add './app/cells/**'
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+ require 'dotenv'
3
+
4
+ Dotenv.load
5
+
6
+ Bundler.require :default, ENV.fetch('RACK_ENV')
7
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ # Instantiate about one process per X MiB of available memory, scaling up to as
3
+ # close to MAX_THREADS as possible while observing an upper bound based on the
4
+ # number of virtual/logical CPUs. If there are fewer processes than
5
+ # MAX_THREADS, add threads per process to reach MAX_THREADS.
6
+ require 'etc'
7
+
8
+ KB_PER_WORKER = 64 * 1_024 # average of peak PSS of single-threaded processes (watch smem -k)
9
+ MIN_WORKERS = 2
10
+ MAX_WORKERS_PER_VCPU = 1.25 # virtual/logical
11
+ MIN_THREADS_PER_WORKER = 1
12
+ MAX_THREADS = Integer(ENV['MAX_CONCURRENCY'] || 256)
13
+
14
+ def meminfo arg
15
+ File.open('/proc/meminfo') do |f|
16
+ f.each_line do |line|
17
+ key, value = line.split(/:\s+/)
18
+ return value.split(/\s+/).first.to_i if key == arg
19
+ end
20
+ end
21
+
22
+ raise "Unable to find `#{arg}' in /proc/meminfo!"
23
+ rescue
24
+ 1_000_000
25
+ end
26
+
27
+ def auto_tune
28
+ avail_mem = meminfo('MemAvailable') * 0.8 - MAX_THREADS * 1_024
29
+
30
+ workers = [
31
+ [(1.0 * avail_mem / KB_PER_WORKER).floor, MIN_WORKERS].max,
32
+ (Etc.nprocessors * MAX_WORKERS_PER_VCPU).ceil
33
+ ].min
34
+
35
+ threads_per_worker = [
36
+ workers < MAX_THREADS ? (1.0 * MAX_THREADS / workers).ceil : -Float::INFINITY,
37
+ MIN_THREADS_PER_WORKER
38
+ ].max
39
+
40
+ [workers, threads_per_worker]
41
+ end
42
+
43
+ p auto_tune if $0 == __FILE__
data/misc/unicorn.rb ADDED
@@ -0,0 +1,37 @@
1
+ # set path to application
2
+ app_dir = File.expand_path("../..", __FILE__)
3
+ working_directory app_dir
4
+
5
+ # Set unicorn options
6
+ worker_processes 10
7
+ preload_app true
8
+ timeout 20
9
+
10
+ # Set up socket location
11
+ listen "127.0.0.1:3000", :tcp_nopush => true
12
+ listen "#{app_dir}/tmp/unicorn.sock", :backlog => 512
13
+
14
+ # Logging
15
+ stderr_path "#{app_dir}/log/unicorn.stderr.log"
16
+ stdout_path "#{app_dir}/log/unicorn.stdout.log"
17
+
18
+ # Set master PID location
19
+ pid "#{app_dir}/tmp/unicorn.pid"
20
+
21
+ worker_processes 5
22
+ timeout 15
23
+
24
+ preload_app true
25
+
26
+ GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
27
+
28
+ check_client_connection false
29
+
30
+ before_exec do |server|
31
+ end
32
+
33
+ before_fork do |server, worker|
34
+ end
35
+
36
+ after_fork do |server, worker|
37
+ end
@@ -12,21 +12,26 @@
12
12
  class Lux::Api
13
13
  attr_accessor :message, :response
14
14
 
15
- ClassCallbacks.define self, :before, :after, :on_error
15
+ class_callback :before
16
+ class_callback :after
16
17
 
17
18
  class << self
18
19
  # public mount method for router
19
- def call path
20
- return 'Unsupported API call' if !path[1] || path[3]
21
-
22
- opts = Lux.current.params # Lux.current.request.post? ? Rack::Utils.parse_nested_query(Lux.current.request.body.read).h : Lux.current.params
20
+ def call path, opts={}
21
+ if path.is_a?(Symbol)
22
+ # TestApi.call(:foo, email: '...')
23
+ new.call path, opts
24
+ else
25
+ # Lux::Api.call([:user, :profile], email: '...' )
26
+ return error 'Unsupported API call' if !path[1] || path[3]
27
+
28
+ if path[2]
29
+ opts[:_id] = path[1]
30
+ path[1] = path[2]
31
+ end
23
32
 
24
- if path[2]
25
- opts[:_id] = path[1]
26
- path[1] = path[2]
33
+ run path[0], path[1], opts
27
34
  end
28
-
29
- Lux.current.response.body run(path[0], path[1], opts)
30
35
  end
31
36
 
32
37
  # public method for running actions on global class
@@ -43,7 +48,7 @@ class Lux::Api
43
48
  begin
44
49
  params.merge! params.delete(class_name.underscore)
45
50
  rescue
46
- error "#{$!.message}. Domain value is probably not hash, invalid parameter #{class_name.underscore}"
51
+ return error "#{$!.message}. Domain value is probably not hash, invalid parameter #{class_name.underscore}"
47
52
  end
48
53
  end
49
54
 
@@ -54,11 +59,15 @@ class Lux::Api
54
59
  begin
55
60
  klass = (klass.singularize.camelize+'Api').constantize
56
61
  rescue
57
- return Lux.current.response.body({ error:"API #{klass} not found" })
62
+ return error "API #{klass} not found"
58
63
  end
59
64
 
60
65
  klass.new.call(action.to_sym, params)
61
66
  end
67
+
68
+ def error message
69
+ Lux::Api::Response.error message
70
+ end
62
71
  end
63
72
 
64
73
  ###
@@ -69,44 +78,39 @@ class Lux::Api
69
78
  rescue Lux::Api::Error => e
70
79
  response.error e.message if e.message.to_s != 'false'
71
80
  rescue => e
72
- rr [e.message, e.backtrace] if Lux.config(:log_to_stdout)
73
-
74
- ClassCallbacks.execute self, :on_error, e
75
-
76
- response.error e.message
81
+ on_error(e)
77
82
  end
78
83
 
84
+ puts response.render.pretty_generate if Lux.config(:log_to_stdout)
85
+
79
86
  response.render
80
87
  end
81
88
 
82
89
  # internal method for running actions
83
90
  # UserApi.new.call(:login, { email:'', pass:'' })
84
91
  def rescued_call action, params={}
85
- raise ForbidenError, "Protected action call" if [:call, :rescued_call, :params, :error].index action
86
- error("Action #{action} not found in #{self.class.to_s}") unless respond_to? action
87
-
88
92
  @response = Lux::Api::Response.new
89
93
  @params = params
94
+ @action = action
90
95
  @class_name = self.class.to_s.sub(/Api$/,'')
91
96
 
97
+ error("Protected action call") if [:call, :rescued_call, :params, :error].index action
98
+ error("Action #{action} not found in #{self.class.to_s}") unless respond_to? action
99
+
92
100
  # load default object
93
101
  if @params[:_id]
94
102
  eval "@object = @#{@class_name.underscore} = #{@class_name}[@params[:_id].to_i]"
95
103
  @params.delete(:_id)
96
104
  end
97
105
 
98
- check_params_and_mock_instance_variables action
106
+ @method_attr = self.class.method_attr[action] || {}
99
107
 
100
108
  return if response.errors?
101
109
 
102
110
  # execte api call and verify params if possible
103
- ClassCallbacks.execute(self, :before)
104
-
105
- response.data = send(action)
106
-
107
- ClassCallbacks.execute(self, :after)
108
-
109
- puts response.render.pretty_generate if Lux.config.log_to_stdout
111
+ Object.class_callback :before, self
112
+ response.data = send(action) unless response.errors?
113
+ Object.class_callback :after, self unless response.errors?
110
114
  end
111
115
 
112
116
  def params
@@ -121,6 +125,10 @@ class Lux::Api
121
125
  response.message = what
122
126
  end
123
127
 
128
+ def current
129
+ Lux.current
130
+ end
131
+
124
132
  # default after block, can be overloaded
125
133
  def after
126
134
  return unless Lux.current
@@ -130,7 +138,16 @@ class Lux::Api
130
138
  response.meta :http_status, Lux.current.response.status(200)
131
139
  end
132
140
 
141
+ def on_error error
142
+ response.meta :error_key, Lux.error.log(error)
143
+ response.meta :error_class, error.class.to_s
144
+ response.error error.message
145
+ end
146
+
133
147
  end
134
148
 
135
- ApplicationApi = Class.new Lux::Api
149
+ ApplicationApi ||= Class.new Lux::Api
150
+
151
+
152
+
136
153
 
@@ -0,0 +1,31 @@
1
+ # - in ApplicationApi, class level
2
+ # api_attr :secure_token do |name|
3
+ # error 'User session required' unless User.current
4
+ # error 'Secure token not found' unless params[:secure_token]
5
+ # error 'Invalid secure token' if User.current.secure_token(name) != params.delete(:secure_token)
6
+ # end
7
+
8
+ # - in object api, instance level
9
+ # secure_token :delete
10
+ # def delete_me
11
+ # 'ok'
12
+ # end
13
+
14
+ class ApplicationApi
15
+ API_ATTR ||= {}
16
+
17
+ def self.api_attr name, &block
18
+ method_attr name
19
+
20
+ API_ATTR[name] = block
21
+ end
22
+
23
+ ## api_attr check
24
+ before do
25
+ for method_attr_name, block in API_ATTR
26
+ for data in @method_attr[method_attr_name].or([])
27
+ instance_exec data, &block
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
- class Lux::Api
1
+ class ApplicationApi
2
2
  # name 'Show user data'
3
3
  # param :email, type: :email, req: false
4
4
  # param :pass
@@ -28,10 +28,7 @@ class Lux::Api
28
28
 
29
29
  ###
30
30
 
31
- def check_params_and_mock_instance_variables action
32
- @method_attr = self.class.method_attr[action] || {}
33
-
34
- # params check if framework default
31
+ before do
35
32
  if @method_attr[:param]
36
33
  local = @method_attr[:param].inject({}) { |h, el| o=el.dup; h[o.delete(:name)] = o; h }
37
34
  rules = Typero.new local
@@ -41,7 +38,7 @@ class Lux::Api
41
38
  raise ArgumentError.new(errors.values.to_sentence) unless Lux.current
42
39
 
43
40
  Lux.current.response.status 400
44
- return response.error errors.values.to_sentence
41
+ error errors.values.to_sentence
45
42
  end
46
43
 
47
44
  # define local prefixed @_ variables
File without changes