rails-footnotes 4.1.5 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +25 -0
  3. data/.gitignore +4 -3
  4. data/CHANGELOG +8 -0
  5. data/Gemfile +8 -1
  6. data/Gemfile.lock +187 -0
  7. data/README.rdoc +8 -54
  8. data/Rakefile +1 -6
  9. data/bin/rake +29 -0
  10. data/bin/rspec +29 -0
  11. data/gemfiles/{Gemfile.rails-3.2.x → Gemfile.rails-3.2.22} +1 -1
  12. data/lib/generators/templates/rails_footnotes.rb +4 -5
  13. data/lib/rails-footnotes.rb +9 -9
  14. data/lib/rails-footnotes/extension.rb +8 -11
  15. data/lib/rails-footnotes/filter.rb +13 -4
  16. data/lib/rails-footnotes/notes/assigns_note.rb +2 -2
  17. data/lib/rails-footnotes/notes/files_note.rb +12 -23
  18. data/lib/rails-footnotes/notes/log_note.rb +1 -1
  19. data/lib/rails-footnotes/notes/params_note.rb +5 -1
  20. data/lib/rails-footnotes/notes/queries_note.rb +9 -10
  21. data/lib/rails-footnotes/notes/view_note.rb +16 -7
  22. data/lib/rails-footnotes/version.rb +1 -1
  23. data/lib/rails6-footnotes.rb +1 -0
  24. data/rails-footnotes.gemspec +5 -10
  25. data/spec/abstract_note_spec.rb +17 -13
  26. data/spec/app/assets/config/manifest.js +2 -0
  27. data/spec/app/assets/javascripts/foobar.js +1 -0
  28. data/spec/app/assets/stylesheets/foobar.css +0 -0
  29. data/spec/app/views/files/index.html.erb +1 -0
  30. data/spec/app/views/layouts/application.html.erb +12 -0
  31. data/spec/{views → app/views}/partials/_foo.html.erb +0 -0
  32. data/spec/{views → app/views}/partials/index.html.erb +0 -0
  33. data/spec/controllers/files_note_controller_spec.rb +38 -0
  34. data/spec/controllers/footnotes_controller_spec.rb +49 -34
  35. data/spec/controllers/log_note_controller_spec.rb +4 -8
  36. data/spec/controllers/partials_note_controller_spec.rb +2 -3
  37. data/spec/env_note_spec.rb +4 -4
  38. data/spec/footnotes_spec.rb +38 -54
  39. data/spec/notes/assigns_note_spec.rb +13 -9
  40. data/spec/notes/controller_note_spec.rb +2 -2
  41. data/spec/notes/files_note_spec.rb +12 -3
  42. data/spec/notes/javascripts_note_spec.rb +1 -1
  43. data/spec/notes/stylesheets_note_spec.rb +1 -1
  44. data/spec/notes/view_note_spec.rb +18 -0
  45. data/spec/spec_helper.rb +35 -3
  46. metadata +38 -48
  47. data/.travis.yml +0 -14
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec :path => '..'
4
4
 
5
- gem 'rails', '~> 3.2.0'
5
+ gem 'rails', '~> 3.2.22'
@@ -1,11 +1,10 @@
1
- defined?(Footnotes) && Footnotes.setup do |f|
1
+ Footnotes.setup do |f|
2
2
  # Whether or not to enable footnotes
3
3
  f.enabled = Rails.env.development?
4
- # You can also use a lambda / proc to conditionally toggle footnotes
5
- # Example :
4
+ # You can also use a lambda / proc to conditionally toggle footnotes, like
6
5
  # f.enabled = -> { User.current.admin? }
7
6
  # Beware of thread-safety though, Footnotes.enabled is NOT thread safe
8
- # and should not be modified anywhere else.
7
+ # and should not be modified outside this initializer.
9
8
 
10
9
  # Only toggle some notes :
11
10
  # f.notes = [:session, :cookies, :params, :filters, :routes, :env, :queries, :log]
@@ -24,4 +23,4 @@ defined?(Footnotes) && Footnotes.setup do |f|
24
23
 
25
24
  # Allow to open multiple notes :
26
25
  # f.multiple_notes = true
27
- end
26
+ end if defined?(Footnotes) && Footnotes.respond_to?(:setup)
@@ -5,7 +5,6 @@ require 'rails-footnotes/each_with_rescue'
5
5
  require 'rails-footnotes/filter'
6
6
  require 'rails-footnotes/notes/all'
