rails-footnotes 3.7.9 → 4.0.0

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 (44) hide show
  1. data/.gitignore +4 -3
  2. data/.travis.yml +10 -6
  3. data/CHANGELOG +13 -0
  4. data/README.rdoc +33 -46
  5. data/Rakefile +2 -2
  6. data/gemfiles/Gemfile.rails-3.2.x +5 -0
  7. data/gemfiles/Gemfile.rails-4.0.x +6 -0
  8. data/gemfiles/Gemfile.rails-4.1.x +5 -0
  9. data/gemfiles/Gemfile.rails-edge +5 -0
  10. data/lib/generators/rails_footnotes/install_generator.rb +1 -4
  11. data/lib/generators/templates/rails_footnotes.rb +19 -3
  12. data/lib/rails-footnotes.rb +41 -13
  13. data/lib/rails-footnotes/extension.rb +22 -3
  14. data/lib/rails-footnotes/filter.rb +9 -18
  15. data/lib/rails-footnotes/notes/log_note.rb +18 -25
  16. data/lib/rails-footnotes/notes/log_note/note_logger.rb +59 -0
  17. data/lib/rails-footnotes/notes/partials_note.rb +20 -38
  18. data/lib/rails-footnotes/notes/queries_note.rb +1 -1
  19. data/lib/rails-footnotes/notes/routes_note.rb +13 -14
  20. data/lib/rails-footnotes/version.rb +1 -1
  21. data/rails-footnotes.gemspec +5 -6
  22. data/spec/abstract_note_spec.rb +5 -0
  23. data/spec/controllers/footnotes_controller_spec.rb +113 -0
  24. data/spec/controllers/log_note_controller_spec.rb +45 -0
  25. data/spec/controllers/partials_note_controller_spec.rb +29 -0
  26. data/spec/fixtures/html_download.html +5 -0
  27. data/spec/footnotes_spec.rb +5 -8
  28. data/spec/notes/assigns_note_spec.rb +1 -1
  29. data/spec/notes/controller_note_spec.rb +1 -1
  30. data/spec/notes/files_note_spec.rb +1 -1
  31. data/spec/notes/javascripts_note_spec.rb +1 -1
  32. data/spec/notes/stylesheets_note_spec.rb +1 -1
  33. data/spec/spec_helper.rb +23 -12
  34. data/spec/views/partials/_foo.html.erb +1 -0
  35. data/spec/views/partials/index.html.erb +1 -0
  36. metadata +31 -22
  37. data/.watchr.example +0 -13
  38. data/lib/generators/templates/rails_footnotes +0 -3
  39. data/lib/rails-footnotes/after_filter.rb +0 -10
  40. data/lib/rails-footnotes/backtracer.rb +0 -32
  41. data/lib/rails-footnotes/before_filter.rb +0 -9
  42. data/lib/rails-footnotes/footnotes.rb +0 -7
  43. data/lib/rails-footnotes/notes/general_note.rb +0 -17
  44. data/spec/notes/partials_notes_spec.rb +0 -9
@@ -1,14 +1,21 @@
1
1
  module Footnotes
2
2
  module Notes
3
3
  class LogNote < AbstractNote
4
- @@log = []
5
4
 
6
- def self.log(message)
7
- @@log << message
8
- end
5
+ autoload :NoteLogger, 'rails-footnotes/notes/log_note/note_logger'
6
+
7
+ cattr_accessor :logs
8
+ cattr_accessor :original_logger
9
9
 
10
- def initialize(controller)
11
- @controller = controller
10
+ def self.start!(controller)
11
+ self.logs = []
12
+ self.original_logger = Rails.logger
13
+ note_logger = NoteLogger.new(self.logs)
14
+ note_logger.level = self.original_logger.level
15
+ note_logger.formatter = self.original_logger.kind_of?(Logger) ? self.original_logger.formatter : Logger::SimpleFormatter.new
16
+ # Rails 3 don't have ActiveSupport::Logger#broadcast so we backported it
17
+ extend_module = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger.broadcast(note_logger) : NoteLogger.broadcast(note_logger)
18
+ Rails.logger = self.original_logger.dup.extend(extend_module)
12
19
  end
13
20
 
14
21
  def title
@@ -16,30 +23,16 @@ module Footnotes
16
23
  end
17
24
 
18
25
  def content
