lux-fw 0.1.35 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +5 -5
  2. data/.version +1 -1
  3. data/bin/cli/am +67 -41
  4. data/bin/cli/assets +1 -1
  5. data/bin/cli/console +3 -2
  6. data/bin/cli/eval +11 -2
  7. data/bin/cli/exceptions +1 -1
  8. data/bin/cli/generate +4 -0
  9. data/bin/cli/render +18 -0
  10. data/bin/cli/routes +3 -1
  11. data/bin/cli/server +4 -1
  12. data/bin/lux +10 -1
  13. data/bin/txt/nginx.conf +35 -18
  14. data/lib/common/class_attributes.rb +10 -10
  15. data/lib/common/{before_and_after.rb → class_callbacks.rb} +12 -21
  16. data/lib/common/crypt.rb +10 -6
  17. data/lib/common/dynamic_class.rb +12 -7
  18. data/lib/common/generic_model.rb +6 -6
  19. data/lib/common/hash_with_indifferent_access.rb +6 -284
  20. data/lib/{lux/helper/lib/html_tag.rb → common/html_tag_builder.rb} +1 -1
  21. data/lib/common/policy.rb +2 -2
  22. data/lib/common/url.rb +6 -4
  23. data/lib/lux-fw.rb +2 -13
  24. data/lib/lux/api/api.rb +34 -47
  25. data/lib/lux/api/lib/dsl.rb +2 -2
  26. data/lib/lux/api/lib/model_api.rb +40 -23
  27. data/lib/lux/api/lib/response.rb +30 -5
  28. data/lib/lux/application/application.rb +182 -0
  29. data/lib/lux/{controller → application}/lib/nav.rb +18 -21
  30. data/lib/lux/application/lib/plugs.rb +10 -0
  31. data/lib/lux/application/lib/render.rb +58 -0
  32. data/lib/lux/application/lib/route_test.rb +64 -0
  33. data/lib/lux/cache/cache.rb +27 -16
  34. data/lib/lux/cell/cell.rb +66 -54
  35. data/lib/lux/config/config.rb +51 -27
  36. data/lib/lux/current/current.rb +122 -0
  37. data/lib/lux/{page → current}/lib/encrypt_params.rb +2 -2
  38. data/lib/lux/{page → current}/lib/static_file.rb +29 -25
  39. data/lib/lux/delayed_job/delayed_job.rb +4 -4
  40. data/lib/lux/error/error.rb +31 -16
  41. data/lib/lux/helper/helper.rb +32 -37
  42. data/lib/lux/helper/helpers/application_helper.rb +3 -0
  43. data/lib/lux/helper/helpers/html_helper.rb +3 -0
  44. data/lib/lux/helper/helpers/mailer_helper.rb +11 -0
  45. data/lib/lux/lux.rb +40 -30
  46. data/lib/lux/mailer/mailer.rb +46 -29
  47. data/lib/lux/{page → response}/lib/flash.rb +1 -1
  48. data/lib/lux/response/lib/header.rb +21 -0
  49. data/lib/lux/response/response.rb +237 -0
  50. data/lib/lux/template/template.rb +20 -18
  51. data/lib/overload/array.rb +5 -0
  52. data/lib/overload/auto_loader.rb +27 -0
  53. data/lib/overload/blank.rb +8 -2
  54. data/lib/overload/float.rb +10 -0
  55. data/lib/overload/hash.rb +5 -12
  56. data/lib/overload/integer.rb +1 -5
  57. data/lib/overload/nil.rb +5 -0
  58. data/lib/overload/object.rb +1 -0
  59. data/lib/overload/r.rb +5 -0
  60. data/lib/overload/string.rb +4 -5
  61. data/lib/overload/{date.rb → time.rb} +23 -3
  62. metadata +37 -73
  63. data/bin/forever +0 -65
  64. data/bin/job_que +0 -39
  65. data/lib/lux/api/lib/application_api.rb +0 -38
  66. data/lib/lux/api/lib/doc_builder.rb +0 -19
  67. data/lib/lux/api/lib/rescue.rb +0 -8
  68. data/lib/lux/controller/controller.rb +0 -185
  69. data/lib/lux/controller/lib/plugs.rb +0 -10
  70. data/lib/lux/html/html.rb +0 -3
  71. data/lib/lux/html/lib/form.rb +0 -81
  72. data/lib/lux/html/lib/input.rb +0 -71
  73. data/lib/lux/html/lib/input_types.rb +0 -287
  74. data/lib/lux/lib/lux.rb +0 -51
  75. data/lib/lux/page/lib/response.rb +0 -178
  76. data/lib/lux/page/page.rb +0 -292
  77. data/lib/lux/rescue_from/rescue_from.rb +0 -63
  78. data/lib/plugins/assets/assets_plug.rb +0 -31
  79. data/lib/plugins/assets/helper_module_adapter.rb +0 -51
  80. data/lib/plugins/assets/init.rb +0 -4
  81. data/lib/plugins/db_helpers/array_and_hstore.rb +0 -64
  82. data/lib/plugins/db_helpers/arrays_and_tags.rb +0 -23
  83. data/lib/plugins/db_helpers/before_save.rb +0 -44
  84. data/lib/plugins/db_helpers/cached_find_by.rb +0 -45
  85. data/lib/plugins/db_helpers/class_and_instance.rb +0 -120
  86. data/lib/plugins/db_helpers/dataset_plugin.rb +0 -101
  87. data/lib/plugins/db_helpers/filter_wrappers.rb +0 -21
  88. data/lib/plugins/db_helpers/link_plugin.rb +0 -95
  89. data/lib/plugins/db_helpers/localize_plugin.rb +0 -57
  90. data/lib/plugins/db_helpers/primary_keys.rb +0 -36
  91. data/lib/plugins/db_helpers/typero_attributes.rb +0 -69
  92. data/lib/plugins/db_logger/init.rb +0 -18
  93. data/lib/plugins/db_logger/lux_response_adapter.rb +0 -9
  94. data/lib/plugins/paginate/helper.rb +0 -32
  95. data/lib/plugins/paginate/sequel_adapter.rb +0 -18
  96. data/lib/vendor/mini_assets/lib/asset.rb +0 -71
  97. data/lib/vendor/mini_assets/lib/asset/css.rb +0 -19
  98. data/lib/vendor/mini_assets/lib/asset/js.rb +0 -17
  99. data/lib/vendor/mini_assets/lib/base.rb +0 -69
  100. data/lib/vendor/mini_assets/lib/base/javascript.rb +0 -13
  101. data/lib/vendor/mini_assets/lib/base/stylesheet.rb +0 -5
  102. data/lib/vendor/mini_assets/lib/manifest.rb +0 -18
  103. data/lib/vendor/mini_assets/lib/opts.rb +0 -16
  104. data/lib/vendor/mini_assets/mini_assets.rb +0 -74
  105. data/lib/vendor/oauth/lib/facebook.rb +0 -35
  106. data/lib/vendor/oauth/lib/github.rb +0 -37
  107. data/lib/vendor/oauth/lib/google.rb +0 -41
  108. data/lib/vendor/oauth/lib/linkedin.rb +0 -41
  109. data/lib/vendor/oauth/lib/stackexchange.rb +0 -37
  110. data/lib/vendor/oauth/lib/twitter.rb +0 -41
  111. data/lib/vendor/oauth/oauth.rb +0 -46