7
7
  require 'rails-footnotes/extension'
8
- require 'active_support/deprecation'
9
8
 
10
9
  module Footnotes
11
10
  mattr_accessor :before_hooks
@@ -37,11 +36,6 @@ module Footnotes
37
36
  delegate :font_size=, :to => Filter
38
37
  end
39
38
 
40
- def self.run!
41
- ActiveSupport::Deprecation.warn "run! is deprecated and will be removed from future releases, use Footnotes.setup or Footnotes.enabled instead.", caller
42
- Footnotes.enabled = true
43
- end
44
-
45
39
  def self.before(&block)
46
40
  @@before_hooks << block
47
41
  end
@@ -50,9 +44,13 @@ module Footnotes
50
44
  @@after_hooks << block
51
45
  end
52
46
 
53
- def self.enabled?
47
+ def self.enabled?(controller)
54
48
  if @@enabled.is_a? Proc
55
- @@enabled.call
49
+ if @@enabled.arity == 1
50
+ @@enabled.call(controller)
51
+ else
52
+ @@enabled.call
53
+ end
56
54
  else
57
55
  !!@@enabled
58
56
  end
@@ -63,6 +61,8 @@ module Footnotes
63
61
  end
64
62
  end
65
63
 
66
- ActionController::Base.send(:include, Footnotes::RailsFootnotesExtension)
64
+ ActiveSupport.on_load(:action_controller) do
65
+ ActionController::Base.send(:include, Footnotes::RailsFootnotesExtension)
66
+ end
67
67
 
68
68
  load Rails.root.join('.rails_footnotes') if Rails.root && Rails.root.join('.rails_footnotes').exist?
@@ -2,26 +2,23 @@ require 'active_support/concern'
2
2
 
3
3
  module Footnotes
4
4
  module RailsFootnotesExtension
5
-
6
5
  extend ActiveSupport::Concern
7
6
 
8
7
  included do
9
- prepend_before_filter :rails_footnotes_before_filter
10
- after_filter :rails_footnotes_after_filter
8
+ prepend_before_action :rails_footnotes_before_filter
9
+ after_action :rails_footnotes_after_filter
11
10
  end
12
11
 
13
12
  def rails_footnotes_before_filter
14
- if Footnotes.enabled?
15
- Footnotes::Filter.start!(self)
16
- end
13
+ Footnotes::Filter.start!(self) if Footnotes.enabled?(self)
17
14
  end
18
15
 
19
16
  def rails_footnotes_after_filter
20
- if Footnotes.enabled?
21
- filter = Footnotes::Filter.new(self)
22
- filter.add_footnotes!
23
- filter.close!(self)
24
- end
17
+ return unless Footnotes.enabled?(self)
18
+
19
+ filter = Footnotes::Filter.new(self)
20
+ filter.add_footnotes!
21
+ filter.close!(self)
25
22
  end
26
23
  end
27
24
  end
@@ -47,7 +47,7 @@ module Footnotes
47
47
  if args.empty?
48
48
  @@prefix
49
49
  else
50
- args.map! { |arg| URI.escape(arg.to_s) }
50
+ args.map! { |arg| arg.to_s.split("/").map{|s| ERB::Util.url_encode(s) }.join("/") }
51
51
 
52
52
  if @@prefix.respond_to? :call
53
53
  @@prefix.call *args
@@ -116,7 +116,8 @@ module Footnotes
116
116
  end
117
117
 
118
118
  def valid_format?
119
- ['text/html', nil].include? @controller.response.content_type
119
+ format = @controller.response.content_type
120
+ format.nil? || format.include?("text/html")
120
121
  end
121
122
 
122
123
  def valid_content_type?
@@ -169,7 +170,7 @@ module Footnotes
169
170
  #footnotes_debug table td {padding: 5px; border-bottom: 1px solid #ccc;}
170
171
  #footnotes_debug table td strong {color: #9b1b1b;}
171
172
  #footnotes_debug table th {padding: 5px; border-bottom: 1px solid #ccc;}
172
- #footnotes_debug table tr:nth-child(2n) td {background: #eee;}
173
+ #footnotes_debug table tr:nth-child(2n) td {background: #f5f5f5;}
173
174
  #footnotes_debug table tr:nth-child(2n + 1) td {background: #fff;}
174
175
  #footnotes_debug tbody {text-align: left;}
175
176
  #footnotes_debug .name_values td {vertical-align: top;}
