lux-fw 0.5.36 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/bin/README.md +26 -13
  4. data/bin/cli/benchmark.rb +18 -0
  5. data/bin/cli/cerb.rb +90 -0
  6. data/bin/cli/config.rb +4 -11
  7. data/bin/cli/console.rb +72 -30
  8. data/bin/cli/eval.rb +5 -27
  9. data/bin/cli/generate.rb +9 -11
  10. data/bin/cli/get.rb +14 -6
  11. data/bin/cli/memory.rb +12 -0
  12. data/bin/cli/new.rb +2 -0
  13. data/bin/cli/secrets.rb +3 -31
  14. data/bin/cli/server.rb +28 -9
  15. data/bin/cli/stats.rb +26 -20
  16. data/bin/cli/template.rb +10 -0
  17. data/bin/generate_doc +168 -0
  18. data/bin/lux +73 -10
  19. data/lib/README.md +18 -8
  20. data/lib/common/crypt.rb +60 -9
  21. data/lib/common/string_base.rb +54 -15
  22. data/lib/common/struct_opts.rb +30 -0
  23. data/lib/common/time_difference.rb +75 -0
  24. data/lib/loader.rb +41 -0
  25. data/lib/lux/application/README.md +67 -105
  26. data/lib/lux/application/application.rb +87 -329
  27. data/lib/lux/application/lib/magic_routes.rb +22 -0
  28. data/lib/lux/application/lib/nav.rb +218 -99
  29. data/lib/lux/application/lib/render.rb +47 -67
  30. data/lib/lux/application/lib/routes.rb +242 -0
  31. data/lib/lux/application/lib/shared.rb +47 -0
  32. data/lib/lux/application/lux_adapter.rb +6 -0
  33. data/lib/lux/application/lux_config.rb +26 -0
  34. data/lib/lux/cache/Find Results +24 -0
  35. data/lib/lux/cache/README.md +28 -35
  36. data/lib/lux/cache/cache.rb +78 -26
  37. data/lib/lux/cache/lib/memcached_server.rb +36 -0
  38. data/lib/lux/cache/lib/memory_server.rb +44 -0
  39. data/lib/lux/cache/lib/null_server.rb +33 -0
  40. data/lib/lux/cache/lib/sqlite_server.rb +62 -0
  41. data/lib/lux/cache/lux_adapter.rb +19 -0
  42. data/lib/lux/config/config.rb +93 -144
  43. data/lib/lux/config/lux_adapter.rb +27 -0
  44. data/lib/lux/controller/README.md +67 -12
  45. data/lib/lux/controller/controller.rb +237 -187
  46. data/lib/lux/current/README.md +29 -10
  47. data/lib/lux/current/current.rb +166 -77
  48. data/lib/lux/current/lib/current.rb +6 -0
  49. data/lib/lux/current/lib/encrypt_params.rb +38 -36
  50. data/lib/lux/current/lib/session.rb +86 -65
  51. data/lib/lux/current/lux_adapter.rb +5 -0
  52. data/lib/lux/environment/README.md +24 -0
  53. data/lib/lux/environment/environment.rb +91 -0
  54. data/lib/lux/environment/lux_adapter.rb +13 -0
  55. data/lib/lux/error/README.md +18 -19
  56. data/lib/lux/error/error.rb +207 -152
  57. data/lib/lux/error/lux_adapter.rb +9 -0
  58. data/lib/lux/logger/README.md +45 -0
  59. data/lib/lux/logger/lux_adapter.rb +27 -0
  60. data/lib/lux/lux.rb +72 -129
  61. data/lib/lux/mailer/README.md +12 -5
  62. data/lib/lux/mailer/lux_config.rb +4 -0
  63. data/lib/lux/mailer/mailer.rb +81 -59
  64. data/lib/lux/plugin/README.md +19 -0
  65. data/lib/lux/plugin/lux_adapter.rb +8 -0
  66. data/lib/lux/plugin/plugin.rb +65 -0
  67. data/lib/lux/render/README.md +100 -0
  68. data/lib/lux/render/render.rb +12 -0
  69. data/lib/lux/response/README.md +57 -1
  70. data/lib/lux/response/lib/file.rb +87 -65
  71. data/lib/lux/response/lib/flash.rb +49 -34
  72. data/lib/lux/response/lib/header.rb +34 -33
  73. data/lib/lux/response/response.rb +252 -164
  74. data/lib/lux/template/helper.rb +130 -0
  75. data/lib/lux/template/inline_render_proxy.rb +31 -0
  76. data/lib/lux/template/lux_adapter.rb +5 -0
  77. data/lib/lux/template/template.rb +127 -0
  78. data/lib/lux-fw.rb +15 -33
  79. data/lib/overload/array.rb +33 -7
  80. data/lib/overload/blank.rb +8 -3
  81. data/lib/overload/boolean.rb +46 -0
  82. data/lib/overload/class.rb +28 -0
  83. data/lib/overload/dir.rb +117 -7
  84. data/lib/overload/file.rb +40 -5
  85. data/lib/overload/float.rb +38 -3
  86. data/lib/overload/hash.rb +81 -91
  87. data/lib/overload/integer.rb +15 -0
  88. data/lib/overload/json.rb +26 -0
  89. data/lib/overload/nil.rb +4 -8
  90. data/lib/overload/object.rb +91 -24
  91. data/lib/overload/pathname.rb +11 -0
  92. data/lib/overload/raise_variants.rb +26 -36
  93. data/lib/overload/string.rb +100 -27
  94. data/lib/overload/thread_simple.rb +100 -0
  95. data/lib/overload/time.rb +60 -38
  96. data/tasks/loader.rb +20 -7
  97. metadata +170 -169
  98. data/bin/.DS_Store +0 -0
  99. data/bin/build_gem +0 -77
  100. data/bin/cli/dbconsole.rb +0 -8
  101. data/bin/cli/routes.rb +0 -90
  102. data/lib/.DS_Store +0 -0
  103. data/lib/common/.DS_Store +0 -0
  104. data/lib/common/class_attributes.rb +0 -51
  105. data/lib/common/class_callbacks.rb +0 -47
  106. data/lib/common/free_struct.rb +0 -42
  107. data/lib/common/hash_with_indifferent_access.rb +0 -74
  108. data/lib/common/html_tag_builder.rb +0 -91
  109. data/lib/common/method_attr.rb +0 -69
  110. data/lib/common/url.rb +0 -191
  111. data/lib/lux/.DS_Store +0 -0
  112. data/lib/lux/README.md +0 -10
  113. data/lib/lux/cache/.DS_Store +0 -0
  114. data/lib/lux/cache/lib/memory.rb +0 -36
  115. data/lib/lux/cache/lib/null.rb +0 -21
  116. data/lib/lux/config/README.md +0 -63
  117. data/lib/lux/config/lib/plugin.rb +0 -65
  118. data/lib/lux/config/lib/secrets.rb +0 -48
  119. data/lib/lux/current/.DS_Store +0 -0
  120. data/lib/lux/delayed_job/.DS_Store +0 -0
  121. data/lib/lux/delayed_job/README.md +0 -3
  122. data/lib/lux/delayed_job/delayed_job.rb +0 -51
  123. data/lib/lux/delayed_job/lib/memory.rb +0 -16
  124. data/lib/lux/delayed_job/lib/nsq.rb +0 -3
  125. data/lib/lux/delayed_job/lib/postgre.rb +0 -6
  126. data/lib/lux/delayed_job/lib/redis.rb +0 -19
  127. data/lib/lux/event_bus/README.md +0 -36
  128. data/lib/lux/event_bus/event_bus.rb +0 -27
  129. data/lib/lux/view/README.md +0 -85
  130. data/lib/lux/view/cell.rb +0 -102
  131. data/lib/lux/view/helper.rb +0 -120
  132. data/lib/lux/view/lib/cell_helpers.rb +0 -29
  133. data/lib/lux/view/view.rb +0 -95
  134. data/lib/overload/it.rb +0 -29
  135. data/plugins/api/README.md +0 -49
  136. data/plugins/api/api.rb +0 -153
  137. data/plugins/api/lib/attr.rb +0 -31
  138. data/plugins/api/lib/dsl.rb +0 -52
  139. data/plugins/api/lib/error.rb +0 -3
  140. data/plugins/api/lib/model_api.rb +0 -203
  141. data/plugins/api/lib/response.rb +0 -85
  142. data/plugins/db/.DS_Store +0 -0
  143. data/plugins/db/README.md +0 -29
  144. data/plugins/db/auto_migrate/auto_migrate.rb +0 -268
  145. data/plugins/db/auto_migrate/db.rake +0 -15
  146. data/plugins/db/helpers/array_search.rb +0 -27
  147. data/plugins/db/helpers/before_save_filters.rb +0 -32
  148. data/plugins/db/helpers/composite_primary_keys.rb +0 -36
  149. data/plugins/db/helpers/core.rb +0 -94
  150. data/plugins/db/helpers/dataset_methods.rb +0 -138
  151. data/plugins/db/helpers/enums_plugin.rb +0 -52
  152. data/plugins/db/helpers/find_precache.rb +0 -31
  153. data/plugins/db/helpers/link_objects.rb +0 -84
  154. data/plugins/db/helpers/schema_checks.rb +0 -83
  155. data/plugins/db/helpers/typero_adapter.rb +0 -71
  156. data/plugins/db/logger/config.rb +0 -22
  157. data/plugins/db/logger/lux_response_adapter.rb +0 -10
  158. data/plugins/db/paginate/helper.rb +0 -32
  159. data/plugins/db/paginate/sequel_adapter.rb +0 -23
  160. data/plugins/exceptions/exceptions.rake +0 -43
  161. data/plugins/exceptions/simple_exception.rb +0 -64
  162. data/plugins/favicon/favicon.rb +0 -10
  163. data/plugins/html/README.md +0 -3
  164. data/plugins/html/html_form.rb +0 -118
  165. data/plugins/html/html_input.rb +0 -98
  166. data/plugins/html/html_menu.rb +0 -79
  167. data/plugins/html/input_types.rb +0 -346
  168. data/plugins/js_widgets/README.md +0 -5
  169. data/plugins/js_widgets/js/html_tag.coffee +0 -42
  170. data/plugins/js_widgets/js/widgets.coffee +0 -161
  171. data/plugins/js_widgets/js_widgets.rb +0 -15
  172. data/plugins/oauth/lib/facebook.rb +0 -35
  173. data/plugins/oauth/lib/github.rb +0 -38
  174. data/plugins/oauth/lib/google.rb +0 -41
  175. data/plugins/oauth/lib/linkedin.rb +0 -41
  176. data/plugins/oauth/lib/stackexchange.rb +0 -41
  177. data/plugins/oauth/lib/twitter.rb +0 -38
  178. data/plugins/oauth/oauth.rb +0 -42
  179. data/plugins/policy/policy.rb +0 -53
  180. data/tasks/nginx.rake +0 -23
  181. /data/lib/lux/{view/lib → mailer}/helper_modules.rb +0 -0