@@ -11,35 +11,16 @@ module Lux::Config
11
11
  @module_error = []
12
12
 
13
13
  # requires all files recrusive in, with spart sort
14
- def require_all(files)
14
+ def require_all files
15
15
  files = files.to_s
16
16
  files += '/*' unless files.include?('*')
17
17
 
18
18
  file_errors = []
19
19
  glob = `echo #{files} #{files}/* #{files}/*/* #{files}/*/*/* #{files}/*/*/*/* |tr ' ' '\n' | grep .rb`.split("\n")
20
- glob.reject! { |file| file =~ /_\d+\.rb$/ }
21
20
 
22
21
  glob.select{ |o| o.index('.rb') }.map{ |o| o.split('.rb')[0]}.each do |ruby_file|
23
- require ruby_file rescue file_errors.push(ruby_file)
22
+ require ruby_file
24
23
  end
25
-
26
- file_errors.each { |klass|
27
- @klass = klass
28
- require klass
29
- }
30
- rescue
31
- puts "* double load error: require_all #{files}\n #{@klass}.rb\n #{$!.message}".red
32
- raise $!
33
- end
34
-
35
- # load specific plugin
36
- def plugin(name)
37
- files = Dir['%s/lib/plugins/%s/*.rb' % [Lux.fw_root, name]]
38
- die('Plugin "%s" load error, no plugin' % name) if files.length == 0
39
- for file in files
40
- require file
41
- end
42
- # Lux.log "* plugin :#{name}"
43
24
  end
