deforest 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/deforest/files_controller.rb +0 -37
  3. data/app/views/deforest/files/_percentile_table.html.erb +2 -8
  4. data/app/views/deforest/files/dashboard.html.erb +23 -24
  5. data/app/views/layouts/deforest/application.html.erb +0 -2
  6. data/lib/deforest/version.rb +1 -1
  7. data/lib/deforest.rb +66 -96
  8. data/lib/generators/deforest/deforest_generator.rb +5 -6
  9. data/lib/generators/deforest/templates/classic_enabled_initializer.rb +0 -2
  10. data/lib/generators/deforest/templates/zeitwerk_enabled_initializer.rb +0 -2
  11. data/test/deforest_test.rb +6 -6
  12. data/test/dummy/db/test.sqlite3 +0 -0
  13. data/test/dummy/deforest_db_sync.txt +1 -0
  14. data/test/dummy/log/test.log +2562 -18355
  15. data/test/models/post_test.rb +29 -3
  16. metadata +5 -66
  17. data/app/assets/javascripts/deforest/bootstrap.js +0 -4356
  18. data/app/assets/javascripts/deforest/bootstrap.js.map +0 -1
  19. data/app/assets/stylesheets/deforest/bootstrap-grid.css +0 -3872
  20. data/app/assets/stylesheets/deforest/bootstrap.css +0 -10332
  21. data/app/assets/stylesheets/deforest/bootstrap.css.map +0 -1
  22. data/app/views/deforest/files/index.html.erb +0 -16
  23. data/app/views/deforest/files/show.html.erb +0 -39
  24. data/test/dummy/db/development.sqlite3 +0 -0
  25. data/test/dummy/log/development.log +0 -248
  26. data/test/dummy/tmp/cache/assets/sprockets/v3.0/-T/-T8OIATNI3evoKq5bZdOBNbU0tZeQYxDHGmMOQnF2MM.cache +0 -1
  27. data/test/dummy/tmp/cache/assets/sprockets/v3.0/5L/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +0 -2
  28. data/test/dummy/tmp/cache/assets/sprockets/v3.0/5U/5U1ZhgjUSyIuw2yEYRCbe2n0xGeyHmYwnDlSdtQ2Dnw.cache +0 -1
  29. data/test/dummy/tmp/cache/assets/sprockets/v3.0/AX/AXrDvl0RN_5S8jW0MwnE13ukiiihtUTsaSvoKDVlam4.cache +0 -0
  30. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Cz/Cz2gWla4RNTXNuZf93le7clQqax63V1EHdQWaHR0s-8.cache +0 -1
  31. data/test/dummy/tmp/cache/assets/sprockets/v3.0/DS/DSvREN-eIb--STC5GdXcwmlJjFTw6ZmUVNmW_Sdh1-s.cache +0 -0
  32. data/test/dummy/tmp/cache/assets/sprockets/v3.0/GH/GH5mD035fZ1hsoErrkyMEorz6bwqi30T9a8f3zBIqtE.cache +0 -1
  33. data/test/dummy/tmp/cache/assets/sprockets/v3.0/NL/NLspqKUPe4g6Q4WEvWHMjSTqkF8YS4m2vcBhHBuhVqc.cache +0 -2
  34. data/test/dummy/tmp/cache/assets/sprockets/v3.0/OI/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +0 -2
  35. data/test/dummy/tmp/cache/assets/sprockets/v3.0/S3/S36SlXZyuQfqj2KG4e2Dpj_ZdUQbe2VflfsqjgLNSag.cache +0 -1
  36. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Sh/ShNcRHXrLA44HDRhTj2J11rZhqAuc56Kdr5Ea6O31Mk.cache +0 -0
  37. data/test/dummy/tmp/cache/assets/sprockets/v3.0/TL/TLNT1dXfMKTBmLi7RI_AoPSFmUtB9LfMeG6OuTkR1HQ.cache +0 -1
  38. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ba/ba0VOL0KrwkwcfcuKSnYe1tT0ccddXS8z2KVn_cjtnI.cache +0 -1
  39. data/test/dummy/tmp/cache/assets/sprockets/v3.0/eV/eVN4NMxJn9WpXFRvBaX65H7Ni3Ux4agZLg6r04-9Zf0.cache +0 -0
  40. data/test/dummy/tmp/cache/assets/sprockets/v3.0/gK/gKO1oowLJsUvxaYbr5rucOzM9MDl7D4Ppj8l7q3AX0g.cache +0 -1
  41. data/test/dummy/tmp/cache/assets/sprockets/v3.0/h-/h-Bt2tKoZ131FgeX_De5387nfrje85Zsquko2lu_uL4.cache +0 -0
  42. data/test/dummy/tmp/cache/assets/sprockets/v3.0/hR/hRDjpdlCa6CLHs-KV6u1wHhQ842r9m1R5eEpivfiFBE.cache +0 -1
  43. data/test/dummy/tmp/cache/assets/sprockets/v3.0/hZ/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -2
  44. data/test/dummy/tmp/cache/assets/sprockets/v3.0/jD/jDJ0_EfCHu9gwyqis3I2-EsrfB7dBs8YZzvyqaWoOjU.cache +0 -1
  45. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ly/ly49UX-4__EP86mWF_vobKTgvtAGLxUXqGOAPOzY53g.cache +0 -1
  46. data/test/dummy/tmp/cache/assets/sprockets/v3.0/pE/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +0 -2
  47. data/test/dummy/tmp/cache/assets/sprockets/v3.0/qM/qMiFkN6R1w5uIr6HRgTrSHnbEVddbDAVdz0D1XF7T2I.cache +0 -0
  48. data/test/dummy/tmp/cache/assets/sprockets/v3.0/th/thNa8SIbNZvQMtDF3-dUnEJNEFYxRsND8XYtqA2t328.cache +0 -0
  49. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ui/uiFXrn_ILoEjcXpHWygBCsbEcWFKSiMvofYK6-saGVY.cache +0 -1
  50. data/test/dummy/tmp/cache/assets/sprockets/v3.0/xw/xwxSZPjNVcvVU7DwpeJBJ1ZX6yyIFiCvf0GKrN6bZgc.cache +0 -0
  51. data/test/dummy/tmp/cache/assets/sprockets/v3.0/yp/ypFoyURV_Y0NHlBKznetHE6cVjR-mmRHcGSGQ_hERVg.cache +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 696760761eb3f30b0c9005b4b415517b2425e818b5a314d23872821b3a596877
