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
@@ -1,249 +1,299 @@
1
- # frozen_string_literal: true
1
+ # filters stack for call - before, before_action, :action, after
2
+ # if action is missing capture it via def action_missing name
2
3
 
3
- # filters stack for call
4
- # before, before_action, :action, after
4
+ module Lux
5
+ class Controller
6
+ include ClassCallbacks
7
+ include ::Lux::Application::Shared
5
8
 
6
- class Lux::Controller
7
- # define maser layout
8
- # string is template, symbol is metod pointer and lambda is lambda
9
- class_attribute :layout
9
+ # define master layout
10
+ # string is template, symbol is method pointer and lambda is lambda
11
+ cattr :layout, class: true
10
12
 
11
- # define helper contest, by defult derived from class name
12
- class_attribute :helper
13
+ # define helper contest, by defult derived from class name
14
+ # cattr :helper, class: true
13
15
 
14
- # before and after any action filter, ignored in controllers, after is called just before render
15
- [:before, :before_action, :before_render, :after].each { |filter| class_callback filter }
16
+ # custom template root instead calcualted one
17
+ cattr :template_root, default: './app/views', class: true
16
18
 
17
- class << self
18
- # simple shortcut allows direct call to action, bypasing call
19
- def action *args
20
- new.action(*args)
21
- end
19
+ # before and after any action filter, ignored in controllers, after is called just before render
20
+ define_callback :before
21
+ define_callback :before_action
22
+ define_callback :before_render
23
+
24
+ class << self
25
+ # simple shortcut allows direct call to action, bypasing call
26
+ def action *args
27
+ new.action(*args)
28
+ end
22
29
 
23
- # create mock function, to enable template rendering
24
- # mock :index, :login
25
- def mock *args
26
- args.each do |el|
27
- define_method(el) { true }
30
+ # create mock function, to enable template rendering
31
+ # mock :index, :login
32
+ def mock *args
33
+ args.each do |el|
34
+ define_method(el) { true }
35
+ end
28
36
  end
29
37
  end
30
- end
31
38
 
32
- ### INSTANCE METHODS
39
+ ### INSTANCE METHODS
33
40
 
34
- attr_reader :controller_action
41
+ IVARS ||= Struct.new 'LuxControllerIvars', :template_sufix, :action, :layout, :render_cache
42
+ RENDER_OPTS ||= Struct.new 'LuxControllerRenderOpts', :inline, :text, :plain, :html, :json, :javascript, :xml, :cache, :template, :layout, :render_to_string, :status, :ttl, :content_type
35
43
 
36
- def initialize
37
- # before and after should be exected only once
38
- @executed_filters = {}
39
- @base_template = self.class.to_s.include?('::') ? self.class.to_s.sub(/Controller$/,'').underscore : self.class.to_s.sub(/Controller$/,'').downcase
40
- end
44
+ attr_reader :controller_action
41
45
 
42
- # because we can call action multiple times
43
- # ensure we execute filters only once
44
- def filter fiter_name, arg=nil
45
- return if @executed_filters[fiter_name]
46
- @executed_filters[fiter_name] = true
46
+ def initialize
47
+ # before and after should be exected only once
48
+ @lux = IVARS.new
49
+ @lux.template_sufix = self.class.to_s.sub(/Controller$/,'').underscore.downcase.split('/').first
50
+ end
47
51
 
48
- Object.class_callback fiter_name, self, @controller_action
49
- end
52
+ # action(:show)
53
+ # action(:select', ['users'])
54
+ def action method_name, *args
55
+ if method_name.blank?
56
+ raise ArgumentError.new('Controller action called with blank action name argument')
57
+ end
50
58
 
51
- def cache *args, &block
52
- Lux.cache.fetch *args, &block
53
- end
59
+ if method_name.is_a?(Symbol)
60
+ raise Lux.error.internal_server_error('Forbiden action name :%s' % method_name) if [:action, :error].include?(method_name)
61
+ else
62
+ return controller_action_call(method_name, *args)
63
+ end
54
64
 
