tuttle 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +17 -0
  3. data/Rakefile +0 -1
  4. data/app/controllers/tuttle/active_job_controller.rb +1 -0
  5. data/app/controllers/tuttle/active_model_serializers_controller.rb +1 -0
  6. data/app/controllers/tuttle/active_support_controller.rb +1 -0
  7. data/app/controllers/tuttle/application_controller.rb +19 -2
  8. data/app/controllers/tuttle/cancancan_controller.rb +2 -0
  9. data/app/controllers/tuttle/devise_controller.rb +1 -0
  10. data/app/controllers/tuttle/execjs_controller.rb +12 -0
  11. data/app/controllers/tuttle/gems_controller.rb +3 -2
  12. data/app/controllers/tuttle/home_controller.rb +1 -0
  13. data/app/controllers/tuttle/i18n_controller.rb +27 -0
  14. data/app/controllers/tuttle/paperclip_controller.rb +1 -0
  15. data/app/controllers/tuttle/rack_attack_controller.rb +26 -0
  16. data/app/controllers/tuttle/rack_mini_profiler_controller.rb +1 -0
  17. data/app/controllers/tuttle/rails_controller.rb +19 -5
  18. data/app/controllers/tuttle/request_controller.rb +1 -0
  19. data/app/controllers/tuttle/ruby_controller.rb +15 -2
  20. data/app/helpers/tuttle/application_helper.rb +64 -2
  21. data/app/models/tuttle/configuration_registry.rb +1 -0
  22. data/app/models/tuttle/version_detector.rb +1 -0
  23. data/app/views/layouts/tuttle/application.html.erb +22 -6
  24. data/app/views/tuttle/active_support/dependencies.html.erb +7 -7
  25. data/app/views/tuttle/active_support/inflectors.html.erb +1 -1
  26. data/app/views/tuttle/cancancan/index.html.erb +1 -1
  27. data/app/views/tuttle/cancancan/rule_tester.html.erb +3 -3
  28. data/app/views/tuttle/execjs/index.html.erb +87 -0
  29. data/app/views/tuttle/gems/http_clients.html.erb +13 -12
  30. data/app/views/tuttle/gems/index.html.erb +4 -4
  31. data/app/views/tuttle/gems/json.html.erb +10 -10
  32. data/app/views/tuttle/home/index.html.erb +6 -6
  33. data/app/views/tuttle/i18n/_translation_entry.html.erb +10 -0
  34. data/app/views/tuttle/i18n/index.html.erb +111 -0
  35. data/app/views/tuttle/i18n/localize.html.erb +53 -0
  36. data/app/views/tuttle/i18n/translations.html.erb +12 -0
  37. data/app/views/tuttle/rack_attack/index.html.erb +227 -0
  38. data/app/views/tuttle/rails/assets.html.erb +4 -4
  39. data/app/views/tuttle/rails/cache.html.erb +4 -8
  40. data/app/views/tuttle/rails/controllers.html.erb +54 -7
  41. data/app/views/tuttle/rails/database.html.erb +14 -1
  42. data/app/views/tuttle/rails/engines.html.erb +1 -1
  43. data/app/views/tuttle/rails/helpers.html.erb +1 -1
  44. data/app/views/tuttle/rails/index.html.erb +72 -19
  45. data/app/views/tuttle/rails/models.html.erb +150 -73
  46. data/app/views/tuttle/rails/routes.html.erb +10 -8
  47. data/app/views/tuttle/rails/schema_cache.html.erb +2 -2
  48. data/app/views/tuttle/ruby/constants.html.erb +29 -0
  49. data/app/views/tuttle/ruby/extensions.html.erb +24 -0
  50. data/app/views/tuttle/ruby/index.html.erb +21 -15
  51. data/app/views/tuttle/ruby/tuning.html.erb +6 -9
  52. data/config/routes.rb +15 -1
  53. data/lib/tuttle.rb +1 -0
  54. data/lib/tuttle/engine.rb +3 -4
  55. data/lib/tuttle/instrumenter.rb +3 -1
  56. data/lib/tuttle/middleware/request_profiler.rb +11 -11
  57. data/lib/tuttle/presenters/action_dispatch/routing/route_wrapper.rb +34 -2
  58. data/lib/tuttle/presenters/active_record/reflection_presenter.rb +54 -0
  59. data/lib/tuttle/presenters/active_support/callbacks.rb +26 -0
  60. data/lib/tuttle/presenters/base_presenter.rb +19 -0
  61. data/lib/tuttle/presenters/rack_mini_profiler/client_settings.rb +1 -0
  62. data/lib/tuttle/ruby_prof/fast_call_stack_printer.rb +2 -1
  63. data/lib/tuttle/version.rb +2 -1
  64. metadata +27 -18
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  Tuttle::Engine.routes.draw do
2
3
 