4
- data.tar.gz: fc24e0c602020f5b8bafb8ec8bc409e7e08ae7a84832654ec4c2b6d8aaf21633
3
+ metadata.gz: f124724d629f69ad95476356da5f41d1d7c6e15f273d93db8b383474875a51f8
4
+ data.tar.gz: 18fee8cb02cfe65e5b16e146f02a189dec55f454528786a932aef7e6d7a472e2
5
5
  SHA512:
6
- metadata.gz: 3037cd3c5f07cf97a16199ffb3c710f6190be9575db5f96037b8d406eeecadc8fa3d2f5e7edf7a83c2a8eb490697d836403157b0d6b5efd14b3370fc5f375f39
7
- data.tar.gz: bff04b8410c8c02c9ddb60d44190d1fc28eac31083e9c19842b3a10197120f4f9f7e1dfc73faafcbb5fe682ad7ebf6806ee091c4c3fd9fd75c9db1fafc2d7ab4
6
+ metadata.gz: 1b8ca750779df577eb512a8b928d60678a01597686a806df8b93b710cab2d696767d30b81dad810edc6c7cd9d339919d4b077933355122482ff16e6daf7d9916
7
+ data.tar.gz: fb94f2c1dc011e29b6b566da7c5265f0ea806b876806caebe1b6c616bed408ccbcdec81b73dfbed8b922fad8778f74432810b29d081a6a83e39673047e5acb18
@@ -2,9 +2,6 @@ require_dependency "deforest/application_controller"
2
2
 
3
3
  module Deforest
4
4
  class FilesController < ApplicationController
5
- before_action :check_if_admin_logged_in
6
- before_action :should_render_source, only: [:index, :show]
7
-
8
5
  def dashboard
9
6
  @top_percentile_methods = {}
10
7
  @medium_percentile_methods = {}
@@ -21,25 +18,6 @@ module Deforest
21
18
  end
22
19
  end
23
20
 