55
- # action(:show)
56
- # action(:select', ['users'])
57
- def action method_name, *args
58
- raise ArgumentError.new('Controller action called with blank action name argument') if method_name.blank?
65
+ method_name = method_name.to_s.gsub('-', '_').gsub(/[^\w]/, '')
59
66
 
60
- method_name = method_name.to_s.gsub('-', '_').gsub(/[^\w]/, '')
67
+ # dev console log
68
+ Lux.log { ' %s#%s (action)'.light_blue % [self.class, method_name] }
69
+ # Lux.log { ' %s' % self.class.source_location }
61
70
 
62
- # dev console log
63
- Lux.log " #{self.class.to_s}##{method_name}".light_blue
71
+ @lux.action = method_name.to_sym
64
72
 
65
- @controller_action = method_name.to_sym
66
- if @controller_format = current.nav.format
67
- current.nav.format = nil
68
- end
73
+ run_callback :before, @lux.action
69
74
 
70
- # format error unless method found
71
- report_not_found_error unless respond_to? method_name
75
+ catch :done do
76
+ unless response.body?
77
+ run_callback :before_action, @lux.action
72
78
 
73
- catch :done do
74
- filter :before
75
- filter :before_action
76
- send method_name, *args
77
- render
79
+ # if action not found
80
+ if respond_to?(method_name)
81
+ send method_name, *args
82
+ else
83
+ action_missing method_name
84
+ end
85
+
86
+ render
87
+ end
88
+ end
89
+ rescue => error
90
+ rescue_from error
78
91
  end
79
92
 
80
- filter :after
93
+ def timeout seconds
94
+ Lux.current.var[:app_timeout] = seconds
95
+ end
81
96
 
82
- throw :done
83
- rescue => e
84
- response.body { nil }
85
- on_error(e)
86
- end
97
+ def flash
98
+ response.flash
99
+ end
87
100
 
88
- def error *args
89
- args.first.nil? ? Lux::Error::AutoRaise : Lux::Error.report(*args)
90
- end
101
+ def rescue_from error
102
+ Lux::Error.log error
103
+ data = Lux.env.show_errors? ? Lux::Error.inline(error) : 'Server error: %s (%s)' % [error.message, error.class]
104
+ render html: data, status: 400
105
+ end
91
106
 
92
- def on_error error
93
- raise error
94
- end
107
+ private
95
108
 
96
- def send_file file, opts={}
97
- Lux::Response::File.send(file, opts)
98
- end
109
+ # delegated to current
110
+ define_method(:get?) { request.request_method == 'GET' }
111
+ define_method(:post?) { request.request_method == 'POST' }
112
+ define_method(:etag) { |*args| current.response.etag *args }
113
+ define_method(:layout) { |arg = :_nil| arg == :_nil ? @lux.layout : (@lux.layout = arg) }
114
+ define_method(:cache_control) { |arg| response.headers['cache-control'] = arg }
99
115
 
100
- # render :index
101
- # render 'main/root/index'
102
- # render text: 'ok'
103
- def render name=nil, opts={}
104
- on_error Lux::Error.new(404, '%s document Not Found' % @controller_format.to_s.upcase) if @controller_format
116
+ # send file to browser
117
+ def send_file file, opts = {}
118
+ response.send_file(file, opts)
119
+ end
105
120
 
106
- if name.class == Hash
107
- opts.merge! name
108
- else
109
- opts[:template] = name
121
+ # does not set the body, returns body string
122
+ def render_to_string name=nil, opts={}
123
+ opts[:render_to_string] = true
124
+ render name, opts
110
125
  end
111
126
 
112
- filter :before_render
127
+ # shortcut to render javascript
128
+ def render_javascript name=nil, opts={}
129
+ opts[:content_type] = :javascript
130
+ opts[:layout] = false
131
+ render name, opts
132
+ end
113
133
 