data/lib/lux/lux.rb CHANGED
@@ -1,165 +1,108 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../common/class_callbacks'
4
- require_relative 'cache/cache'
5
-
6
1
  module ::Lux
7
2
  extend self
8
3
 
9
- ENV_PROD = ENV['RACK_ENV'] == 'production' unless defined?(ENV_PROD)
10
- CACHE_SERVER ||= Lux::Cache.new
11
- VERSION ||= File.read File.expand_path('../../../.version', __FILE__).chomp
12
- CONFIG ||= Hashie::Mash.new
13
- APP_ROOT ||= Pathname.new(Dir.pwd).freeze
14
- FW_ROOT ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__))).freeze
15
- EVENTS ||= {}
16
- MCACHE ||= {}
17
-
18
- BACKGROUND_THREADS ||= []
19
- # Kernel.at_exit { BACKGROUND_THREADS.each { |t| t.join } }
20
-
21
- define_method(:cli?) { !@rackup_start }
22
- define_method(:test?) { ENV['RACK_ENV'] == 'test' }
23
- define_method(:prod?) { ENV_PROD }
24
- define_method(:production?) { ENV_PROD }
25
- define_method(:dev?) { !ENV_PROD }
26
- define_method(:development?) { !ENV_PROD }
27
- define_method(:cache) { CACHE_SERVER }
28
- define_method(:secrets) { @secrets ||= Lux::Config::Secrets.new.load }
29
- define_method(:root) { APP_ROOT }
30
- define_method(:fw_root) { FW_ROOT }
31
- define_method(:event) { Lux::EventBus }
32
- define_method(:require_all) { |folder| Lux::Config.require_all folder }
4
+ VERSION ||= File.read File.expand_path('../../../.version', __FILE__).chomp
5
+
6
+ def root
7
+ @lux_app_root ||= Pathname.new(ENV.fetch('APP_ROOT') { Dir.pwd }).freeze
8
+ end
9
+
10
+ def fw_root
11
+ @lux_fw_root ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__))).freeze
12
+ end
33
13
 