3
4
  root :to => 'home#index'
@@ -10,7 +11,7 @@ Tuttle::Engine.routes.draw do
10
11
 
11
12
  namespace :ruby do
12
13
  get '', :action => :index
13
- get :miscellaneous, :tuning
14
+ get :miscellaneous, :tuning, :extensions, :constants
14
15
  end
15
16
 
16
17
  namespace :gems do
@@ -18,6 +19,11 @@ Tuttle::Engine.routes.draw do
18
19
  get :get_process_mem, :http_clients, :json, :other
19
20
  end
20
21
 
22
+ namespace :i18n do
23
+ get '', :action => :index
24
+ get :localize, :translations
25
+ end
26
+
21
27
  namespace :active_support do
22
28
  get '', :action => :index
23
29
  get :dependencies, :inflectors, :time_zones
@@ -52,4 +58,12 @@ Tuttle::Engine.routes.draw do
52
58
  get '/cancancan/rule_tester' => 'cancancan#rule_tester'
53
59
  end
54
60
 
61
+ if defined?(::ExecJS)
62
+ get '/execjs' => 'execjs#index'
63
+ end
64
+
65
+ if defined?(::Rack::Attack)
66
+ get '/rack-attack' => 'rack_attack#index'
67
+ end
68
+
55
69
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'tuttle/version'
2
3
 
3
4
  # TODO: clean this up so that mattr_accessor is not needed
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'tuttle'
2
3
  require 'rails/engine'
3
4
 
@@ -26,7 +27,7 @@ module Tuttle
26
27
 
27
28
  next unless Tuttle.enabled
28
29
 
29
- @logger = ::Logger.new("#{Rails.root}/log/tuttle.log")
30
+ @logger = ::Logger.new(Rails.root.join('log', 'tuttle.log'))
30
31
  Tuttle::Engine.logger.info('Tuttle engine started')
31
32
 
32
33
  Tuttle.automount_engine = true if Tuttle.automount_engine.nil?
@@ -34,9 +35,7 @@ module Tuttle
34
35
  mount_engine! if Tuttle.automount_engine
35
36
  use_profiling_middleware! if Tuttle.enable_profiling
36
37
 
37
- if Tuttle.track_notifications
38
- Tuttle::Instrumenter.initialize_tuttle_instrumenter
39
- end
38
+ Tuttle::Instrumenter.initialize_tuttle_instrumenter if Tuttle.track_notifications
40
39
  end
41
40
 
42
41
  config.to_prepare do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  class Instrumenter
3
4
 
@@ -20,7 +21,8 @@ module Tuttle
20
21
  # Hitting the cache inspector page will enable it for that session.
21
22
  Tuttle::Engine.logger.info('Initializing cache_read subscriber')
22
23
  ActiveSupport::Notifications.subscribe('cache_read.active_support') do |*args|
23
- cache_call_location = caller_locations.detect { |cl| cl.path.start_with?("#{Rails.root}/app".freeze) }
24
+ app_path = Rails.root.join('app').to_s
25
+ cache_call_location = caller_locations.detect { |cl| cl.path.start_with?(app_path) }
24
26
  event = ActiveSupport::Notifications::Event.new(*args)
25
27
 
26
28
  Tuttle::Engine.logger.info("Cache Read called: #{cache_call_location.path} on line #{cache_call_location.lineno} :: #{event.payload.inspect}")
@@ -11,7 +11,7 @@ module Tuttle
11
11
  def call(env)
12
12
  query_string = env['QUERY_STRING']
13
13
 
14
- tuttle_profiler_action = /(^|[&?])tuttle\-profiler=([\w\-]*)/.match(query_string) { |m| m[2] }
14
+ tuttle_profiler_action = /(^|[&?])tuttle-profiler=([\w\-]*)/.match(query_string) { |m| m[2] }
15
15
 
16
16
  case tuttle_profiler_action
17
17
  when 'memory_profiler', 'memory'