44
25
 
45
26
  # preview config in development
@@ -70,14 +51,57 @@ module Lux::Config
70
51
  true
71
52
  end
72
53
 
73
- def show_load_speed(load_start)
54
+ def ram
55
+ `ps -o rss -p #{$$}`.chomp.split("\n").last.to_i / 1000
56
+ end
57
+
58
+ def show_load_speed load_start=nil
59
+ return @@load_info || 'No lux load info' unless load_start
60
+
74
61
  speed = ((Time.now - load_start)*1000).round.to_s.sub(/(\d)(\d{3})$/,'\1s \2')+'ms'
75
- ram = `ps -o rss -p #{$$}`.chomp.split("\n").last.to_i / 1000
76
- opts = []
77
- opts.push Lux.verbose? ? 'verbose'.yellow : 'no-verbose'.green
78
- opts.push Lux.config(:auto_code_reload) ? 'auto-code-reload'.yellow : 'no-code-reload'.green
79
62
 
80
- "* #{'Lux'.white} loaded #{Lux.env('RACK_ENV').green} (#{opts.join(', ')}) mode in #{speed.to_s.white}, uses #{ram.to_s.white} MB RAM with total of #{Gem.loaded_specs.keys.length.to_s.white} gems in spec"
63
+ production_mode = true
64
+
65
+ production_opts = [
66
+ [:compile_assets, false],
67
+ [:auto_code_reload, false],
68
+ [:show_server_errors, false],
69
+ [:log_to_stdout, false],
70
+ ]
71
+
72
+ opts = production_opts.map do |key, production_value|
73
+ config_test = Lux.config(key)
74
+ config_ok = production_value == config_test
75
+ production_mode = false unless config_ok
76
+
77
+ data = "#{key} (%s)" % [config_test ? :yes : :no]
78
+ config_ok ? data : data.yellow
79
+ end
80
+
81
+ puts @@load_info = '* Config: %s' % opts.join(', ')
82
+
83
+ mode = production_mode ? 'production'.green : 'development'.yellow
84
+
85
+ "* #{'Lux'.white} loaded #{mode} mode in #{speed.to_s.white}, uses #{ram.to_s.white} MB RAM with total of #{Gem.loaded_specs.keys.length.to_s.white} gems in spec".tap do |it|
86
+ @@load_info += "\n#{it}"
87
+ end
88
+ end
89
+
90
+ def set_default_vars
91
+ # how long will session last if BROWSER or IP change
92
+ Lux.config.session_forced_validity = 5.minutes.to_i
93
+
94
+ # name of the session cookie
95
+ Lux.config.session_cookie_name = '__luxs'
96
+
97
+ # Show server errors to a client
98
+ Lux.config.show_server_errors = false
99
+
100
+ # Log debug output to stdout
101
+ Lux.config.log_to_stdout = false
102
+
103
+ # Automatic code reloads in development
104
+ Lux.config.auto_code_reload = false
81
105
  end
82
106
 
83
107
  end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ # we need this for command line