24
- def index
25
- @dirs = []
26
- @files = []
27
- @path = params[:path] || "#{Rails.root}/app/models"
28
- Dir.entries(@path)[2..-1].each do |m|
29
- if Dir.exists?("#{@path}/#{m}")
30
- @dirs << m
31
- else
32
- @files << m
33
- end
34
- end
35
- @dirs.uniq!
36
- end
37
-
38
- def show
39
- @full_path = params[:path]
40
- # @full_path = "#{params[:path]}/#{params[:file_name]}.rb"
41
- end
42
-
43
21
  def extension_data
44
22
  result = Hash.new { |h,k| h[k] = [] }
45
23
  Deforest.track_dirs.each do |dir|
@@ -55,20 +33,5 @@ module Deforest
55
33
  end
56
34
  send_data result.to_json, filename: "deforest.json", type: "application/json", disposition: "attachment"
57
35
  end
58
-
59
- private
60
-
61
- def check_if_admin_logged_in
62
- if send(Deforest.current_admin_method_name).blank?
63
- puts "Make sure to set config.current_admin_method_name to the correct method in config/initializers/deforest.rb"
64
- raise ActionController::RoutingError.new('Not Found')
65
- end
66
- end
67
-
68
- def should_render_source
69
- if !Deforest.render_source_on_browser
70
- redirect_to files_dashboard_path and return
71
- end
72
- end
73
36
  end
74
37
  end
@@ -1,4 +1,4 @@
1
- <h4><%= heading %></h4>
1
+ <h3><%= heading %></h3>
2
2
  <table class="table table-striped">
3
3
  <thead>
4
4
  <tr>
@@ -15,13 +15,7 @@
15
15
  <%= color_and_count[:file_name] %>
16
16
  </td>
17
17
  <td>
18
- <% if Deforest.render_source_on_browser %>
19
- <a href=<%= file_path(path: color_and_count[:file_name], line_no: color_and_count[:line_no]) %>>
20
- <%= method_name %>
21
- </a>
22
- <% else %>
23
- <%= method_name %>
24
- <% end %>
18
+ <%= method_name %>
25
19
  </td>
26
20
  <td>
27
21
  <%= color_and_count[:line_no] %>
@@ -1,29 +1,28 @@
1
- <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
2
- <a class="navbar-brand" href="#">Deforest</a>
3
- <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
4
- <span class="navbar-toggler-icon"></span>
5
- </button>
1
+ <%= link_to "Extension Data", files_extension_data_path, id: "extension-data-btn", aria: { current: "page" } %>
6
2
 
7
- <div class="collapse navbar-collapse" id="navbarSupportedContent">
8
- <ul class="navbar-nav mr-auto">
9
- <li class="nav-item active">
10
- <%= link_to "Extension Data", files_extension_data_path, class: "nav-link active", aria: { current: "page" } %>
11
- </li>
12
- <li class="nav-item dropdown">
13
- <a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-expanded="false">
14
- Directory
15
- </a>
16
- <div class="dropdown-menu">
17
- <% Deforest.track_dirs.each do |dir| %>
18
- <a class="dropdown-item" href="<%= files_dashboard_path(dir: dir) %>"><%= dir %></a>
19
- <% end %>
20
- </div>
21
- </li>
22
- </ul>
23
- </div>
24
- </nav>
3
+ <%= form_tag files_dashboard_path, method: :get do %>
4
+ <%= label_tag "Show data for Directory" %>
5
+ <%= select_tag :dir, options_for_select(Deforest.track_dirs, params[:dir]) %>
6
+ <%= submit_tag "Submit" %>
7
+ <% end %>
25
8
 
26
9
 
27
10
  <%= render partial: "percentile_table", locals: { heading: "Top #{100 - Deforest.most_used_percentile_threshold} percentile", method_stats: @top_percentile_methods } %>
28
11
  <%= render partial: "percentile_table", locals: { heading: "Bottom #{100 - Deforest.most_used_percentile_threshold} percentile", method_stats: @low_percentile_methods } %>