114
- opts = opts.to_opts :text, :html, :json, :javascript, :cache, :template, :layout, :render_to_string, :data, :status, :ttl, :content_type
134
+ # render :index
135
+ # render 'main/root/index'
136
+ # render text: 'ok'
137
+ def render name = nil, opts = {}
138
+ return if response.body?
115
139
 
116
- response.status opts.status if opts.status
117
- response.content_type = opts.content_type if opts.content_type
140
+ if name.class == Hash
141
+ opts.merge! name
142
+ else
143
+ opts[:template] = name
144
+ end
118
145
 
119
- page =
120
- if opts.cache
121
- Lux.cache.fetch(opts.cache, opts.ttl || 3600) { render_resolve(opts) }
122
- else
123
- render_resolve(opts)
124
- end
146
+ opts = RENDER_OPTS.new **opts
125
147
 
126
- if opts.render_to_string
127
- page
128
- else
129
- response.body { page }
130
- throw :done
131
- end
132
- end
148
+ # set response status and content_type
149
+ response.status opts.status if opts.status
150
+ response.content_type = opts.content_type if opts.content_type
133
151
 
134
- def render_to_string name=nil, opts={}
135
- opts[:render_to_string] = true
136
- render name, opts
137
- end
152
+ # match rails nameing
153
+ opts.text = opts.plain if opts.plain
138
154
 
139
- def render_javascript name=nil, opts={}
140
- opts[:content_type] = :javascript
141
- opts[:layout] = false
142
- render name, opts
143
- end
155
+ # copy value from render_cache
156
+ opts.cache = @lux.render_cache if @lux.render_cache
144
157
 
145
- private
146
-
147
- # delegated to current
148
- define_method(:current) { Lux.current }
149
- define_method(:request) { current.request }
150
- define_method(:response) { current.response }
151
- define_method(:params) { current.request.params }
152
- define_method(:nav) { current.nav }
153
- define_method(:session) { current.session }
154
- define_method(:get?) { request.request_method == 'GET' }
155
- define_method(:post?) { request.request_method == 'POST' }
156
- define_method(:redirect) { |where, flash={}| current.redirect where, flash }
157
- define_method(:etag) { |*args| current.response.etag *args }
158
- define_method(:layout) { |arg| current.var[:controller_layout] = arg }
159
-
160
- # called be render
161
- def render_resolve opts
162
- # render static types
163
- for el in [:text, :html, :json, :javascript]
164
- if value = opts[el]
165
- response.content_type = "text/#{el}"
166
- return value
158
+ # we do not want to cache pages that have flashes in response
159
+ opts.cache = nil if response.flash.present?
160
+
161
+ # define which layout we use
162
+ opts.layout ||= @lux.layout.nil? ? self.class.cattr.layout : @lux.layout
163
+
164
+ # render static types
165
+ for el in [:text, :html, :json, :javascript, :xml]
166
+ if value = opts[el]
167
+ response.body value, content_type: el
168
+ end
169
+ end
170
+
171
+ data = if cache = opts.cache
172
+ return if etag(cache)
173
+
174
+ add_info = true
175
+ from_cache = Lux.cache.fetch opts.cache, ttl: 1_000_000 do
176
+ add_info = false
177
+ render_template(opts)
178
+ end
179
+
180
+ if add_info && from_cache
181
+ response.header['x-lux-cache'] = 'render-cache'
182
+ from_cache += '<!-- from page cache -->' if from_cache =~ %r{</html>\s*$}
183
+ end
184
+
185
+ from_cache
186
+ else
187
+ render_template(opts)
167
188
  end
189
+
190
+ response.body data
168
191
  end
169
192
 
170
- # resolve page data, without template
171
- page_part = opts.data || render_body(opts)
193
+ def render_template opts
194
+ run_callback :before_render, @lux.action
172
195
 