4
+ Thread.current[:lux] ||= { cache: {} }
5
+
6
+ class Lux::Current
7
+ # set to true if user is admin and you want him to be able to clear caches in production
8
+ attr_accessor :can_clear_cache
9
+
10
+ attr_accessor :session, :locale
11
+ attr_reader :request, :response, :params, :nav, :cookies
12
+
13
+ def initialize env=nil
14
+ env ||= '/mock'
15
+ env = ::Rack::MockRequest.env_for(env) if env.class == String
16
+ request = ::Rack::Request.new env
17
+
18
+ # reset page cache
19
+ Thread.current[:lux] = { cache:{}, page: self }
20
+
21
+ @files_in_use = []
22
+ @response = Lux::Response.new
23
+ @request = request
24
+ @cookies = {}
25
+ @session = {}
26
+
27
+ for cookie in request.env['HTTP_COOKIE'].to_s.split(/;\s*/).map{ |el| el.split('=',2) }
28
+ @cookies[cookie[0]] = cookie[1]
29
+ end
30
+
31
+ @session = JSON.parse(Crypt.decrypt(@cookies['__luxs'] || '{}')) rescue {}
32
+
33
+ # check for session
34
+ if Lux.dev? && request.env['HTTP_REFERER'] && request.env['HTTP_REFERER'].index(request.host) && @session.keys.length == 0
35
+ puts "ERROR: There is no session set!".red
36
+ end
37
+
38
+ # hard sec, bind session to user agent and IP
39
+ set_and_check_client_unique_hash
40
+
41
+ @session = HashWithIndifferentAccess.new(@session)
42
+
43
+ ap request.params if request.post? && Lux.config(:log_to_stdout)
44
+
45
+ @params = request.params.h_wia
46
+ Lux::Current::EncryptParams.decrypt @params
47
+
48
+ @nav = Lux::Application::Nav.new request
49
+ end
50
+
51
+ def files_in_use file=nil
52
+ @files_in_use.push file if file && !@files_in_use.include?(file)
53
+ @files_in_use
54
+ end
55
+
56
+ def set_and_check_client_unique_hash
57
+ key = '_c'
58
+ check = Crypt.sha1(@request.ip.to_s+@request.env['HTTP_USER_AGENT'].to_s)[0,10]
59
+
60
+ # force type array
61
+ @session.delete(key) unless @session[key].class == Array
62
+
63
+ # allow 5 mins delay for IP change
64
+ @session = {} if @session[key] && (@session[key][0] != check && @session[key][1].to_i < Time.now.to_i - Lux.config.session_forced_validity)
65
+
66
+ # add new time stamp to every request
67
+ @session[key] = [check, Time.now.to_i]
68
+ end
69
+
70
+ def domain
71
+ host = Lux.current.request.host.split('.')
72
+ host_country = host.pop
73
+ host_name = host.pop
74
+ host_name ? "#{host_name}.#{host_country}" : host_country
75
+ end
76
+
77
+ def host
78
+ "#{request.env['rack.url_scheme']}://#{request.host}:#{request.port}".sub(':80','')# rescue 'http://locahost:3000'
79
+ end
80
+
81
+ def var
82
+ Thread.current[:lux][:var] ||= Hashie::Mash.new
83
+ end
84
+
85
+ # cache data in current page
86
+ def cache key
87
+ data = Thread.current[:lux][:cache][key]
88
+ return data if data
89
+ Thread.current[:lux][:cache][key] = yield
90
+ end
91
+
92
+ # set current.can_clear_cache = true in production for admins
93
+ def no_cache?
94
+ @can_clear_cache ||= true if Lux.dev?
95
+ (@can_clear_cache && @request.env['HTTP_CACHE_CONTROL'].to_s.downcase == 'no-cache') ? true : false
96
+ end
97
+
98
+ def redirect *args
99
+ response.redirect *args
100
+ end
101
+
102
+ # execute action once per page
103
+ def once id=nil, data=nil, &block
104
+ id ||= Digest::SHA1.hexdigest caller[0] if block
105
+
106
+ @once_hash ||= {}
107
+ return @once_hash[id] if @once_hash.key?(id)
108
+
109
+ @once_hash[id] = if block_given?
110
+ yield
111
+ else
112
+ data || true
113
+ end
114
+ end
115
+
116
+ def uid
117
+ Thread.current[:uid_cnt] ||= 0
118
+ "uid-#{Thread.current[:uid_cnt]+=1}"
119
+ end
120
+
121
+ end
122
+
@@ -1,6 +1,6 @@
1
1
  # used for encrypting and decrypting data in forms
2
2
 
3
- module Lux::Page::EncryptParams
3
+ module Lux::Current::EncryptParams
4
4
  extend self
5
5
 
6
6
  @cnt = 0
@@ -38,7 +38,7 @@ module Lux::Page::EncryptParams
38
38
 
39
39
  hash
40
40
  rescue
41
- Lux.log ' Lux::Page::EncryptParams decrypt error'.red
41
+ Lux.log ' Lux::Current::EncryptParams decrypt error'.red
42
42
  {}
43
43
  end