34
14
  # main rack response
35
- def call env=nil
36
- state = Lux::Current.new env
37
- app = Lux::Application.new state
38
- app.render
39
- rescue => error
40
- if Lux.config(:dump_errors)
41
- raise error
42
- else
43
- log error.backtrace
44
- [500, {}, ['Server error: %s' % error.message]]
15
+ def call env = nil
16
+ Timeout::timeout Lux::Config.app_timeout do
17
+ app = Lux::Application.new env
18
+ app.render_base || raise('No RACK response given')
45
19
  end
46
- end
20
+ rescue => err
21
+ Lux::Error.log err
47
22
 
48
- def env key=nil
49
- if key
50
- value = ENV[key]
51
- die "ENV['#{key}'] not found" if value.nil?
52
- value
23
+ if Lux.env.show_errors?
24
+ raise err
53
25
  else
54
- ENV['RACK_ENV']
26
+ [500, {}, ['Server error: %s' % err.message]]
55
27
  end
56
28
  end
57
29
 
58
- def config key=nil
59
- if key
60
- value = CONFIG[key]
61
- die 'Lux.config.%s not found' % key if value.nil?
62
- value.kind_of?(Proc) ? value.call() : value
30
+ # simple block to calc block execution speed
31
+ def speed
32
+ render_start = Time.monotonic
33
+ yield
34
+ num = (Time.monotonic - render_start) * 1000
35
+ if num > 1000
36
+ '%s sec' % (num/1000).round(2)
63
37
  else