173
- # resolve data with layout
174
- layout = opts.layout
175
- layout = nil if layout.class == TrueClass
176
- layout = false if current.var[:controller_layout].class == FalseClass
196
+ local_helper = self.helper opts.layout.or(cattr.layout) # if layout is false (for dialogs) we fallback to controller default layout
177
197
 
178
- if layout.class == FalseClass
179
- page_part
180
- else
181
- layout_define = layout || self.class.layout
198
+ page_template = cattr.template_root + opts.template.to_s
199
+ Lux.current.var.root_template_path = page_template.sub(%r{/[\w]+$}, '')
200
+ data = opts.inline || Lux::Template.render(local_helper, page_template)
182
201
 
183
- layout = case layout_define
184
- when String
185
- 'layouts/%s' % layout_define
186
- when Symbol
187
- send(layout_define)
188
- when Proc
189
- layout_define.call
190
- else
191
- 'layouts/%s' % @base_template.split('/')[0]
202
+ if opts.layout
203
+ path = Lux::Template.find_layout cattr.template_root, opts.layout
204
+ data = Lux::Template.render(local_helper, path) { data }
192
205
  end
193
206
 
194
- Lux::View.new(layout, helper).render_part { page_part }
207
+ data
195
208
  end
196
- end
197
209
 
198
- def render_body opts
199
- if template = opts.template
200
- template = template.to_s
201
- template = "#{@base_template}/#{template}" unless template.starts_with?('/')
202
- else
203
- template = "#{@base_template}/#{@controller_action}"
210
+ def namespace
211
+ self.class.to_s.split('::').first.underscore.to_sym
204
212
  end
205
213
 
206
- Lux::View.render_part(template, helper)
207
- end
214
+ def helper helper
215
+ helper = nil unless helper
216
+ Lux::Template::Helper.new self, :html, helper
217
+ end
218
+
219
+ # respond_to :js do ...
220
+ # respond_to do |format| ...
221
+ def respond_to ext=nil
222
+ if ext
223
+ if ext == nav.format
224
+ yield if block_given?
225
+ true
226
+ elsif nav.format
227
+ Lux.error.not_found '%s document Not Found' % nav.format.to_s.upcase
228
+ end
229
+ else
230
+ yield nav.format
231
+ end
232
+ end
208
233
 
209
- def halt status, desc=nil
210
- response.status = status
211
- response.body = desc || "Hatlt code #{status}"
234
+ def cache *args, &block
235
+ Lux.cache.fetch *args, &block
236
+ end
212
237
 
213
- throw :done
214
- end
238
+ def render_cache key = :_nil
239
+ if key == :_nil
240
+ @lux.render_cache
241
+ else
242
+ unless @lux.render_cache == false
243
+ @lux.render_cache = key
244
+ end
245
+ end
246
+ end
215
247
 
216
- def namespace
217
- @base_template.split('/')[0].to_sym
218
- end
248
+ def controller_action_call controller_action, *args
249
+ object, action = nil
219
250
 
220
- def helper ns=nil
221
- Lux::View::Helper.new self, :html, self.class.helper, ns
222
- end
251
+ if controller_action.is_a?(String)
252
+ object, action = controller_action.split('#') if controller_action.include?('#')
253
+ object = ('%s_controller' % object).classify.constantize
254
+ elsif object.is_a?(Array)
255
+ object, action = controller_action
256
+ else
257
+ raise ArgumentError.new('Not supported')
258
+ end
223
259
 
224
- def report_not_found_error
225
- raise Lux::Error.not_found unless Lux.config(:dump_errors)
260
+ object.action action.to_sym, *args
261
+ end
226
262
 