44
44
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Lux::Page::StaticFile
4
- DIRS = Dir.entries('./public').select{|d| d[0,1]!='.' && File.directory?("./public/#{d}") } rescue []
5
-
3
+ class Lux::Current::StaticFile
6
4
  MIMME_TYPES = {
7
5
  txt: 'text/plain',
8
6
  html: 'text/html',
@@ -23,23 +21,25 @@ class Lux::Page::StaticFile
23
21
  ttf: 'application/font-ttf',
24
22
  eot: 'application/vnd.ms-fontobject',
25
23
  otf: 'application/font-otf',
24
+ doc: 'application/msword'
26
25
  }
27
26
 
28
27
  class << self
29
- def deliver(file)
30
- new(file).read
28
+ def deliver file
29
+ new(file).deliver
31
30
  end
32
31
  end
33
32
 
34
33
  ###
35
34
 
36
- [:body, :status].each { |f| eval "def #{f}(what=nil); Lux.page.#{f}(what); end" }
37
- [:headers].each { |f| eval "def #{f}; Lux.page.#{f}; end" }
38
-
39
- def initialize(file)
35
+ def initialize file
40
36
  @file = file
41
37
  end
42
38
 
39
+ def c
40
+ Lux.current
41
+ end
42
+
43
43
  def is_static_file?
44
44
  return false unless @file.index('.')
45
45
 
@@ -51,47 +51,51 @@ class Lux::Page::StaticFile
51
51
 
52
52
  return false if ext.to_s.length == 0
53
53
  return false unless MIMME_TYPES[ext.to_sym]
54
- return true if path.first.blank? # if /favico.ico is not present return true
55
- return DIRS.index(path.first) ? true : false
54
+
56
55
  true
57
56
  end
58
57
 
59
- def read(data=nil)
58
+ def deliver data=nil
60
59
  file = File.exist?(@file) ? @file : Lux.root.join("public#{@file}")
61
60
 
62
61
  unless File.exists?(file)
63
62
  if @file == '/favicon.ico'
64
- file = Lux.fw_root.join('public/lux.png')
63
+ file = Lux.fw_root.join('misc/lux.png')
65
64
  else
66
- raise NotFoundError, %[Static file "#{@file.split(Lux.root.to_s+'/public')[1]}" not found]
65
+ raise NotFoundError, %[Static file not found]
67
66
  end
68
67
  end
69
68
 
70
69
  ext = file.to_s.split('.').last
71
70
  mimme = MIMME_TYPES[ext.to_sym]
71
+
72
72
  unless mimme
73
- body('Mimme type not supported')
74
- status(404)
73
+ c.response.body('Mimme type not supported')
74
+ c.response.status(404)
75
75
  return
76
76
  end
77
77
 
78
- Lux.page.content_type = mimme
78
+ c.response.content_type = mimme
79
79
 
80
80
  file_mtime = File.mtime(file).utc.to_s
81
- key = Crypt.md5(file+file_mtime.to_s)
82
- headers['cache-control'] = 'max-age=31536000, no-transform, public'
83
- headers['etag'] = key
84
- headers['last-modified'] = file_mtime
81
+ key = Crypt.sha1(file+file_mtime.to_s)
82
+
83
+ c.response.headers['cache-control'] = 'max-age=31536000, public'
84
+ c.response.headers['etag'] = '"%s"' % key
85
+ c.response.headers['last-modified'] = file_mtime
85
86
 
86
87
  # IF etags match, returnfrom cache
87
- if Lux.page.request.env['HTTP_IF_NONE_MATCH'] == key
88
- status(304)
89
- body('not-modified')
88
+ if c.request.env['HTTP_IF_NONE_MATCH'] == key
89
+ c.response.status(304)
90
+ c.response.body('not-modified')
90
91
  return
91
92
  end
92
93
 
94
+ # c.response.headers['X-Sendfile'] = file
95
+
93
96
  data ||= File.read(file)
94
- body(data)
97
+ c.response.body(data)
98
+
95
99
  true
96
100
  end
97
101
  end
@@ -3,14 +3,14 @@ module Lux::DelayedJob
3
3
 
4
4
  @@server = nil
5
5
 
6
- def server=(name)
6
+ def server= name
7
7
  adapter = "Lux::DelayedJob::#{name.to_s.capitalize}"
8
8
  @@server = adapter.constantize
9
9
  rescue NameError
10
- die('No adapter %s not found' % adapter)
10
+ die 'No adapter %s not found' % adapter
11
11
  end