29
- <%= render partial: "percentile_table", locals: { heading: "Between #{Deforest.least_used_percentile_threshold} and #{Deforest.most_used_percentile_threshold} percentile", method_stats: @medium_percentile_methods } %>
12
+ <%#= render partial: "percentile_table", locals: { heading: "Between #{Deforest.least_used_percentile_threshold} and #{Deforest.most_used_percentile_threshold} percentile", method_stats: @medium_percentile_methods } %>
13
+
14
+ <style>
15
+ #extension-data-btn {
16
+ float: right;
17
+ padding: 10px;
18
+ background: blue;
19
+ color: white;
20
+ border-radius: 2px;
21
+ text-decoration: none;
22
+ }
23
+ table {
24
+ border-collapse: separate;
25
+ border-spacing: 10px;
26
+ margin-bottom: 50px;
27
+ }
28
+ </style>
@@ -2,8 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Deforest</title>
5
- <%= stylesheet_link_tag "deforest/application", media: "all" %>
6
- <%= javascript_include_tag "deforest/application" %>
7
5
  <%= csrf_meta_tags %>
8
6
  </head>
9
7
  <body>
@@ -1,3 +1,3 @@
1
1
  module Deforest
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.1"
3
3
  end
data/lib/deforest.rb CHANGED
@@ -4,23 +4,13 @@ require "active_support"
4
4
  require "active_record"
5
5
 
6
6
  module Deforest
7
- mattr_accessor :write_logs_to_db_every, :current_admin_method_name, :most_used_percentile_threshold, :least_used_percentile_threshold, :track_dirs, :render_source_on_browser, :last_saved_log_file_at, :saving_log_file
7
+ mattr_accessor :write_logs_to_db_every, :current_admin_method_name, :most_used_percentile_threshold, :least_used_percentile_threshold, :track_dirs, :last_saved_log_file_at, :saving_log_file
8
8
 
9
9
  def self.get_app_classes(dir)
10
10
  Dir["#{Rails.root}#{dir}/**/*.rb"].each do |f|
11
11
  idx = f.index(dir)
12
12
  models_heirarchy = f[idx..-1].gsub(dir,"")
13
- exec_str = ""
14
- loop do
15
- parent, *children = models_heirarchy.split("/")
16
- if children.any?
17
- exec_str += "#{parent.camelize}::"
18
- else
19
- exec_str += parent.chomp(".rb").camelize
20
- break
21
- end
22
- models_heirarchy = children.join("/")
23
- end
13
+ exec_str = models_heirarchy.split("/").map(&:camelize).join("::").chomp(".rb")
24
14
  begin
25
15
  model = exec_str.constantize
26
16
  yield model
@@ -29,6 +19,40 @@ module Deforest
29
19
  end
30
20
  end
31
21
  end
22
+
23
+ def self.inject_tracking_module(klass, dir, method_type)
24
+ track_methods = if method_type == 'instance'
25
+ klass.instance_methods(false)
26
+ elsif method_type == 'class'
27
+ klass.singleton_methods(false)
28
+ else
29
+ raise "Unknown method type: #{method_type}"
30
+ end
31
+ Module.new do
32
+ track_methods.each do |mname|
33
+ method_location = if method_type == 'instance'
34
+ klass.instance_method(mname).source_location
35
+ else
36
+ klass.singleton_method(mname).source_location
37
+ end
38
+ if method_location.first.ends_with?("#{klass.to_s.underscore}.rb")
39
+ define_method mname do |*args, &block|
40
+ file_name, line_no = method_location
41
+ if file_name.include?(dir)
42
+ Deforest.insert_into_logs(mname, file_name, line_no)
43
+ end
44
+ if Deforest.last_saved_log_file_at < Deforest.write_logs_to_db_every.ago && !Deforest.saving_log_file
45
+ Deforest.parse_and_save_log_file()
46
+ t = Time.zone.now
47
+ Deforest.last_saved_log_file_at = t
48
+ File.open("deforest_db_sync.#{Process.pid}.txt", "w") { |fl| fl.write(t.to_i) }
49
+ end
50
+ super(*args, &block)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
32
56
 
33
57
  def self.initialize!
34
58
  if block_given?
@@ -38,58 +62,19 @@ module Deforest
38
62
  Deforest.track_dirs.each do |dir|
39
63
  self.get_app_classes(dir) do |klass|
40
64
  if klass.present?