227
- err = [%[Method "#{@controller_action}" not found found in #{self.class.to_s}]]
228
- err.push "You have defined \n- %s" % (methods - Lux::Controller.instance_methods).join("\n- ")
263
+ def action_missing name
264
+ path = [cattr.template_root, @lux.template_sufix, name].join('/')
265
+
266
+ if template = Dir['%s.*' % path].first
267
+ unless Lux.config.use_autoroutes
268
+ raise 'Autoroute for "%s" is found but it is disabled in Lux.config.use_autoroutes' % name
269
+ end
270
+
271
+ self.class.define_method(name) {}
272
+ Lux.log ' created method %s#%s | found template %s'.yellow % [self.class, name, template]
273
+ return true
274
+ else
275
+ # if called via super from `action_missing', return false,
276
+ # so once can easily fallback to custom template search pattern
277
+ return false if caller[0].include?("`action_missing'")
278
+ end
229
279
 
230
- return Lux.error err.join("\n\n")
231
- end
280
+ message = 'Method "%s" not found found in "%s" (nav: %s).' % [name, self.class, nav]
232
281
 
233
- def respond_to ext=nil
234
- fmt = @controller_format
235
- @controller_format = nil
282
+ if Lux.env.show_errors?
283
+ defined_methods = (methods - Lux::Controller.instance_methods).map(&:to_s)
284
+ defined = '<br /><br />Defined methods %s' % defined_methods.sort.to_ul
236
285
 
237
- if ext
238
- if ext == fmt
239
- yield if block_given?
240
- true
241
- elsif fmt
242
- on_error Lux::Error.new(404, '%s document Not Found' % fmt.to_s.upcase)
286
+ if Lux.config.use_autoroutes
287
+ root = [cattr.template_root, @lux.template_sufix].join('/')
288
+ files = Dir.files(root).sort.filter {|f| f =~ /^[a-z]/ }.map {|f| f.sub(/\.\w+$/, '') }
289
+ files = files - defined_methods
290
+ defined += '<br />Defined via templates in %s%s' % [root, files.to_ul]
291
+ else
292
+ defined += 'Defined templates - disabled'
293
+ end
243
294
  end
244
- else
245
- yield fmt
295
+
296
+ raise Lux::Error.not_found [message, defined].join(' ')
246
297
  end
247
298
  end
248
-
249
299
  end
@@ -1,14 +1,33 @@
1
- ## Lux::Current - Main state object
1
+ ## Lux.current (Lux::Current)
2
2
 
3
- Current application state as single object. Defined in Thread.current, available everywhere.
3
+ Lux handles state of the app in the single object, stored in `Thread.current`, available everywhere.
4
4
 
5
- `Lux.current` - current response state
5
+ You are not forced to use this object, but you can if you want to.
6
6
 
7
- * `session` - session, encoded in cookie
8
- * `locale` - locale, default nil
9
- * `request` - Rack request
10
- * `response` - Lux response object
11
- * `nav` - lux nav object
12
- * `cookies` - Rack cookies
13
- * `can_clear_cache` - set to true if user can force refresh cache
7
+ ```ruby
8
+ current.session # session, encoded in cookie
9
+ current.locale # locale, default nil
10
+ current.request # Rack request
11
+ current.response # Lux response object
12
+ current.nav # lux nav object
13
+ current.cookies # Rack cookies
14
+ current.can_clear_cache # set to true if user can force refresh cache
15
+ current.var # CleaHash to store global variables
16
+ current[:user] # current.var.user
17
+ current.uid # new unique ID in a page, per response
18
+ current.secure_token # Get or check current session secure token
14
19
 
20
+ # Execute only once in current scope
21
+ current.once { @data }
22
+ current.once(key, @data)
23
+
24
+ # Cache in current response scope
25
+ current.cache(key) {}
26
+
27
+ # Set current.can_clear_cache = true if user is able to clear cache with SHIFT+refresh
28
+ current.no_cache? # false
29
+ current.can_clear_cache = true
30
+ current.no_cache? # true if env['HTTP_CACHE_CONTROL'] == 'no-cache'
31
+
32
+
33
+ ```