@@ -67,7 +67,7 @@ module Tuttle
67
67
  query_params = Rack::Utils.parse_nested_query(query_string)
68
68
  options = {}
69
69
  options[:threshold] = Float(query_params['ruby-prof_threshold']) if query_params.key?('ruby-prof_threshold')
70
- rubyprof_printer = /ruby\-prof_printer=([\w]*)/.match(query_string) { |m| m[1] }
70
+ rubyprof_printer = /ruby-prof_printer=([\w]*)/.match(query_string) { |m| m[1] }
71
71
 
72
72
  data = ::RubyProf::Profile.profile do
73
73
  _, _, body = @app.call(env)
@@ -96,10 +96,10 @@ module Tuttle
96
96
  end
97
97
 
98
98
  # These methods *may* cause the method cache to be invalidated
99
- TRACE_METHODS = Set.new([:extend, :include, :const_set, :remove_const, :alias_method, :remove_method,
100
- :prepend, :append_features, :prepend_features,
101
- :public_constant, :private_constant, :autoload,
102
- :define_method, :define_singleton_method])
99
+ TRACE_METHODS = Set.new(%i[extend include const_set remove_const alias_method remove_method
100
+ prepend append_features prepend_features
101
+ public_constant private_constant autoload
102
+ define_method define_singleton_method])
103
103
 
104
104
  def profile_busted(env, _query_string)
105
105
  # Note: Requires Busted (of course) and DTrace so will need much better error handling and information
@@ -166,7 +166,7 @@ module Tuttle
166
166
 
167
167
  # Prepare the output
168
168
  output = "\nRubyVM.stat: Before After Change\n".dup