41
- klass.prepend(Module.new do
42
- klass.instance_methods(false).each do |mname|
43
- method_location = klass.instance_method(mname).source_location
44
- if method_location.first.ends_with?("#{klass.to_s.underscore}.rb")
45
- define_method mname do |*args, &block|
46
- file_name, line_no = method_location
47
- if file_name.include?(dir)
48
- Deforest.insert_into_logs(mname, file_name, line_no)
49
- end
50
- if Deforest.last_saved_log_file_at < Deforest.write_logs_to_db_every.ago && !Deforest.saving_log_file
51
- Deforest.parse_and_save_log_file()
52
- t = Time.zone.now
53
- Deforest.last_saved_log_file_at = t
54
- File.open("deforest_db_sync.txt", "w") { |fl| fl.write(t.to_i) }
55
- end
56
- super(*args, &block)
57
- end
58
- end
59
- end
60
- end)
61
-
62
- klass.singleton_class.prepend(Module.new do
63
- klass.singleton_methods(false).each do |mname|
64
- method_location = klass.singleton_method(mname).source_location
65
- if method_location.first.ends_with?("#{klass.to_s.underscore}.rb")
66
- define_method mname do |*args, &block|
67
- file_name, line_no = method_location
68
- if file_name.include?(dir)
69
- Deforest.insert_into_logs(mname, file_name, line_no)
70
- end
71
- if Deforest.last_saved_log_file_at < Deforest.write_logs_to_db_every.ago && !Deforest.saving_log_file
72
- Deforest.parse_and_save_log_file()
73
- t = Time.zone.now
74
- Deforest.last_saved_log_file_at = t
75
- File.open("deforest_db_sync.txt", "w") { |fl| fl.write(t.to_i) }
76
- end
77
- super(*args, &block)
78
- end
79
- end
80
- end
81
- end)
65
+ klass.prepend(Deforest.inject_tracking_module(klass, dir, 'instance'))
66
+ klass.singleton_class.prepend(Deforest.inject_tracking_module(klass, dir, 'class'))
82
67
  end
83
68
  end
84
69
  end
85
70
  end
86
71
 
87
72
  def self.initialize_db_sync_file
88
- File.open("deforest.log", "w") unless File.exist?("deforest.log")
89
- if File.exist?("deforest_db_sync.txt")
90
- Deforest.last_saved_log_file_at = Time.at(File.open("deforest_db_sync.txt").read.to_i)
73
+ File.open("deforest.#{Process.pid}.log", "w") unless File.exist?("deforest.#{Process.pid}.log")
74
+ if File.exist?("deforest_db_sync.#{Process.pid}.txt")
75
+ Deforest.last_saved_log_file_at = Time.at(File.open("deforest_db_sync.#{Process.pid}.txt").read.to_i)
91
76
  else
92
- File.open("deforest_db_sync.txt", "w") do |f|
77
+ File.open("deforest_db_sync.#{Process.pid}.txt", "w") do |f|
93
78
  current_time = Time.zone.now
94
79
  Deforest.last_saved_log_file_at = current_time
95
80
  f.write(current_time.to_i)
@@ -99,7 +84,7 @@ module Deforest
99
84
 
100
85
  def self.insert_into_logs(method_name, file_name, line_no)
101
86
  key = "#{file_name}|#{line_no}|#{method_name}\n"
102
- log_file_name = Deforest.saving_log_file ? "deforest_tmp.log" : "deforest.log"
87
+ log_file_name = Deforest.saving_log_file ? "deforest_tmp.#{Process.pid}.log" : "deforest.#{Process.pid}.log"
103
88
  File.open(log_file_name, "a") do |f|
104
89
  f.write(key)
105
90
  end
@@ -109,7 +94,7 @@ module Deforest
109
94
  Deforest.saving_log_file = true
110
95
  sql_stmt = "INSERT INTO deforest_logs (file_name, line_no, method_name, count, created_at, updated_at) VALUES "
111
96
  hash = {}
112
- File.foreach("deforest.log") do |line|
97
+ File.foreach("deforest.#{Process.pid}.log") do |line|
113
98
  line = line.chomp("\n")
114
99
  if hash.has_key?(line)
115
100
  hash[line] += 1
@@ -125,51 +110,36 @@ module Deforest
125
110
  sql_stmt += ";"
126
111
  if hash.present?