@@ -207,14 +208,22 @@ module Footnotes
207
208
  }
208
209
 
209
210
  function hideAllAndToggle(id) {
211
+ var n = note(id);
212
+ var display = n.style.display;
210
213
  hideAll();
214
+ // Restore original display to allow toggling
215
+ n.style.display = display;
211
216
  toggle(id)
212
217
 
213
218
  location.href = '#footnotes_debug';
214
219
  }
215
220
 
221
+ function note(id) {
222
+ return (document.getElementById(id));
223
+ }
224
+
216
225
  function toggle(id){
217
- var el = document.getElementById(id);
226
+ var el = note(id);
218
227
  if (el.style.display == 'none') {
219
228
  Footnotes.show(el);
220
229
  } else {
@@ -16,9 +16,9 @@ module Footnotes
16
16
  :@view_runtime,
17
17
  :@marked_for_same_origin_verification
18
18
  ]
19
- cattr_accessor :ignored_assigns, :instance_writter => false
19
+ cattr_accessor :ignored_assigns, :instance_writer => false
20
20
  @@ignored_assigns_pattern = /^@_/
21
- cattr_accessor :ignored_assigns_pattern, :instance_writter => false
21
+ cattr_accessor :ignored_assigns_pattern, :instance_writer => false
22
22
 
23
23
  def initialize(controller)
24
24
  @controller = controller
@@ -24,36 +24,25 @@ module Footnotes
24
24
 
25
25
  protected
26
26
  def scan_text(text)
27
- []
27
+ raise NotImplementedError, "implement this in your subclass"
28
28
  end
29
29
 
30
30
  def parse_files!
31
- if Rails.version >= '3.1' && Rails.application.config.assets[:enabled]
32
- asset_paths = Rails.application.config.assets.paths
33
- linked_files = []
31
+ asset_paths = Rails.application.config.try(:assets).try(:paths) || []
32
+ linked_files = []
34
33
 
35
- @files.collect do |file|
36
- base_name = File.basename(file)
37
- asset_paths.each do |asset_path|
38
- results = Dir[File.expand_path(base_name, asset_path) + '*']
39
- results.each do |r|
40
- linked_files << %[<a href="#{Footnotes::Filter.prefix(r, 1, 1)}">#{File.basename(r)}</a>]
41
- end
42
- break if results.present?
43
- end
44
- end
45
- @files = linked_files
46
- else
47
- #Original Implementation
48
- @files.collect! do |filename|
49
- if filename =~ %r{^/}
50
- full_filename = File.join(File.expand_path(Rails.root), 'public', filename)
51
- %[<a href="#{Footnotes::Filter.prefix(full_filename, 1, 1)}">#{filename}</a>]
52
- else
53
- %[<a href="#{filename}">#{filename}</a>]
34
+ @files.collect do |file|
35
+ file.gsub!(/-[a-f0-9]{64}\./, '.')
36
+ base_name = File.basename(file)
37
+ asset_paths.each do |asset_path|
38
+ results = Dir[File.expand_path(base_name, asset_path) + '*']
39
+ results.each do |r|
40
+ linked_files << %[<a href="#{Footnotes::Filter.prefix(r, 1, 1)}">#{File.basename(r)}</a>]
54
41
  end
42
+ break if results.present?
55
43
  end
56
44
  end
45
+ @files = linked_files
57
46
  end
58
47
  end
59
48
  end
@@ -20,7 +20,7 @@ module Footnotes
20
20
  end
21
21
  # Rails 3 don't have ActiveSupport::Logger#broadcast so we backported it
22
22
  extend_module = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger.broadcast(note_logger) : NoteLogger.broadcast(note_logger)
23
- Rails.logger = self.original_logger.dup.extend(extend_module)
23
+ Rails.logger = self.original_logger.clone.extend(extend_module)
24
24
  end
25
25
 
26
26
  def title
@@ -2,7 +2,11 @@ module Footnotes
2
2
  module Notes
3
3
  class ParamsNote < AbstractNote
4
4
  def initialize(controller)
5
- @params = controller.params.symbolize_keys
5
+ @params = if Rails::VERSION::MAJOR >= 5
6
+ controller.params.to_unsafe_h
7
+ else
8
+ controller.params
9
+ end
6
10
  end
7
11
 
8
12
  def title
@@ -1,7 +1,7 @@
1
1
  module Footnotes
2
2
  module Notes
3
3
  class QueriesNote < AbstractNote
4
- cattr_accessor :alert_db_time, :alert_sql_number, :orm, :ignored_regexps, :instance_writter => false
4
+ cattr_accessor :alert_db_time, :alert_sql_number, :orm, :ignored_regexps, :instance_writer => false
5
5
  @@alert_db_time = 16.0
6
6
  @@alert_sql_number = 8
7
7
  @@query_subscriber = nil
@@ -23,8 +23,8 @@ module Footnotes
23
23
  def title
24
24
  queries = self.events.count
25
25
  total_time = self.events.map(&:duration).sum
26
- query_color = generate_red_color(self.events.count, alert_sql_number)
27
- db_color = generate_red_color(total_time, alert_db_time)
26
+ query_color = alert_color(self.events.count, alert_sql_number)
27
+ db_color = alert_color(total_time, alert_db_time)
28
28
 
29
29
  <<-TITLE
30
30
  <span style="background-color:#{query_color}">Queries (#{queries})</span>
@@ -47,7 +47,7 @@ module Footnotes
47
47
  <td>
48
48
  <span id="sql_#{index}">#{print_query(event.payload[:sql])}</span>
49
49
  </td>
50
- <td>#{print_name_and_time(event.payload[:name], event.duration / 1000.0)}</td>
50
+ <td>#{print_name_and_time(event.payload[:name], event.duration)}</td>
51
51
  </tr>
52
52
  HTML
53
53
  end
@@ -57,17 +57,16 @@ module Footnotes
57
57
 
58
58
  protected
59
59
  def print_name_and_time(name, time)
60
- "<span style='background-color:#{generate_red_color(time, alert_ratio)}'>#{escape(name || 'SQL')} (#{'%.3fms' % time})</span>"
60
+ "<span style='background-color:#{alert_color(time, alert_ratio)}'>#{escape(name || 'SQL')} (#{'%.3fms' % time})</span>"
61
61
  end
62
62
 
63
63
  def print_query(query)
64
64
  escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
65
65
  end
66
66
 
67
- def generate_red_color(value, alert)
68
- c = ((value.to_f/alert).to_i - 1) * 16
69
- c = 0 if c < 0; c = 15 if c > 15; c = (15-c).to_s(16)
70
- "#ff#{c*4}"
67
+ def alert_color(value, threshold)
68
+ return 'transparent' if value < threshold
69
+ '#ffff00'
71
70
  end
72
71
 
73
72
  def alert_ratio
@@ -103,7 +102,7 @@ module Footnotes
103
102
  attr_accessor :events, :ignore_regexps
104
103
 
105
104
  def initialize(orm)
106
- super()
105
+ super()
107
106
  @events = []
108
107
  orm.each {|adapter| ActiveSupport::LogSubscriber.attach_to adapter, self}
109
108
  end
@@ -1,31 +1,40 @@
1
1
  module Footnotes
2
2
  module Notes
3
3
  class ViewNote < AbstractNote
4
+ cattr_accessor :template
5
+
6
+ def self.start!(controller)
7
+ @subscriber ||= ActiveSupport::Notifications.subscribe('render_template.action_view') do |*args|
8
+ event = ActiveSupport::Notifications::Event.new *args
9
+ self.template = {:file => event.payload[:identifier], :duration => event.duration}
10
+ end
11
+ end
12
+
4
13
  def initialize(controller)
5
14
  @controller = controller
6
- @template = controller.instance_variable_get(:@template)
7
15
  end
8
16
 
9
17
  def row
10
18
  :edit
11
19
  end
12
20
 
21
+ def title
22
+ "View (#{"%.3f" % self.template[:duration]}ms)"
23
+ end
24
+
13
25
  def link
14
26
  escape(Footnotes::Filter.prefix(filename, 1, 1))
15
27
  end
16
28
 
17
29
  def valid?
18
- prefix? && first_render?
30
+ prefix? && filename && File.exists?(filename)
19
31
  end
20
32
 
21
33
  protected
22
34
 
23
- def first_render?
24
- @template.instance_variable_get(:@_first_render)
25
- end
26
-
27
35
  def filename
28
- @filename ||= @template.instance_variable_get(:@_first_render).filename
36
+ return @filename if defined?(@filename)
37
+ @filename = self.class.template.try(:[], :file)
29
38
  end
30
39
 
31
40
  end
@@ -1,3 +1,3 @@
1
1
  module Footnotes
2
- VERSION = "4.1.5"
2
+ VERSION = "5.0.0"
3
3
  end
@@ -0,0 +1 @@
1
+ require_relative "./rails-footnotes"
@@ -6,21 +6,16 @@ Gem::Specification.new do |s|
6
6
  s.name = "rails-footnotes"
7
7
  s.version = Footnotes::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson", "Adrien Siami"]
10
- s.email = ["romanvbabenko@gmail.com"]
11
- s.homepage = "http://github.com/josevalim/rails-footnotes"
9
+ s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson", "Adrien Siami", "André Arko"]
10
+ s.email = ["andre@arko.net"]
11
+ s.homepage = "http://github.com/indirect/rails-footnotes"
12
12
  s.summary = %q{Every Rails page has footnotes that gives information about your application and links back to your editor.}
13
13
  s.description = %q{Every Rails page has footnotes that gives information about your application and links back to your editor.}
14
14
 
15
- s.rubyforge_project = "rails-footnotes"
16
-
17
- s.add_dependency "rails", ">= 3.2"
18
-
19
- s.add_development_dependency "rspec-rails", '~> 2.14.0'
20
- s.add_development_dependency "capybara"
15
+ s.add_dependency "rails", "~> 6.0"
16
+ s.required_ruby_version = "~> 3.0"
21
17
 
22
18
  s.files = `git ls-files`.split("\n")
23
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
25
20
  s.require_paths = ["lib"]
26
21
  end
@@ -11,17 +11,21 @@ describe Footnotes::Notes::AbstractNote do
11
11
  Footnotes::Filter.notes = @notes
12
12
  end
13
13
 
14
- it {described_class.should respond_to :start!}
15
- it {described_class.should respond_to :close!}
16
- it {described_class.should respond_to :title}
14
+ it {expect(described_class).to respond_to :start!}
15
+ it {expect(described_class).to respond_to :close!}
16
+ it {expect(described_class).to respond_to :title}
17
17
 
18
18
  it {should respond_to :to_sym}
19
- its(:to_sym) {should eql :abstract}
20
19
 
21
- it { described_class.should be_included }
20
+ describe '#to_sym' do
21
+ subject { super().to_sym }
22
+ it {should eql :abstract}
23
+ end
24
+
25
+ it { expect(described_class).to be_included }
22
26
  specify do
23
27
  Footnotes::Filter.notes = []
24
- described_class.should_not be_included
28
+ expect(described_class).not_to be_included
25
29
  end
26
30
 
27
31
  it { should respond_to :row }
@@ -45,12 +49,12 @@ describe Footnotes::Notes::AbstractNote do
45
49
 
46
50
  #TODO should be moved to builder
47
51
  #helpers
48
- specify { subject.escape('<').should eql '&lt;' }
49
- specify { subject.escape('&').should eql '&amp;' }
50
- specify { subject.escape('>').should eql '&gt;' }
52
+ specify { expect(subject.escape('<')).to eql '&lt;' }
53
+ specify { expect(subject.escape('&')).to eql '&amp;' }
54
+ specify { expect(subject.escape('>')).to eql '&gt;' }
51
55
 
52
- specify { subject.mount_table([]).should be_blank }
53
- specify { subject.mount_table([['h1', 'h2', 'h3']], :class => 'table').should be_blank }
56
+ specify { expect(subject.mount_table([])).to be_blank }
57
+ specify { expect(subject.mount_table([['h1', 'h2', 'h3']], :class => 'table')).to be_blank }
54
58
 
55
59
  specify {
56
60
  tab = <<-TABLE
@@ -60,7 +64,7 @@ describe Footnotes::Notes::AbstractNote do
60
64
  </table>
61
65
  TABLE
62
66
 
63
- subject.mount_table([['h1'],['r1c1']], :class => 'table').should eql tab
67
+ expect(subject.mount_table([['h1'],['r1c1']], :class => 'table')).to eql tab
64
68
  }
65
69
 
66
70
  specify {
@@ -70,7 +74,7 @@ describe Footnotes::Notes::AbstractNote do
70
74
  <tbody><tr><td>r1c1</td><td>r1c2</td><td>r1c3</td></tr></tbody>
71
75
  </table>
72
76
  TABLE
73
- subject.mount_table([['h1', 'h2', 'h3'],['r1c1', 'r1c2', 'r1c3']]).should eql tab
77
+ expect(subject.mount_table([['h1', 'h2', 'h3'],['r1c1', 'r1c2', 'r1c3']])).to eql tab
74
78
  }
75
79
 
76
80
  specify {