64
- CONFIG
38
+ '%s ms' % num.round(1)
65
39
  end
66
40
  end
67
41
 
68
- def current
69
- Thread.current[:lux][:page] ||= Lux::Current.new('/mock')
70
- end
71
-
72
- def current=(what)
73
- Thread.current[:lux][:page] = what
42
+ def info text
43
+ if text.class == Array
44
+ text.each {|line| self.info line }
45
+ else
46
+ puts '* %s' % text.magenta
47
+ end
74
48
  end
75
49
 
76
- def app &block
77
- block ? Lux::Application.class_eval(&block) : Lux::Application
50
+ # Cdn.run has maybe better runner, inspect
51
+ def run command, get_result = false
52
+ puts command.light_black
53
+ logger(:system_run).info command
54
+ get_result ? `${command}` : system(command)
78
55
  end
79
56
 
80
- def error data=nil
81
- data ? Lux::Error.render(data) : Lux::Error
57
+ def die text
58
+ puts "Lux FATAL: #{text}".red
59
+ logger(:system_die).error text
60
+ exit
82
61
  end
83
62
 
84
- # simple log to stdout
85
- def log what=nil
86
- return unless Lux.config(:log_to_stdout)
87
- puts what || yield
63
+ def app_caller
64
+ app_line = caller.find { |line| !line.include?('/lux-') && !line.include?('/.') && !line.include?('(eval)') }
65
+ app_line ? app_line.split(':in ').first.sub(Lux.root.to_s, '.') : nil
88
66
  end
89
67
 
90
- # simple interface to plugins
91
- # Lux.plugin :foo
92
- # Lux.plugin
93
- def plugin *args
94
- args.first ? Lux::Config::Plugin.load(*args) : Lux::Config::Plugin
95
- end
68
+ def delay time_to_live = nil
69
+ Thread.new do
70
+ time_to_live ||= Lux.config.delay_timeout
96
71
 
97
- # if block given, simple new thread bg job
98
- # if string given, eval it in bg
99
- # if object given, instance it and run it
100
- def delay *args, &block
101
- if block_given?
102
- puts 'add'
103
-
104
- t = Thread.new do
105
- begin
106
- block.call
107
- rescue => e
108
- Lux.logger(:delay_errors).error [e.message, e.backtrace]
109
- end
72
+ unless time_to_live.is_a?(Numeric)
73
+ raise 'Time to live is not integer (seconds)'
110
74
  end
111
75
 