19
- escape(log.gsub(/\e\[.+?m/, '')).gsub("\n", '<br />')
26
+ result = escape(log.gsub(/\e\[.+?m/, '')).gsub("\n", '<br />')
27
+ # Restore formatter
28
+ Rails.logger = self.class.original_logger
29
+ result
20
30
  end
21
31
 
22
32
  def log
23
- unless @log
24
- @log = @@log.join('')
25
- @@log = []
26
- if rindex = @log.rindex('Processing '+@controller.class.name+'#'+@controller.action_name)
27
- @log = @log[rindex..-1]
28
- end
29
- end
30
- @log
33
+ self.class.logs.join("\n")
31
34
  end
32
35
 
33
- module LoggingExtensions
34
- def add(*args, &block)
35
- logged_message = super
36
- Footnotes::Notes::LogNote.log(logged_message)
37
- logged_message
38
- end
39
- end
40
-
41
- Rails.logger.extend LoggingExtensions
42
36
  end
43
37
  end
44
38
  end
45
-
@@ -0,0 +1,59 @@
1
+ module Footnotes
2
+ module Notes
3
+ class LogNote
4
+ class NoteLogger < Logger
5
+
6
+ def initialize(logs)
7
+ @logs = logs
8
+ end
9
+
10
+ def add(severity, message = nil, progname = nil, &block)
11
+ severity ||= UNKNOWN
12
+ if severity < level
13
+ return true
14
+ end
15
+ formatter = @formatter || Logger::Formatter.new
16
+ @logs << formatter.call(format_severity(severity), Time.now, message, progname)
17
+ end
18
+
19
+ ## Backport from rails 4 for handling logging broadcast, should be removed when rails 3 is deprecated :
20
+
21
+ # Broadcasts logs to multiple loggers.
22
+ def self.broadcast(logger) # :nodoc:
23
+ Module.new do
24
+ define_method(:add) do |*args, &block|
25
+ logger.add(*args, &block)
26
+ super(*args, &block)
27
+ end
28
+
29
+ define_method(:<<) do |x|
30
+ logger << x
31
+ super(x)
32
+ end
33
+
34
+ define_method(:close) do
35
+ logger.close
36
+ super()
37
+ end
38
+
39
+ define_method(:progname=) do |name|
40
+ logger.progname = name
41
+ super(name)
42
+ end
43
+
44
+ define_method(:formatter=) do |formatter|
45
+ logger.formatter = formatter
46
+ super(formatter)
47
+ end
48
+
49
+ define_method(:level=) do |level|
50
+ logger.level = level
51
+ super(level)
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,56 +1,38 @@
1
- require 'rails-footnotes/notes/log_note'
2
-
3
1
  module Footnotes
4
2
  module Notes
5
- class PartialsNote < LogNote
3
+ class PartialsNote < AbstractNote
4
+
5
+ cattr_accessor :partials
6
+
7
+ def self.start!(controller)
8
+ self.partials = []
9
+ @subscriber ||= ActiveSupport::Notifications.subscribe('render_partial.action_view') do |*args|
10
+ event = ActiveSupport::Notifications::Event.new *args
11
+ self.partials << {:file => event.payload[:identifier], :duration => event.duration}
12
+ end
13
+ end
14
+
6
15
  def initialize(controller)
7
- super
8
16
  @controller = controller
9
17
  end
18
+
10
19
  def row
11
20
  :edit
12
21
  end
22
+
13
23
  def title
14
24
  "Partials (#{partials.size})"
15
25
  end
26
+
16
27
  def content
17
- rows = partials.map do |filename|
18
- href = Footnotes::Filter.prefix(filename,1,1)
19
- shortened_name=filename.gsub(File.join(Rails.root,"app/views/"),"")
20
- [%{<a href="#{href}">#{shortened_name}</a>},"#{@partial_times[filename].sum}ms",@partial_counts[filename]]
28
+ rows = self.class.partials.map do |partial|
29
+ href = Footnotes::Filter.prefix(partial[:file],1,1)
30
+ shortened_name = partial[:file].gsub(File.join(Rails.root,"app/views/"),"")
31
+ [%{<a href="#{href}">#{shortened_name}</a>},"#{partial[:duration]}ms"]
21
32
  end
22
- mount_table(rows.unshift(%w(Partial Time Count)), :summary => "Partials for #{title}")
33
+ mount_table(rows.unshift(%w(Partial Time)), :summary => "Partials for #{title}")
23
34
  end
24
35
 
25
- protected
26
- #Generate a list of partials that were rendered, also build up render times and counts.
27
- #This is memoized so we can use its information in the title easily.
28
- def partials
29
- @partials ||= begin
30
- partials = []
31
- @partial_counts = {}
32
- @partial_times = {}
33
- log_lines = log
34
- log_lines.split("\n").each do |line|
35
- if line =~ /Rendered (\S*) \(([\d\.]+)\S*?\)/
36
- partial = $1
37
- @controller.view_paths.each do |view_path|
38
- path = File.join(view_path.to_s, "#{partial}*")
39
- files = Dir.glob(path)
40
- for file in files
41
- #TODO figure out what format got rendered if theres multiple
42
- @partial_times[file] ||= []
43
- @partial_times[file] << $2.to_f
44
- @partial_counts[file] ||= 0
45
- @partial_counts[file] += 1
46
- partials << file unless partials.include?(file)
47
- end
48
- end
49
- end
50
- end
51
- partials.reverse
52
- end
53
- end
54
36
  end
55
37
  end
56
38
  end
@@ -6,7 +6,7 @@ module Footnotes
6
6
  @@alert_sql_number = 8
7
7
  @@query_subscriber = nil
8
8
  @@orm = [:active_record, :data_mapper]
9
- @@ignored_regexps = [%r{(pg_table|pg_attribute|show\stables|pragma|sqlite_master)}i]
9
+ @@ignored_regexps = [%r{(pg_table|pg_attribute|pg_namespace|show\stables|pragma|sqlite_master)}i]
10
10
 
11
11
  def self.start!(controller)
12
12
  self.query_subscriber.reset!
@@ -24,17 +24,8 @@ module Footnotes
24
24
  name = i ? routes_with_name[i-1].to_s : ''
25
25
 
26
26
  # Catch segments requirements
27
- req = {}
28
- if Rails.version < '3.0'
29
- route.segments.each do |segment|
30
- next unless segment.is_a?(ActionController::Routing::DynamicSegment) && segment.regexp
31
- req[segment.key.to_sym] = segment.regexp
32
- end
33
- [escape(name), route.segments.join, route.requirements.reject{|key,value| key == :controller}.inspect, req.inspect]
34
- else
35
- req = route.conditions
36
- [escape(name), route.conditions.keys.join, route.requirements.reject{|key,value| key == :controller}.inspect, req.inspect]
37
- end
27
+ req = route.conditions
28
+ [escape(name), route.conditions.keys.join, route.requirements.reject{|key,value| key == :controller}.inspect, req.inspect]
38
29
  end
39
30
  end
40
31
  end
@@ -42,13 +33,21 @@ module Footnotes
42
33
 
43
34
  module Extensions
44
35
  module Routes
36
+
37
+ def __hash_diff(hash_self, other)
38
+ # ActiveSupport::Deprecation.warn "Hash#diff is no longer used inside of Rails,
39
+ # and is being deprecated with no replacement. If you're using it to compare hashes for the purpose of testing, please use MiniTest's diff instead."
40
+ hash_self.dup.delete_if { |k, v| other[k] == v }.merge!(other.dup.delete_if { |k, v| hash_self.has_key?(k) })
41
+ end
42
+
45
43
  # Filter routes according to the filter sent
46
44
  #
47
45
  def filtered_routes(filter = {})
48
46
  return [] unless filter.is_a?(Hash)
49
47
  return routes.reject do |r|
50
- filter_diff = filter.diff(r.requirements)
51
- route_diff = r.requirements.diff(filter)
48
+ filter_diff = __hash_diff(filter, r.requirements)
49
+ route_diff = __hash_diff(r.requirements, filter)
50
+
52
51
  (filter_diff == filter) || (filter_diff != route_diff)
53
52
  end
54
53
  end
@@ -57,5 +56,5 @@ module Footnotes
57
56
  end
58
57
 
59
58
  if Footnotes::Notes::RoutesNote.included?
60
- ActionController::Routing::RouteSet.send :include, Footnotes::Extensions::Routes
59
+ ActionDispatch::Routing::RouteSet.send :include, Footnotes::Extensions::Routes
61
60
  end
@@ -1,3 +1,3 @@
1
1
  module Footnotes
2
- VERSION = "3.7.9"
2
+ VERSION = "4.0.0"
3
3
  end
@@ -6,7 +6,7 @@ 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"]
9
+ s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson", "Adrien Siami"]
10
10
  s.email = ["romanvbabenko@gmail.com"]
11
11
  s.homepage = "http://github.com/josevalim/rails-footnotes"
12
12
  s.summary = %q{Every Rails page has footnotes that gives information about your application and links back to your editor.}
@@ -14,14 +14,13 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "rails-footnotes"
16
16
 
17
- s.add_dependency "rails", ">= 3.0.0"
17
+ s.add_dependency "rails", ">= 3.2"
18
18
 
19
- s.add_development_dependency "rails", ">= 3.0.0"
20
- s.add_development_dependency "rspec", "~> 2.9.0"
19
+ s.add_development_dependency "rspec-rails"
20
+ s.add_development_dependency "capybara"
21
21
 
22
22
  s.files = `git ls-files`.split("\n")
23
23
  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) }
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
25
25
  s.require_paths = ["lib"]
26
26
  end
27
-
@@ -3,9 +3,14 @@ require "spec_helper"
3
3
  describe Footnotes::Notes::AbstractNote do
4
4
  before do
5
5
  @note = Footnotes::Notes::AbstractNote.new
6
+ @notes = Footnotes::Filter.notes
6
7
  Footnotes::Filter.notes = [:abstract]
7
8
  end
8
9
 
10
+ after do
11
+ Footnotes::Filter.notes = @notes
12
+ end
13
+
9
14
  it {described_class.should respond_to :start!}
10
15
  it {described_class.should respond_to :close!}
11
16
  it {described_class.should respond_to :title}
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ class FootnotesController < ActionController::Base
4
+
5
+ def foo
6
+ render :text => HTML_DOCUMENT, :content_type => 'text/html'
7
+ end
8
+
9
+ def foo_holder
10
+ render :text => '<html><body><div id="footnotes_holder"></div></body></html>'
11
+ end
12
+
13
+ def foo_js
14
+ render :text => '<script></script>', :content_type => 'text/javascript'
15
+ end
16
+
17
+ def foo_download
18
+ send_file Rails.root.join('spec', 'fixtures', 'html_download.html'), :disposition => 'attachment'
19
+ end
20
+
21
+ end
22
+
23
+ describe FootnotesController do
24
+
25
+ def page
26
+ Capybara::Node::Simple.new(response.body)
27
+ end
28
+
29
+ shared_examples 'has_footnotes' do
30
+ it 'includes footnotes' do
31
+ get :foo
32
+ response.body.should have_selector('#footnotes_debug')
33
+ end
34
+ end
35
+
36
+ shared_examples 'has_no_footnotes' do
37
+ it 'does not include footnotes' do
38
+ response.body.should_not have_selector('#footnotes_debug')
39
+ end
40
+ end
41
+
42
+ it 'does not alter the page by default' do
43
+ get :foo
44
+ response.body.should == HTML_DOCUMENT
45
+ end
46
+
47
+ context 'with footnotes' do
48
+
49
+ before :all do
50
+ Footnotes.enabled = true
51
+ end
52
+
53
+ after :all do
54
+ Footnotes.enabled = false
55
+ end
56
+
57
+ describe 'by default' do
58
+ include_context 'has_footnotes'
59
+
60
+ before do
61
+ get :foo
62
+ end
63
+
64
+ it 'includes footnotes in the last div in body' do
65
+ all('body > :last-child')[0][:id].should == 'footnotes_debug'
66
+ end
67
+
68
+ it 'includes footnotes in the footnoted_holder div if present' do
69
+ get :foo_holder
70
+ response.body.should have_selector('#footnotes_holder > #footnotes_debug')
71
+ end
72
+
73
+ it 'does not alter a html file download' do
74
+ get :foo_download
75
+ response.body.should == File.open(Rails.root.join('spec', 'fixtures', 'html_download.html')).read
76
+ end
77
+ end
78
+
79
+ describe 'when request is xhr' do
80
+ include_context 'has_no_footnotes'
81
+ before do
82
+ xhr :get, :foo
83
+ end
84
+ end
85
+
86
+ describe 'when content type is javascript' do
87
+ include_context 'has_no_footnotes'
88
+ before do
89
+ get :foo_js
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+
98
+ HTML_DOCUMENT = <<EOF
99
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
100
+ <html>
101
+ <head>
102
+ <title>HTML to XHTML Example: HTML page</title>
103
+ <link rel="Stylesheet" href="htmltohxhtml.css" type="text/css" media="screen">
104
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
105
+ </head>
106
+ <body>
107
+ <p>This is the HTML page. It works and is encoded just like any HTML page you
108
+ have previously done. View <a href="htmltoxhtml2.htm">the XHTML version</a> of
109
+ this page to view the difference between HTML and XHTML.</p>
110
+ <p>You will be glad to know that no changes need to be made to any of your CSS files.</p>
111
+ </body>
112
+ </html>
113
+ EOF
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe 'log note' do
5
+
6
+ class ApplicationController < ActionController::Base
7
+ end
8
+
9
+ controller do
10
+ def index
11
+ Rails.logger.error 'foo'
12
+ Rails.logger.warn 'bar'
13
+ render :text => '<html><head></head><body></body></html>', :content_type => 'text/html'
14
+ end
15
+ end
16
+
17
+ def page
18
+ Capybara::Node::Simple.new(response.body)
19
+ end
20
+
21
+ before :all do
22
+ Footnotes.enabled = true
23
+ end
24
+
25
+ after :all do
26
+ Footnotes.enabled = false
27
+ end
28
+
29
+ before do
30
+ @original_logger = Rails.logger
31
+ Rails.logger = Logger.new(StringIO.new)
32
+ end
33
+
34
+ after do
35
+ Rails.logger = @original_logger
36
+ end
37
+
38
+ it 'Includes the log in the response' do
39
+ get :index
40
+ log_debug = first('fieldset#log_debug_info div', :visible => false)
41
+ log_debug.should have_content('foo')
42
+ log_debug.should have_content('bar')
43
+ end
44
+
45
+ end