127
112
  ActiveRecord::Base.connection.execute(sql_stmt)
128
- if File.exist?("deforest_tmp.log")
129
- File.delete("deforest.log")
130
- File.rename("deforest_tmp.log", "deforest.log")
113
+ if File.exist?("deforest_tmp.#{Process.pid}.log")
114
+ File.delete("deforest.#{Process.pid}.log")
115
+ File.rename("deforest_tmp.#{Process.pid}.log", "deforest.#{Process.pid}.log")
131
116
  else
132
- File.delete("deforest.log")
117
+ File.delete("deforest.#{Process.pid}.log")
133
118
  end
134
119
  end
135
120
  Deforest.saving_log_file = false
136
121
  end
137
122
 
138
- def self.prepare_file_for_render(file)
139
- line_no_count = Log.where(file_name: file).group(:line_no).select("line_no,SUM(count) AS count_sum").inject({}) { |h, el| h.merge!(el.line_no => el.count_sum) }
140
- stack = []
141
- current_highlight_color = nil
142
- highlight = Log.get_highlight_colors_for_file(file)
143
- prepare_for_render(File.open(file).read) do |line, idx|
144
- idx += 1
145
- if line_no_count.has_key?(idx)
146
- stack = [1]
147
- current_highlight_color = highlight[idx]
148
- last_log_for_current_line = Log.where(file_name: file).where(line_no: idx).order("created_at DESC").limit(1).first
149
- "<span id='#{idx}' class='highlight-line #{current_highlight_color}'>" +
150
- line +
151
- "</span>&nbsp;&nbsp;" +
152
- "<span class='method_call_count'>#{line_no_count[idx]}</span>" +
153
- "<span class='last_accessed'>last called at: #{last_log_for_current_line.created_at.localtime.strftime('%m/%d/%Y')}</span>"
154
- else
155
- "<span>#{line}</span>"
156
- end
123
+ def self.most_used_methods(dir, size=1)
124
+ query = Deforest::Log.group(:file_name, :line_no, :method_name)
125
+ if dir.present?
126
+ query = query.where("file_name like '%#{dir}/%'")
127
+ end
128
+ res = query.pluck("file_name, line_no, method_name, SUM(count)")
129
+ .sort_by { |fname, lno, method, cnt| cnt }
130
+ .reverse
131
+ if size == nil
132
+ return res
133
+ else
134
+ return res.take(size)
157
135
  end
158
136
  end
159
137
 
160
- def self.prepare_for_render(source_code, add_line_number = true)
161
- source_code.split("\n").map.with_index do |line, index|
162
- first_letter_idx = line.chars.index { |ch| ch != " " }
163
- if first_letter_idx && first_letter_idx >= 0 && first_letter_idx < line.size
164
- leading_nbsp = (0...first_letter_idx).map { "&nbsp;" }.join("")
165
- prepared_line = leading_nbsp.present? ? leading_nbsp + line.lstrip : line.strip
166
- result_line = if block_given?
167
- yield prepared_line + "\n", index
168
- else
169
- "<span>#{prepared_line}</span>"
170
- end
171
- "<span class='line-no'>#{index + 1}</span>" + result_line
172
- end
173
- end.join("<br/>")
138
+ def self.least_used_methods(dir, size=1)
139
+ if size == nil
140
+ self.most_used_methods(dir, nil).reverse
141
+ else
142
+ self.most_used_methods(dir, nil).reverse.take(size)
143
+ end
174
144
  end
175
145
  end
@@ -11,27 +11,26 @@ class DeforestGenerator < Rails::Generators::Base
11
11
  end
12
12
 
13
13
  def copy_initializer_file
14
- if rails5_and_up? && Rails.autoloaders.zeitwerk_enabled?
14
+ if DeforestGenerator.rails5_and_up? && Rails.autoloaders.zeitwerk_enabled?
15
15
  copy_file "zeitwerk_enabled_initializer.rb", "config/initializers/deforest.rb"
16
16
  else
17
17
  copy_file "classic_enabled_initializer.rb", "config/initializers/deforest.rb"
18
18
  end
19
19
  end
20
20
 
21
- def rails5_and_up?
21
+ def self.rails5_and_up?
22
22
  Rails::VERSION::MAJOR >= 5
23
23
  end