112
- BACKGROUND_THREADS.push t
113
- elsif args[0]
114
- # Lux.delay(mail_object, :deliver)
115
- Lux::DelayedJob.push(*args)
116
- else
117
- Lux::DelayedJob
76
+ Timeout::timeout time_to_live do
77
+ yield
78
+ end
118
79
  end
119
80
  end
81
+ end
120
82
 
121
- # load rake tasks + including ones in plugins
122
- def load_tasks
123
- require_relative '../../tasks/loader.rb'
124
- end
125
-
126
- # in memory cache, used on app init, no need for Mutex
127
- def ram_cache key
128
- MCACHE[key] = nil if Lux.config(:compile_assets)
129
- MCACHE[key] ||= yield
130
- end
131
-
132
- # initialize the Lux application
133
- def start
134
- Lux.config.lux_config_loaded = true
83
+ ###
135
84
 
136
- Config.start!
85
+ def Lux
86
+ if self.class == Rack::Builder
87
+ $rack_handler = self
88
+ run Lux
89
+ puts Lux::Config.start_info
90
+ else
91
+ raise 'Lux error: Rack not found'
137
92
  end
93
+ end
138
94
 
139
- # must be called when serving web pages from rackup
140
- def serve rack_handler
141
- @rackup_start = true
142
- Object.class_callback :web_boot, Lux::Application, rack_handler
143
- rack_handler.run self
144
- end
95
+ ###
145
96
 
146
- # simple block to calc block execution speed
147
- def speed
148
- render_start = Time.monotonic
149
- yield
150
- num = (Time.monotonic - render_start) * 1000
151
- '%s ms' % num.round(1)
152
- end
97
+ require_relative 'environment/environment'
98
+ require_relative 'environment/lux_adapter'
153
99
 
154
- # Lux.logger(:foo).warn 'bar'
155
- def logger name=nil
156
- name ||= ENV.fetch('RACK_ENV').downcase
100
+ require_relative 'config/config'
101
+ require_relative 'config/lux_adapter'
157
102
 
158
- MCACHE['lux-logger-%s' % name] ||=
159
- Logger.new('./log/%s.log' % name).tap do |it|
160
- it.formatter = Lux.config.logger_formater
161
- end
162
- end
103
+ if $lux_start_time
104
+ # for better start stats add $lux_start_time ||= Time.now to begginging of Gemfile
105
+ $lux_start_time = [$lux_start_time, Time.now]
106
+ else
107
+ $lux_start_time = Time.now
163
108
  end