12
12
 
13
- def push(object, method_to_call=nil)
13
+ def push object, method_to_call=nil
14
14
  die "No DelayedJob server defined" unless @@server
15
15
  @@server.push [object, method_to_call]
16
16
  end
@@ -31,7 +31,7 @@ module Lux::DelayedJob
31
31
  true
32
32
  end
33
33
 
34
- def run!(seconds=2)
34
+ def run! seconds=2
35
35
  puts "JOB QUE> is running for #{@@server}".green
36
36
  Thread.new do
37
37
  while true
@@ -18,27 +18,36 @@ RateLimitError ||= Class.new(StandardError)
18
18
  module Lux::Error
19
19
  extend self
20
20
 
21
- def try(name)
21
+ def try name=nil
22
22
  begin
23
23
  yield
24
- rescue
25
- Lux.page.status 500
26
- log($!)
27
- inline('%s (%s)' % [name, $!.class])
24
+ rescue Exception => e
25
+ Lux.current.response.status 500
26
+
27
+ key = log e
28
+
29
+ if Lux.config(:show_server_errors)
30
+ inline name
31
+ else
32
+ name ||= 'Server error occured'
33
+ name += "\n\nkey: %s" % key
34
+
35
+ Lux.error(name)
36
+ end
28
37
  end
29
38
  end
30
39
 
31
40
  def render data
32
- %[<html><head><title>Server error (#{Lux.page.status})</title></head><body style="background:#fdd;"><pre style="color:red; padding:10px; font-size:14pt;">#{data.gsub('<','&lt;')}</pre></body></html>]
41
+ %[<html><head><title>Server error (#{Lux.current.response.status})</title></head><body style="background:#fdd;"><pre style="color:red; padding:10px; font-size:14pt;">#{data.gsub('<','&lt;')}</pre></body></html>]
33
42
  end
34
43
 
35
- def show(desc=nil)
36
- Lux.page.status(500)
37
- data = "Lux #{Lux.page.status} error\n\n#{desc}"
38
- Lux.page.body! render(data)
44
+ def show desc=nil
45
+ Lux.current.response.status 500
46
+ data = "Lux #{Lux.current.response.status} error\n\n#{desc}"
47
+ Lux.current.response.body! render(data)
39
48
  end
40
49
 
41
- def inline(name=nil, o=nil)
50
+ def inline name=nil, o=nil
42
51
  o ||= $!
43
52
 
44
53
  dmp = [[], []]
@@ -56,13 +65,17 @@ module Lux::Error
56
65
  %[<pre style="color:red; background:#eee; padding:10px; font-family:'Lucida Console'; line-height:15pt; font-size:11pt;"><b style="font-size:110%;">#{name}</b>\n\n<b>#{msg}</b>\n\n#{dmp[0].join("\n")}\n\n#{dmp[1].join("\n")}</pre>]
57
66
  end
58
67
 
59
- def log(exception)
60
- return if Lux.env == 'test'
61
- return unless Lux.page
68
+ def log exception
69
+ return if Lux.env == 'test'
70
+ return if exception.class == LocalRaiseError
71
+ return unless Lux.current
62
72
 
63
- history = exception.backtrace.reject{ |el| el.index('/gems/') }.map{ |el| el.sub(Lux.root.to_s, '') }.join("\n")
73
+ # .backtrace.reject{ |el| el.index('/gems/') }
74
+ history = exception.backtrace
75
+ .map{ |el| el.sub(Lux.root.to_s, '') }
76
+ .join("\n")
64
77
 
65
- data = '%s in %s (user: %s)' % [exception.class, Lux.page.request.url, (Lux.page.var.user.email rescue 'guest')]
78
+ data = '%s in %s (user: %s)' % [exception.class, Lux.current.request.url, (Lux.current.var.user.email rescue 'guest')]
66
79
  data = [data, exception.message, history].join("\n\n")
67
80
  key = Digest::SHA1.hexdigest exception.backtrace.first.split(' ').first
68
81
 
@@ -72,5 +85,7 @@ module Lux::Error
72
85
  Dir.mkdir(folder) unless Dir.exists?(folder)
73
86
 
74
87
  File.write("#{folder}/#{key}.txt", data)
88
+
89
+ key
75
90
  end
76
91
  end