merb_footnotes 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +14 -0
- data/Rakefile +51 -0
- data/lib/merb-plugins-footnotes.rb +79 -0
- data/lib/merb_footnotes/filter.rb +258 -0
- data/lib/merb_footnotes/formatter.rb +63 -0
- data/lib/merb_footnotes/instrumentation.rb +134 -0
- data/lib/merb_footnotes/notes/abstract_note.rb +166 -0
- data/lib/merb_footnotes/notes/controller_note.rb +57 -0
- data/lib/merb_footnotes/notes/cookies_note.rb +19 -0
- data/lib/merb_footnotes/notes/env_note.rb +19 -0
- data/lib/merb_footnotes/notes/files_note.rb +40 -0
- data/lib/merb_footnotes/notes/filters_note.rb +46 -0
- data/lib/merb_footnotes/notes/javascripts_note.rb +16 -0
- data/lib/merb_footnotes/notes/layout_note.rb +33 -0
- data/lib/merb_footnotes/notes/log_note.rb +38 -0
- data/lib/merb_footnotes/notes/params_note.rb +19 -0
- data/lib/merb_footnotes/notes/partials_note.rb +59 -0
- data/lib/merb_footnotes/notes/queries_note.rb +139 -0
- data/lib/merb_footnotes/notes/routes_note.rb +35 -0
- data/lib/merb_footnotes/notes/session_note.rb +19 -0
- data/lib/merb_footnotes/notes/stylesheets_note.rb +16 -0
- data/lib/merb_footnotes/notes/view_note.rb +37 -0
- data/spec/merb_footnotes_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +89 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/files_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class JavascriptsNote < FilesNote
|
6
|
+
def title
|
7
|
+
"Javascripts (#{@files.length})"
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def scan_text(text)
|
12
|
+
text.scan(/<script[^>]+src\s*=\s*['"]([^>?'"]+\.js)/im).flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# LAYOUT NOTE
|
2
|
+
# Todo: make this note display the currently displayed layout
|
3
|
+
|
4
|
+
require "#{File.dirname(__FILE__)}/view_note"
|
5
|
+
|
6
|
+
module MerbFootnotes
|
7
|
+
module Notes
|
8
|
+
class LayoutNote < AbstractNote
|
9
|
+
def initialize(controller)
|
10
|
+
@controller = controller
|
11
|
+
@layout_path = find_layout
|
12
|
+
end
|
13
|
+
|
14
|
+
def row
|
15
|
+
:edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def link
|
19
|
+
escape(Merb::Plugins.config[:merb_footnotes][:prefix] + @layout_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
prefix? and !@layout_path.blank?
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def find_layout
|
28
|
+
# TODO: find the real rendered layout
|
29
|
+
"#{Merb.root}/app/views/layout/application.html.#{Merb.template_engine}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class LogNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
end
|
9
|
+
|
10
|
+
def content
|
11
|
+
""
|
12
|
+
# TODO
|
13
|
+
# escape(log_tail).gsub("\n","<br />")
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def log_tail
|
18
|
+
filename = if Merb.logger.instance_variable_get('@log')
|
19
|
+
Merb.logger.instance_variable_get('@log').path
|
20
|
+
else
|
21
|
+
Merb.logger.instance_variable_get('@logdev').filename
|
22
|
+
end
|
23
|
+
file_string = File.open(filename).read.to_s
|
24
|
+
|
25
|
+
# We try to select the specified action from the log
|
26
|
+
# If we can't find it, we get the last 100 lines
|
27
|
+
#
|
28
|
+
if rindex = file_string.rindex('Processing '+@controller.controller_class_name+'#'+@controller.action_name)
|
29
|
+
file_string[rindex..-1].gsub(/\e\[.+?m/, '')
|
30
|
+
else
|
31
|
+
lines = file_string.split("\n")
|
32
|
+
index = [lines.size-100,0].max
|
33
|
+
lines[index..-1].join("\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class ParamsNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@params = controller.params
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
"Params (#{@params.length})"
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
escape(@params.inspect)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
# View Note
|
4
|
+
# this note should give you an easy linkback to the currently render view
|
5
|
+
# TODO: include all rendered partials by wrapping the partial call
|
6
|
+
module MerbFootnotes
|
7
|
+
module Notes
|
8
|
+
class PartialsNote < AbstractNote
|
9
|
+
def initialize(controller)
|
10
|
+
@controller = controller
|
11
|
+
@partials = format_partials(@controller.footnotes[:partials])
|
12
|
+
end
|
13
|
+
|
14
|
+
def row
|
15
|
+
:edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def title
|
19
|
+
"Partials (#{@partials.size})"
|
20
|
+
end
|
21
|
+
|
22
|
+
# def link
|
23
|
+
# escape(Merb::Plugins.config[:merb_footnotes][:prefix] + filename)
|
24
|
+
# end
|
25
|
+
|
26
|
+
def content
|
27
|
+
mount_table(@partials.unshift([:partial, :arguments]))
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid?
|
31
|
+
prefix?
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def format_partials(partials)
|
36
|
+
display_list = []
|
37
|
+
partials.each do |r|
|
38
|
+
action = r.first
|
39
|
+
opts = r.last
|
40
|
+
|
41
|
+
action = "<a href='#{get_path_for_partial(action)}'>#{action}</a>"
|
42
|
+
display_list << [action.to_s, opts.inspect]
|
43
|
+
end
|
44
|
+
display_list
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_path_for_partial(template)
|
48
|
+
template = template.to_s
|
49
|
+
if template =~ %r{^/}
|
50
|
+
template_path = File.dirname(template) / "_#{File.basename(template)}"
|
51
|
+
else
|
52
|
+
kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : @controller.controller_name
|
53
|
+
template_path = "#{kontroller}/_#{File.basename(template)}"
|
54
|
+
end
|
55
|
+
"#{Merb::Plugins.config[:merb_footnotes][:prefix]}/#{Merb.root}/app/views/#{template_path}.html.#{Merb.template_engine}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# TODO: fix instrumentation in order to populate the MerbFootNotes::Notes::QueriesNote.sql accessor
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
4
|
+
|
5
|
+
module MerbFootnotes
|
6
|
+
module Notes
|
7
|
+
class QueriesNote < AbstractNote
|
8
|
+
@@sql = []
|
9
|
+
|
10
|
+
def self.sql
|
11
|
+
@@sql
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.start!(controller)
|
15
|
+
@@sql = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.to_sym
|
19
|
+
:queries
|
20
|
+
end
|
21
|
+
|
22
|
+
def title
|
23
|
+
"Queries (#{@@sql.length})"
|
24
|
+
end
|
25
|
+
|
26
|
+
def stylesheet
|
27
|
+
%{
|
28
|
+
#queries_debug_info table td, #queries_debug_info table th{border:1px solid #A00; padding:0 3px; text-align:center;}
|
29
|
+
#queries_debug_info table thead, #queries_debug_info table tbody {color:#A00;}
|
30
|
+
#queries_debug_info p {background-color:#F3F3FF; border:1px solid #CCC; margin:12px; padding:4px 6px;}
|
31
|
+
#queries_debug_info a:hover {text-decoration:underline;}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def javascript
|
36
|
+
%{
|
37
|
+
function queries_toogle(type, id){
|
38
|
+
s = document.getElementById('q'+type+'_'+id).style
|
39
|
+
s.display = (s.display != 'block') ? 'block' : 'none'
|
40
|
+
location.href = '#qtitle_'+id
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def content
|
46
|
+
html = ''
|
47
|
+
|
48
|
+
@@sql.each_with_index do |item, i|
|
49
|
+
sql_links = []
|
50
|
+
sql_links << "<a href=\"#\" style=\"color:#A00;\" onclick=\"queries_toogle('table',#{i});return false\">explain</a>" if item.explain
|
51
|
+
sql_links << "<a href=\"#\" style=\"color:#00A;\" onclick=\"queries_toogle('trace',#{i});return false\">trace</a>" if item.trace
|
52
|
+
|
53
|
+
html << %{
|
54
|
+
<b id="qtitle_#{i}">#{escape(item.type.to_s.upcase)}</b> (#{sql_links.join(' | ')})<br />
|
55
|
+
#{print_name_and_time(item.name, item.time)}<br />
|
56
|
+
#{print_query(item.query)}<br />
|
57
|
+
#{print_explain(i, item.explain) if item.explain}
|
58
|
+
<p id="qtrace_#{i}" style="display:none;">#{parse_trace(item.trace) if item.trace}</p><br />
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# return html
|
63
|
+
|
64
|
+
# TODO: remove this
|
65
|
+
return "NOT WORKING"
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
def parse_explain(results)
|
71
|
+
table = []
|
72
|
+
table << results.fetch_fields.map{|f| f.name}
|
73
|
+
results.each{|row| table << row}
|
74
|
+
table
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_trace(trace)
|
78
|
+
trace.map do |t|
|
79
|
+
s = t.split(':')
|
80
|
+
"<a href=\"#{escape("#{Merb::Plugins.config[:merb_footnotes][:prefix]}#{Merb.root}/#{s[0]}&line=#{s[1].to_i}")}\">#{escape(t)}</a><br />"
|
81
|
+
end.join
|
82
|
+
end
|
83
|
+
|
84
|
+
def print_name_and_time(name, time)
|
85
|
+
"#{escape(name || 'SQL')} (#{sprintf('%f', time)}s)"
|
86
|
+
end
|
87
|
+
|
88
|
+
def print_query(query)
|
89
|
+
escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
|
90
|
+
end
|
91
|
+
|
92
|
+
def print_explain(i, explain)
|
93
|
+
mount_table(parse_explain(explain), :id => "qtable_#{i}", :style => 'margin:10px;display:none;')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
module Extensions
|
99
|
+
class Sql
|
100
|
+
attr_accessor :type, :name, :time, :query, :explain, :trace
|
101
|
+
|
102
|
+
def initialize(type, name, time, query, explain)
|
103
|
+
@type = type
|
104
|
+
@name = name
|
105
|
+
@time = time
|
106
|
+
@query = query
|
107
|
+
@explain = explain
|
108
|
+
|
109
|
+
# Strip, select those ones from app and reject first two, because they are from the plugin
|
110
|
+
@trace = Kernel.caller.collect{|c| c.strip}.select{|i| i.gsub!(/^#{Merb.root}\//im, '') }[2..-1]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module AbstractAdapter
|
115
|
+
def log_silence
|
116
|
+
result = nil
|
117
|
+
if @logger
|
118
|
+
@logger.silence do
|
119
|
+
result = yield
|
120
|
+
end
|
121
|
+
else
|
122
|
+
result = yield
|
123
|
+
end
|
124
|
+
result
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# NOT WORKING
|
131
|
+
|
132
|
+
# if MerbFootnotes::Notes::QueriesNote.included?
|
133
|
+
# ActiveRecord::ConnectionAdapters::AbstractAdapter.__send__ :include, MerbFootnotes::Extensions::AbstractAdapter
|
134
|
+
# ActiveRecord::ConnectionAdapters.local_constants.each do |adapter|
|
135
|
+
# next unless adapter =~ /.*[^Abstract]Adapter$/
|
136
|
+
# next if adapter =~ /SQLite.Adapter$/
|
137
|
+
# eval("ActiveRecord::ConnectionAdapters::#{adapter}").__send__ :include, MerbFootnotes::Extensions::QueryAnalyzer
|
138
|
+
# end
|
139
|
+
# end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class RoutesNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
@parsed_routes = parse_routes || []
|
9
|
+
end
|
10
|
+
|
11
|
+
def legend
|
12
|
+
"Routes for #{@controller.class.to_s}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def content
|
16
|
+
mount_table(@parsed_routes.to_a.unshift([:name, :path, :params]))
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def parse_routes
|
21
|
+
routes_with_name = Merb::Router.named_routes.to_a
|
22
|
+
|
23
|
+
return Merb::Router.routes.collect do |route|
|
24
|
+
if route.params[:controller].to_s.include?(@controller.class.to_s.downcase)
|
25
|
+
[
|
26
|
+
escape(route.name.to_s),
|
27
|
+
route.segments.to_a.join,
|
28
|
+
route.params.reject{|key, value| key == :controller}.inspect.gsub('\"', '')
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class SessionNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@session = controller.session
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
"Session (#{@session.size})"
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
escape(@session.inspect)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/files_note"
|
2
|
+
|
3
|
+
module MerbFootnotes
|
4
|
+
module Notes
|
5
|
+
class StylesheetsNote < FilesNote
|
6
|
+
def title
|
7
|
+
"Stylesheets (#{@files.length})"
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def scan_text(text)
|
12
|
+
text.scan(/<link[^>]+href\s*=\s*['"]([^>?'"]+\.css)/im).flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
# View Note
|
4
|
+
# this note should give you an easy linkback to the currently render view
|
5
|
+
# TODO: include all rendered partials by wrapping the partial call
|
6
|
+
module MerbFootnotes
|
7
|
+
module Notes
|
8
|
+
class ViewNote < AbstractNote
|
9
|
+
def initialize(controller)
|
10
|
+
@controller = controller
|
11
|
+
@filename = get_filename
|
12
|
+
end
|
13
|
+
|
14
|
+
def row
|
15
|
+
:edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def title
|
19
|
+
"View"
|
20
|
+
end
|
21
|
+
|
22
|
+
def link
|
23
|
+
escape(Merb::Plugins.config[:merb_footnotes][:prefix] + @filename)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
prefix?
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
def get_filename
|
33
|
+
"#{Merb.root}/app/views/#{@controller.controller_name}/#{@controller.params[:action]}.html.#{Merb.template_engine}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: merb_footnotes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jacques Crocker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-11-22 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: merb
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.0"
|
24
|
+
version:
|
25
|
+
description: Provides an extensible footnotes debugging bar to Merb development mode
|
26
|
+
email: merbjedi@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- LICENSE
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- lib/merb-plugins-footnotes.rb
|
39
|
+
- lib/merb_footnotes
|
40
|
+
- lib/merb_footnotes/filter.rb
|
41
|
+
- lib/merb_footnotes/formatter.rb
|
42
|
+
- lib/merb_footnotes/instrumentation.rb
|
43
|
+
- lib/merb_footnotes/notes
|
44
|
+
- lib/merb_footnotes/notes/abstract_note.rb
|
45
|
+
- lib/merb_footnotes/notes/controller_note.rb
|
46
|
+
- lib/merb_footnotes/notes/cookies_note.rb
|
47
|
+
- lib/merb_footnotes/notes/env_note.rb
|
48
|
+
- lib/merb_footnotes/notes/files_note.rb
|
49
|
+
- lib/merb_footnotes/notes/filters_note.rb
|
50
|
+
- lib/merb_footnotes/notes/javascripts_note.rb
|
51
|
+
- lib/merb_footnotes/notes/layout_note.rb
|
52
|
+
- lib/merb_footnotes/notes/log_note.rb
|
53
|
+
- lib/merb_footnotes/notes/params_note.rb
|
54
|
+
- lib/merb_footnotes/notes/partials_note.rb
|
55
|
+
- lib/merb_footnotes/notes/queries_note.rb
|
56
|
+
- lib/merb_footnotes/notes/routes_note.rb
|
57
|
+
- lib/merb_footnotes/notes/session_note.rb
|
58
|
+
- lib/merb_footnotes/notes/stylesheets_note.rb
|
59
|
+
- lib/merb_footnotes/notes/view_note.rb
|
60
|
+
- spec/merb_footnotes_spec.rb
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
has_rdoc: true
|
63
|
+
homepage: http://merbjedi.com/
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project: merb
|
84
|
+
rubygems_version: 1.3.1
|
85
|
+
signing_key:
|
86
|
+
specification_version: 2
|
87
|
+
summary: Provides an extensible footnotes debugging bar to Merb development mode
|
88
|
+
test_files: []
|
89
|
+
|