24
24
 
25
25
  def migration_version
26
- if rails5_and_up?
26
+ if DeforestGenerator.rails5_and_up?
27
27
  "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
28
28
  end
29
29
  end
30
30
 
31
31
  def self.next_migration_number(dirname)
32
- if ActiveRecord::Base.timestamped_migrations
33
- current_time = Time.now.utc
34
- current_time.strftime("%Y%m%d%H%M%S")
32
+ if (rails5_and_up? && ActiveRecord.timestamped_migrations) || ActiveRecord::Base.timestamped_migrations
33
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
35
34
  else
36
35
  "%.3d" % (current_numeric_version(dirname) + 1)
37
36
  end
@@ -1,8 +1,6 @@
1
1
  Deforest.initialize! do |config|
2
2
  config.write_logs_to_db_every = 1.minute
3
- config.current_admin_method_name = :current_admin
4
3
  config.most_used_percentile_threshold = 80
5
4
  config.least_used_percentile_threshold = 20
6
5
  config.track_dirs = ["/app/models", "/app/controllers", "/app/helpers"]
7
- config.render_source_on_browser = true
8
6
  end
@@ -1,10 +1,8 @@
1
1
  Rails.application.config.to_prepare do
2
2
  Deforest.initialize! do |config|
3
3
  config.write_logs_to_db_every = 1.minute
4
- config.current_admin_method_name = :current_admin
5
4
  config.most_used_percentile_threshold = 80
6
5
  config.least_used_percentile_threshold = 20
7
6
  config.track_dirs = ["/app/models", "/app/controllers", "/app/helpers"]
8
- config.render_source_on_browser = true
9
7
  end
10
8
  end
@@ -2,31 +2,31 @@ require 'test_helper'
2
2
 
3
3
  class DeforestTest < ActiveSupport::TestCase
4
4
  setup do
5
- File.open("deforest_db_sync.txt", "w") { |f| f.write(1.hour.ago.to_i.to_s) }
5
+ File.open("deforest_db_sync.#{Process.pid}.txt", "w") { |f| f.write(1.hour.ago.to_i.to_s) }
6
6
  Deforest.initialize_db_sync_file
7
7
  Deforest.class_variable_set('@@write_logs_to_db_every', 1.minute)
8
8
  end
9
9
 
10
10
  teardown do
11
- File.delete("deforest_db_sync.txt") if File.exist?("deforest_db_sync.txt")
12
- File.delete("deforest.log") if File.exist?("deforest.log")
11
+ File.delete("deforest_db_sync.#{Process.pid}.txt") if File.exist?("deforest_db_sync.#{Process.pid}.txt")
12
+ File.delete("deforest.#{Process.pid}.log") if File.exist?("deforest.#{Process.pid}.log")
13
13
  end
14
14
 
15
15
  test "initialize db_sync_file when db_sync_file does not exist" do
16
- File.delete("deforest_db_sync.txt")
16
+ File.delete("deforest_db_sync.#{Process.pid}.txt")
17
17
  Deforest.initialize_db_sync_file
18
18
  assert Deforest.class_variable_get("@@last_saved_log_file_at") > 1.minute.ago
19
19
  end
20
20
 
21
21
  test "initialize db_sync_file when db_sync_file does exist" do
22
- File.open("deforest_db_sync.txt", "w") { |f| f.write("1676127114") }
22
+ File.open("deforest_db_sync.#{Process.pid}.txt", "w") { |f| f.write("1676127114") }
23
23
  Deforest.initialize_db_sync_file
24
24
  assert Deforest.class_variable_get("@@last_saved_log_file_at") == Time.at(1676127114)
25
25
  end
26
26
 
27
27
  test "insert into logs" do
28
28
  Deforest.insert_into_logs("lock_user", "/Users/johndoe/workspace/app/models/doctor.rb", 2144)
29
- File.foreach("deforest.log") do |line|
29
+ File.foreach("deforest.#{Process.pid}.log") do |line|
30
30
  line = line.chomp("\n")
31
31
  file_name, line_no, method_name = line.split("|")
32
32
  assert file_name == "/Users/johndoe/workspace/app/models/doctor.rb", "file_name mismatched"
Binary file
@@ -0,0 +1 @@
1
+ 1726132725