164
-
165
- require_relative 'config/config'
@@ -1,4 +1,6 @@
1
- ## Lux::Mailer - send mails
1
+ ## Lux::Mailer
2
+
3
+ Light wrapper arrond [ruby mailer gem](https://github.com/mikel/mail).
2
4
 
3
5
  * before and after class methods are supported
4
6
  * before is called mail rendering started
@@ -16,7 +18,7 @@
16
18
  * execute after filter
17
19
  * deliver the mail
18
20
 
19
- ### Example
21
+ #### Example
20
22
 
21
23
  sugessted usage
22
24
 
@@ -39,13 +41,17 @@ Mailer.email_login('foo@bar.baz').deliver
39
41
  Mailer.email_login('foo@bar.baz').body
40
42
  ```
41
43
 
42
- ### Example code
44
+ #### Code
43
45
 
44
46
  ```ruby
45
47
  class Mailer < Lux::Mailer
46
48
  helper :mailer
47
49
 
48
- # before mail is sent
50
+ # before method call
51
+ before do
52
+ end
53
+
54
+ # after method call, but before mail is sent
49
55
  after do
50
56
  mail.from = "#{App.name} <no-reply@#{Lux.config.host}>"
51
57
  end
@@ -67,7 +73,8 @@ class Mailer < Lux::Mailer
67
73
  mail.subject = "#{App.name} – potvrda registracije"
68
74
  mail.to = email
69
75
 
70
- @link = "#{App.http_host}/profile/password?user_hash=#{Crypt.encrypt(email)}"
76
+ # instance variables will be pased to templaes
77
+ @link = "#{App.http_host}/profile/password?user_hash=#{Crypt.encrypt(email)}"
71
78
  end
72
79
  end
73
80
  ```
@@ -0,0 +1,4 @@
1
+ # Default mail logging
2
+ Lux.config.on_mail_send do |mail|
3
+ Lux.logger(:email).info "[#{self.class}.#{@_template} to #{mail.to}] #{mail.subject}"
4
+ end
@@ -10,79 +10,101 @@
10
10
  # Mailer.email_login('foo@bar.baz').deliver
11
11
  # Mailer.email_login('foo@bar.baz').body
12
12
 
13
- class Lux::Mailer
14
- class_callback :before
15
- class_callback :after
16
-
17
- class_attribute :helper
18
- class_attribute :layout, 'mailer'
19
-
20
- attr_reader :mail
21
-
22
- class << self
23
- # Mailer.prepare(:email_login, 'foo@bar.baz')
24
- def prepare template, *args
25
- obj = new
26
- obj.instance_variable_set :@_template, template
27
- Object.class_callback :before, obj
28
- obj.send template, *args
29
- Object.class_callback :after, obj
30
- obj
13
+ # if you want to cancel mail delivery - mail.to = false
14
+ module Lux
15
+ class Mailer
16
+ include ClassCallbacks
17
+
18
+ cattr :template_root, default: './app/views', class: true
19
+ cattr :helper, class: true
20
+ cattr :layout, default: 'mailer', class: true
21
+
22
+ define_callback :before
23
+ define_callback :after
24
+
25
+ attr_reader :mail
26
+
27
+ class << self
28
+ # Mailer.prepare(:email_login, 'foo@bar.baz')
29
+ def prepare template, *args
30
+ obj = new
31
+ obj.instance_variable_set :@_template, template
32
+ obj.run_callback :before
33
+
34
+ if args[0].class == Hash
35
+ obj.send template, **args[0]
36
+ else
37
+ obj.send template, *args
38
+ end
39
+
40
+ obj.run_callback :after
41
+ obj
42
+ end
43
+
44
+ def render method_name, *args
45
+ send(method_name, *args).body
46
+ end
47
+
48
+ def method_missing method_sym, *args
49
+ prepare(method_sym, *args)
50
+ end
51
+
52
+ def deliver
53
+ send(method_name, *args).deliver
54
+ end
31
55
  end
32
56
 
33
- def render method_name, *args
34
- send(method_name, *args).body
35
- end
57
+ ###
36
58
 
37
- def method_missing method_sym, *args
38
- prepare(method_sym, *args)
59
+ def initialize
60
+ @mail = {}.to_hwia :subject, :body, :to, :cc, :from
39
61
  end
40
62
 
41
- def deliver
42
- send(method_name, *args).deliver
43
- end
44
- end
63
+ def body
64
+ data = @mail.body
45
65
 
46
- ###
66
+ unless data
67
+ helper = Lux::Template::Helper.new self, self.class.helper
68
+ layout = Lux::Template.find_layout './app/views', self.class.layout
69
+ data = Lux::Template.render helper, template: "#{cattr.template_root}/mailer/#{@_template}", layout: layout
70
+ end
47
71
 
48
- def initialize
49
- @mail = FreeStruct.new subject: nil, body: nil, to: nil, cc: nil, from: nil
50
- end
72
+ data.gsub(%r{\shref=(['"])/}) { %[ href=#{$1}#{Lux.config.host}/] }
73
+ end
51
74
 
52
- def deliver
53
- raise "From in mailer not defined" unless @mail.from
54
- raise "To in mailer not defined" unless @mail.to
55
- raise "Subject in mailer not defined" unless @mail.subject
75
+ def subject
76
+ @mail.subject
77
+ end
56
78
 
57
- m = Mail.new
58
- m[:from] = @mail.from
59
- m[:to] = @mail.to
60
- m[:subject] = @mail.subject
61
- m[:body] = body
62
- m[:content_type] = 'text/html; charset=UTF-8'
79
+ def to
80
+ @mail.to
81
+ end
63
82
 
64
- Lux.delay { m.deliver! }
83
+ def deliver
84
+ if m = build_mail_object
85
+ Lux.current.delay(m) { |mail| mail.deliver! }
86
+ end
87
+ end
65
88
 
66
- instance_exec m, &Lux.config.on_mail
67
- end
89
+ private
68
90
 
69
- def body
70
- data = @mail.body
91
+ def build_mail_object
92
+ return if @mail.to.class == FalseClass
71
93
 
72
- unless data
73
- helper = Lux::View::Helper.new self, self.class.helper
74
- data = Lux::View.render_with_layout "layouts/#{self.class.layout}", "mailer/#{@_template}", helper
75
- end
94
+ raise "From in mailer not defined" unless @mail.from
95
+ raise "To in mailer not defined" unless @mail.to
96
+ raise "Subject in mailer not defined" unless @mail.subject
76
97
 
77
- data.gsub(%r{\shref=(['"])/}) { %[ href=#{$1}#{Lux.config.host}/] }
78
- end
98
+ m = Mail.new
99
+ m[:from] = @mail.from
100
+ m[:to] = @mail.to
101
+ m[:subject] = @mail.subject
102
+ m[:body] = body
103
+ m[:content_type] = 'text/html; charset=UTF-8'
79
104
 
80
- def subject
81
- @mail.subject
82
- end
105
+ instance_exec m, &Lux.config.on_mail_send
83
106
 
84
- def to
85
- @mail.to
107
+ m
108
+ end
86
109
  end
87
-
88
- end
110
+ end
@@ -0,0 +1,19 @@
1
+ ## Lux.plugin (Lux::Plugin)
2
+
3
+ Plugin management
4
+
5
+ * loads plugins in selected namespace, default namespace :main
6
+ * gets plugins in selected namespace
7
+
8
+ ```ruby
9
+ # load a plugin
10
+ Lux.plugin name_or_folder
11
+ Lux.plugin name: :foo, folder: '/.../...', namespace: [:main, :admin]
12
+ Lux.plugin name: :bar
13
+
14
+ # plugin folder path
15
+ Lux.plugin.folder(:foo) # /home/app/...
16
+
17
+ # Load lux plugin
18
+ Lux.plugin :db
19
+ ```
@@ -0,0 +1,8 @@
1
+ module Lux
2
+ # simple interface to plugins
3
+ # Lux.plugin :foo
4
+ # Lux.plugin
5
+ def plugin *args
6
+ args.first ? ::Lux::Plugin.load(*args) : ::Lux::Plugin
7
+ end
8
+ end
@@ -0,0 +1,65 @@
1
+ module Lux
2
+ module Plugin
3
+ extend self
4
+
5
+ PLUGIN = {}
6
+
7
+ # load specific plugin
8
+ # Lux.plugin :foo
9
+ # Lux.plugin 'foo/bar'
10
+ # Lux.plugin.folders
11
+ # Lux.plugin(:api).folder
12
+ def load arg
13
+ arg = arg.to_s if arg.is_a?(Symbol)
14
+
15
+ if arg.is_a?(String)
16
+ arg = arg.include?('/') ? { folder: arg } : { name: arg }
17
+ end
18
+
19
+ opts = arg.to_hwia :name, :folder, :namespace
20
+ opts.name ||= opts.folder.split('/').last
21
+ opts.name = opts.name.to_s
22
+ opts.folder ||= Lux.fw_root.join('plugins', opts.name).to_s
23
+ opts.namespace = [opts.namespace] unless opts.namespace.is_a?(Array)
24
+
25
+ return PLUGIN[opts.name] if PLUGIN[opts.name]
26
+
27
+ die(%{Plugin "#{opts.name}" not found in "#{opts.folder}"}) unless Dir.exist?(opts.folder)
28
+
29
+ PLUGIN[opts.name] ||= opts
30
+
31
+ base = Pathname.new(opts.folder).join(opts.name, '.rb')
32
+
33
+ if base.exist?
34
+ require base.to_s
35
+ else
36
+ Dir.require_all(opts.folder)
37
+ end
38
+
39
+ PLUGIN[opts.name]
40
+ end
41
+
42
+ def get name
43
+ PLUGIN[name.to_s] || die('Plugin "%s" not loaded' % name)
44
+ end
45
+
46
+ def loaded
47
+ PLUGIN.values
48
+ end
49
+
50
+ def keys
51
+ PLUGIN.keys
52
+ end
53
+
54
+ def plugins
55
+ PLUGIN
56
+ end
57
+
58
+ # get all folders in a namespace
59
+ def folders namespace=:main
60
+ list = PLUGIN.values
61
+ list.select { |it| it.namespace.include?(namespace) }
62
+ list.map { |it| it.folder }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,100 @@
1
+ ## Lux.render
2
+
3
+ Render full pages and templates.
4
+
5
+ ### Render full pages
6
+
7
+ As a first argument to any render method you can provide
8
+ full [Rack environment](https://www.rubydoc.info/gems/rack/Rack/Request/Env).
9
+
10
+ If you provide only local path,
11
+ [`Rack::MockRequest`](https://www.rubydoc.info/gems/rack/Rack/MockRequest) will be created.
12
+
13
+ Two ways of creating render pages are provided.
14
+
15
+ * full builder `Lux.render(@path, @full_opts)`
16
+ * helper builder with request method as method name `Lux.render.post(@path, @params_hash, @rest_of_opts)`
17
+
18
+ ```ruby
19
+ # render options - all optional
20
+ opts = {
21
+ query_string: {}
22
+ post: {},
23
+ body: String
24
+ request_method: String
25
+ session: {}
26
+ cookies: {}
27
+ }
28
+
29
+ # when passing data directly, renders full page with all options
30
+ page = Lux.render('/about', opts)
31
+
32
+ # you can use request method prefix
33
+ page = Lux.render.post('/api/v1/orgs/list', { page_size: 100 }, rest_of_opts)
34
+ page = Lux.render.get('/search', { q: 'london' }, { session: {user_id: 1} })
35
+
36
+ page.info # gets info hash + body
37
+ # {
38
+ # body: '{}',
39
+ # time: '5ms',
40
+ # status: 200,
41
+ # session: { user_id: 123 }
42
+ # headers: { ... }
43
+ # }
44
+
45
+ page.render # get only body
46
+ ```
47
+
48
+
49
+ ### Render templates
50
+
51
+ Renders templates, wrapper arround [ruby tilt gem](https://github.com/rtomayko/tilt).
52
+
53
+ ```ruby
54
+ Lux.render.template(@scope, @template)
55
+ Lux.render.template(@scope, template: @template, layout: @layout_file)
56
+ Lux.render.template(@scope, @layout_template) { @yield_data }
57
+ ```
58
+
59
+ Scope is any object in which context tmplate will be rendered.
60
+
61
+ * you can pass `self` so template has access to the same instance
62
+ variables and methods as current scope.
63
+ * you can construct full valid helper with `Lux.template.helper(@scope, :foo, :bar)`.
64
+ New helper class will be created from `FooHelper module and BarHelper module`,
65
+ and it will be populated with `@scope` instance variables.
66
+
67
+ ```ruby
68
+ # HtmlHelper module or CustomModule has to define link_to method
69
+ helper = Lux.template.helper(@instance_variables_hash, :html, :custom, ...)
70
+ helper.link_to('foo', '#bar') # <a href="#bar">foo</a>
71
+ ```
72
+
73
+ Tip: If you want to access helper mehods while in controller, just use `helper`.
74
+
75
+
76
+ ### Render controllers - [Lux::Controller](https://github.com/dux/lux-fw/tree/master/lib/lux/controller)
77
+
78
+ Render controller action without routes, pass a block to yield before action call
79
+ if you need to set up params or instance variables.
80
+
81
+ ```ruby
82
+ Lux.render.controller('main/cities#foo').body
83
+ Lux.render.controller('main/cities#bar') { @city = City.last_updated }.body
84
+ ```
85
+
86
+ ### Render cells - [Lux::ViewCells](https://github.com/dux/lux-fw/tree/master/lib/lux/view_cell)
87
+
88
+ Convenience helper is available to render cells, but preffered way is to call cell directly.
89
+
90
+ ```ruby
91
+ # UserCell.new.in_a_box @user
92
+ Lux.render.cell(:user).in_a_box @user
93
+
94
+ # UserCell.new(self).in_a_box
95
+ Lux.render.cell(:user, self).in_a_box
96
+
97
+ # UserCell.new(self, user: @user).in_a_box
98
+ Lux.render.cell(:user, user: @user).in_a_box
99
+ ````
100
+
@@ -0,0 +1,12 @@
1
+ module Lux
2
+ # Lux.app.new(path, full_opts).info
3
+ # Lux.render.post(path, params, rest_of_opts).info
4
+ # Lux.render.get('/search', { q: 'london' }, { session: {user_id: 1} }).info def render *args
5
+ def render *args
6
+ if args.first
7
+ app.new(*args)
8
+ else
9
+ app::Render
10
+ end
11
+ end
12
+ end