169
- [:global_method_state, :global_constant_state, :class_serial].each do |stat|
169
+ %i[global_method_state global_constant_state class_serial].each do |stat|
170
170
  output << format("%-22s %-10d %-10d %+d\n",
171
171
  stat,
172
172
  vmstat_before[stat],
@@ -195,18 +195,18 @@ module Tuttle
195
195
 
196
196
  output << "\nTraces (method cache clearing calls): (#{cache_busters.size} times)\n"
197
197
  cache_busters.each do |trace_info|
198
- if trace_info[:event] == :c_call
199
- output << format("%s\#%s: %s %s\n",
198
+ output << if trace_info[:event] == :c_call
199
+ format("%s\#%s: %s %s\n",
200
200
  trace_info[:defined_class],
201
201
  trace_info[:method_id],
202
202
  trace_info[:target_class],
203
203
  trace_info[:location])
204
204
  else
205
- output << format("Class Definition: %s %s %s\n",
205
+ format("Class Definition: %s %s %s\n",
206
206
  trace_info[:target_class],
207
207
  trace_info[:defined_class],
208
208
  trace_info[:location])
209
- end
209
+ end
210
210
  end
211
211
 
212
212
  [200,
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  module Presenters
3
4
  module ActionDispatch
@@ -24,8 +25,39 @@ module Tuttle
24
25
  rack_app.respond_to?(:dispatcher?)
25
26
  end
26
27
 
27
- def internal_to_rails?
28
- true == internal?
28
+ def route_problem
29
+ # TODO: this does not handle ImplicitRender actions where the method does not exist but the template does
30
+ return @route_problem if defined?(@route_problem)
31
+ @route_problem =
32
+ if controller_klass
33
+ if requirements[:action] && controller_klass.action_methods.exclude?(action)
34
+ 'Action does not exist'
35
+ end
36
+ elsif requirements[:controller]
37
+ 'Controller does not exist'
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def controller_klass
44
+ return @controller_klass if defined?(@controller_klass)
45
+ @controller_klass =
46
+ if requirements[:controller].present?
47
+ begin
48
+ controller_reference(controller)
49
+ rescue NameError
50
+ # No class is defined for the give route
51
+ # puts "NameError for #{requirements[:controller]}"
52
+ nil
53
+ end
54
+ end
55
+ end
56
+
57
+ # Copied from <actionpack>/lib/action_dispatch/routing/route_set.rb
58
+ def controller_reference(controller_param)
59
+ const_name = "#{controller_param.camelize}Controller"
60
+ ::ActiveSupport::Dependencies.constantize(const_name)
29
61
  end
30
62
 
31
63
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'tuttle/presenters/base_presenter'
3
+
4
+ module Tuttle
5
+ module Presenters
6
+ module ActiveRecord
7
+ class ReflectionPresenter < ::Tuttle::Presenters::BasePresenter
8
+
9
+ def name; super.inspect end
10
+ def macro; super.inspect end
11
+ def type; super rescue 'Unknown' end
12
+
13
+ def inverse_of
14
+ if has_inverse?
15
+ h.content_tag(:span, has_inverse?.inspect, class: options[:inverse_of].present? ? 'specified' : 'autodetected')
16
+ end
17
+ end
18
+
19
+ def scoped?
20
+ # TODO: potentially show the scope
21
+ h.true_label(scope.present?, 'scoped')
22
+ end
23
+
24
+ def polymorphic?
25
+ h.true_label(super, 'polymorphic')
26
+ end
27
+
28
+ def validate?
29
+ h.true_label(super, 'validate')
30
+ end
31
+
32
+ def options_dependent; options[:dependent] rescue 'Unknown' end
33
+ def options_class_name; options[:class_name] rescue 'Unknown' end
34
+
35
+ def options_autosave
36
+ h.true_label(options[:autosave].present?, 'autosave')
37
+ end
38
+
39
+ def options_required
40
+ ## Todo handle auto-required?
41
+ h.true_label(options[:required].present?, 'required')
42
+ end
43
+
44
+ def foreign_key; super rescue 'Unknown' end
45
+
46
+ def options_other
47
+ other_options = options.except(:polymorphic, :dependent, :class_name, :autosave, :before_add, :before_remove)
48
+ other_options.inspect unless other_options.empty?
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require 'delegate'
3
+
4
+ module Tuttle
5
+ module Presenters
6
+ module ActiveSupport
7
+ module Callbacks
8
+ class CallbackWrapper < DelegateClass(::ActiveSupport::Callbacks::Callback)
9
+ def safe_source_location(controller_instance)
10
+ controller_instance.method(filter).try(:source_location)
11
+ rescue StandardError
12
+ [nil, nil]
13
+ end
14
+ end
15
+
16
+ class CallbackChainWrapper < DelegateClass(::ActiveSupport::Callbacks::CallbackChain)
17
+ delegate :size, to: :chain
18
+
19
+ def each(&block)
20
+ chain.map { |cb| CallbackWrapper.new(::Tuttle::Presenters::ActiveSupport::Callbacks::CallbackWrapper.new(cb)) } .each(&block)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require 'tuttle'
3
+ require 'delegate'
4
+
5
+ module Tuttle
6
+ module Presenters
7
+ class BasePresenter < SimpleDelegator
8
+ def initialize(delegate, view)
9
+ @view = view
10
+ super(delegate)
11
+ end
12
+
13
+ # noinspection RubyInstanceMethodNamingConvention
14
+ def h
15
+ @view
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  module Presenters
3
4
  module RackMiniProfiler
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'ruby-prof/printers/call_stack_printer'
2
3
 
3
4
  # This is a modified version of the RubyProf::CallStackPrinter
@@ -27,7 +28,7 @@ module Tuttle
27
28
 
28
29
  @result.threads.each do |thread|
29
30
  @overall_time = thread.total_time
30
- thread_info = "Thread: #{thread.id}"
31
+ thread_info = "Thread: #{thread.id}".dup
31
32
  thread_info << ", Fiber: #{thread.fiber_id}" unless thread.id == thread.fiber_id
32
33
  thread_info << format(' (%4.2f%% ~ %f)', (@overall_time / @overall_threads_time) * 100, @overall_time)
33
34
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
- VERSION = '0.0.6'.freeze
3
+ VERSION = '0.0.8'.freeze
3
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tuttle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Gynn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-09 00:00:00.000000000 Z
11
+ date: 2018-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,35 +16,30 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '5.1'
19
+ version: 4.1.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: 4.0.0
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '5.1'
26
+ version: 4.1.0
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: appraisal
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
- - - "~>"
31
+ - - ">="
38
32
  - !ruby/object:Gem::Version
39
- version: '0'
33
+ version: 2.2.0
40
34
  type: :development
41
35
  prerelease: false
42
36
  version_requirements: !ruby/object:Gem::Requirement
43
37
  requirements:
44
- - - "~>"
38
+ - - ">="
45
39
  - !ruby/object:Gem::Version
46
- version: '0'
47
- description: Rails server inspector
40
+ version: 2.2.0
41
+ description: Tuttle is a tool for Rails developers to inspect the runtime configuration
42
+ information of their applications, libraries, and frameworks.
48
43
  email:
49
44
  - davegynn@gmail.com
50
45
  executables: []
@@ -61,9 +56,12 @@ files:
61
56
  - app/controllers/tuttle/application_controller.rb
62
57
  - app/controllers/tuttle/cancancan_controller.rb
63
58
  - app/controllers/tuttle/devise_controller.rb
59
+ - app/controllers/tuttle/execjs_controller.rb
64
60
  - app/controllers/tuttle/gems_controller.rb
65
61
  - app/controllers/tuttle/home_controller.rb
62
+ - app/controllers/tuttle/i18n_controller.rb
66
63
  - app/controllers/tuttle/paperclip_controller.rb
64
+ - app/controllers/tuttle/rack_attack_controller.rb
67
65
  - app/controllers/tuttle/rack_mini_profiler_controller.rb
68
66
  - app/controllers/tuttle/rails_controller.rb
69
67
  - app/controllers/tuttle/request_controller.rb
@@ -83,13 +81,19 @@ files:
83
81
  - app/views/tuttle/cancancan/index.html.erb
84
82
  - app/views/tuttle/cancancan/rule_tester.html.erb
85
83
  - app/views/tuttle/devise/index.html.erb
84
+ - app/views/tuttle/execjs/index.html.erb
86
85
  - app/views/tuttle/gems/get_process_mem.html.erb
87
86
  - app/views/tuttle/gems/http_clients.html.erb
88
87
  - app/views/tuttle/gems/index.html.erb
89
88
  - app/views/tuttle/gems/json.html.erb
90
89
  - app/views/tuttle/gems/other.html.erb
91
90
  - app/views/tuttle/home/index.html.erb
91
+ - app/views/tuttle/i18n/_translation_entry.html.erb
92
+ - app/views/tuttle/i18n/index.html.erb
93
+ - app/views/tuttle/i18n/localize.html.erb
94
+ - app/views/tuttle/i18n/translations.html.erb
92
95
  - app/views/tuttle/paperclip/index.html.erb
96
+ - app/views/tuttle/rack_attack/index.html.erb
93
97
  - app/views/tuttle/rack_mini_profiler/index.html.erb
94
98
  - app/views/tuttle/rails/_cache_dalli_store.html.erb
95
99
  - app/views/tuttle/rails/_cache_memory_store.html.erb
@@ -107,6 +111,8 @@ files:
107
111
  - app/views/tuttle/rails/routes.html.erb
108
112
  - app/views/tuttle/rails/schema_cache.html.erb
109
113
  - app/views/tuttle/request/index.html.erb
114
+ - app/views/tuttle/ruby/constants.html.erb
115
+ - app/views/tuttle/ruby/extensions.html.erb
110
116
  - app/views/tuttle/ruby/index.html.erb
111
117
  - app/views/tuttle/ruby/miscellaneous.html.erb
112
118
  - app/views/tuttle/ruby/tuning.html.erb
@@ -120,6 +126,9 @@ files:
120
126
  - lib/tuttle/instrumenter.rb
121
127
  - lib/tuttle/middleware/request_profiler.rb
122
128
  - lib/tuttle/presenters/action_dispatch/routing/route_wrapper.rb
129
+ - lib/tuttle/presenters/active_record/reflection_presenter.rb
130
+ - lib/tuttle/presenters/active_support/callbacks.rb
131
+ - lib/tuttle/presenters/base_presenter.rb
123
132
  - lib/tuttle/presenters/rack_mini_profiler/client_settings.rb
124
133
  - lib/tuttle/ruby_prof/fast_call_stack_printer.rb
125
134
  - lib/tuttle/version.rb
@@ -135,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
144
  requirements:
136
145
  - - ">="
137
146
  - !ruby/object:Gem::Version
138
- version: 2.0.0
147
+ version: 2.1.0
139
148
  required_rubygems_version: !ruby/object:Gem::Requirement
140
149
  requirements:
141
150
  - - ">="
@@ -143,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
152
  version: '0'
144
153
  requirements: []
145
154
  rubyforge_project:
146
- rubygems_version: 2.5.2
155
+ rubygems_version: 2.7.5
147
156
  signing_key:
148
157
  specification_version: 4
149
- summary: Tuttle for Rails
158
+ summary: Rails runtime configuration inspector
150
159
  test_files: []