rails_info 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -61,3 +61,7 @@ code {
61
61
  //
62
62
  // Example:
63
63
  // @linkColor: #ff0000;
64
+
65
+ #log_rails_root {
66
+ width: auto;
67
+ }
@@ -13,7 +13,7 @@ class RailsInfo::Logs::Server::ActionPresenter < ::RailsInfo::Presenter
13
13
  html += content_tag(:div, class: 'tabs', id: "tabs-#{@index}") do
14
14
  raw(navigation) + raw(body)
15
15
  end
16
-
16
+
17
17
  html
18
18
  end
19
19
 
@@ -24,7 +24,7 @@ class RailsInfo::Logs::Server::ActionPresenter < ::RailsInfo::Presenter
24
24
  @tab_index = 0
25
25
 
26
26
  elements = ''
27
-
27
+
28
28
  @tabs_data.keys.select{|tab_key| tab_key.present?}.each do |tab_key|
29
29
  elements += content_tag :li, link_to(tab_key, "#tabs-#{@index}-#{@tab_index}")
30
30
  @tab_index += 1
@@ -46,9 +46,17 @@ class RailsInfo::Logs::Server::ActionPresenter < ::RailsInfo::Presenter
46
46
 
47
47
  def tab(tab_key)
48
48
  @content = @tabs_data[tab_key]
49
-
49
+
50
50
  content_tag :div, class: 'tabs', id: "tabs-#{@index}-#{@tab_index}" do
51
- raw @content.is_a?(Hash) ? sub_tabs : sub_content_tab
51
+ html = if tab_key == 'Request'
52
+ raw render partial: 'rails_info/logs/server/request', locals: { content: @content }
53
+ else
54
+ raw @content.is_a?(Hash) ? sub_tabs : sub_content_tab
55
+ end
56
+
57
+ @tab_index += 1
58
+
59
+ html
52
60
  end
53
61
  end
54
62
 
@@ -65,12 +73,11 @@ class RailsInfo::Logs::Server::ActionPresenter < ::RailsInfo::Presenter
65
73
  def sub_content_tab
66
74
  content_tag :div, style: 'max-height:400px; width:100%; overflow: auto' do
67
75
  if @content.is_a?(Array)
68
- @content.map!{|c| CGI.escapeHTML(c) }.join('<br/><br/>')
76
+ @content.map!{|c| CGI.escapeHTML(c) }
77
+ @content = @content.join('<br/><br/>')
69
78
  else
70
79
  @content = CGI.escapeHTML(@content)
71
80
  end
72
-
73
- @tab_index += 1
74
81
 
75
82
  raw @content
76
83
  end
@@ -99,7 +106,7 @@ class RailsInfo::Logs::Server::ActionPresenter < ::RailsInfo::Presenter
99
106
 
100
107
  html += content_tag :div, class: 'tabs', id: "tabs-#{@index}-#{@tab_index}-#{sub_tab_index}" do
101
108
  sub_tab_index += 1
102
- @tab_index += 1
109
+
103
110
  raw render partial: 'rails_info/logs/server/table', locals: { sub_content: sub_content }
104
111
  end
105
112
  end
@@ -7,7 +7,7 @@ class RailsInfo::Logs::ServerPresenter < ::RailsInfo::Presenter
7
7
 
8
8
  def accordion
9
9
  @action_index = 0
10
-
10
+
11
11
  content_tag :div, id: 'actions', class: 'accordions' do
12
12
  html = ''
13
13
 
@@ -25,8 +25,7 @@ class RailsInfo::Logs::ServerPresenter < ::RailsInfo::Presenter
25
25
 
26
26
  def write_tabs
27
27
  content_tag :div, class: 'tabs', id: 'writes' do
28
- write_navigation
29
- write_body
28
+ raw(write_navigation) + raw(write_body)
30
29
  end
31
30
  end
32
31
 
@@ -34,24 +33,31 @@ class RailsInfo::Logs::ServerPresenter < ::RailsInfo::Presenter
34
33
  tab_index = 0
35
34
 
36
35
  content_tag :ul do
36
+ elements = ''
37
+
37
38
  @rails_info_log.writes.each do |table_name,data|
38
- li = content_tag :li, link_to(table_name, "writes-#{tab_index}")
39
+ elements += content_tag :li, link_to(table_name, "#writes-#{tab_index}")
39
40
 
40
41
  tab_index += 1
41
-
42
- li
43
42
  end
43
+
44
+ raw elements
44
45
  end
45
46
  end
46
47
 
47
48
  def write_body
48
49
  tab_index = 0
49
50
 
51
+ html = ''
52
+
50
53
  @rails_info_log.writes.each do |table_name,data|
51
- content_tag :div, class: 'tabs', id: "writes-#{tab_index}" do
52
- tab_index += 1
53
- render partial: 'table', locals: { sub_content: data }
54
+ html += content_tag :div, id: "writes-#{tab_index}" do
55
+ raw render partial: 'rails_info/logs/server/table', locals: { sub_content: data }
54
56
  end
57
+
58
+ tab_index += 1
55
59
  end
60
+
61
+ html
56
62
  end
57
63
  end
@@ -8,7 +8,7 @@ class RailsInfo::Logs::Test::RspecPresenter < ::RailsInfo::Presenter
8
8
  end
9
9
 
10
10
  def summary
11
- text = ["#{@rails_info_log.hash.keys.length} files"]
11
+ text = ["#{@rails_info_log.number_of_files} files"]
12
12
  text << @rails_info_log.summary unless @rails_info_log.summary.blank?
13
13
 
14
14
  content_tag :p, text.join(', ')
@@ -17,19 +17,23 @@ class RailsInfo::Logs::Test::RspecPresenter < ::RailsInfo::Presenter
17
17
  def accordion
18
18
  @index = 0
19
19
 
20
- content_tag :div, id: 'files', class: 'accordions' do
21
- html = ''
20
+ if @rails_info_log.hash.is_a?(Hash)
21
+ content_tag :div, id: 'files', class: 'accordions' do
22
+ html = ''
22
23
 
23
- @rails_info_log.hash.each do |file, examples|
24
- file_presenter = ::RailsInfo::Logs::Test::Rspec::FilePresenter.new(
25
- @subject, name: "#{file} (#{examples.length})",
26
- tabs_data: examples, index: @index, rails_root: @rails_info_log.rails_root
27
- )
28
- @index += 1
29
- html += raw file_presenter.tabs
24
+ @rails_info_log.hash.each do |file, examples|
25
+ file_presenter = ::RailsInfo::Logs::Test::Rspec::FilePresenter.new(
26
+ @subject, name: "#{file} (#{examples.length})",
27
+ tabs_data: examples, index: @index, rails_root: @rails_info_log.rails_root
28
+ )
29
+ @index += 1
30
+ html += raw file_presenter.tabs
31
+ end
32
+
33
+ raw html
30
34
  end
31
-
32
- raw html
33
- end
35
+ else
36
+ content_tag :pre, @rails_info_log.hash.join("\n")
37
+ end
34
38
  end
35
39
  end
@@ -2,6 +2,8 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Rails Info</title>
5
+ <meta charset='utf-8'>
6
+ <meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
5
7
  <%= stylesheet_link_tag rails_info_stylesheet, media: 'all' %>
6
8
  <%= javascript_include_tag 'rails_info/application' %>
7
9
  <%= csrf_meta_tags %>
@@ -0,0 +1,18 @@
1
+ <div>
2
+ <div>
3
+ <strong>Route:</strong> <%= content['Route']%> |
4
+ <strong>Format:</strong> <%= content['Format']%>
5
+ </div>
6
+ <% if content['Parameters'].present? %>
7
+ <hr/>
8
+ <fieldset>
9
+ <legend><strong>Parameters</strong>
10
+ <div>
11
+ <%= render partial: 'rails_info/logs/server/table', locals: {
12
+ sub_content: { 'columns' => content['Parameters'].keys, 'rows' => [content['Parameters']] }
13
+ }
14
+ %>
15
+ </div>
16
+ </fieldset>
17
+ <% end %>
18
+ </div>
@@ -1,7 +1,9 @@
1
1
  <div style="max-height:400px; width:100%; overflow: auto">
2
- <table>
2
+ <table class="table table-striped">
3
3
  <thead>
4
- <th><%= raw sub_content['columns'].uniq.join('</th><th>') %></th>
4
+ <tr>
5
+ <th><%= raw sub_content['columns'].uniq.join('</th><th>') %></th>
6
+ </tr>
5
7
  </thead>
6
8
  <tbody>
7
9
  <% sub_content['rows'].each do |row| %>
@@ -1,8 +1,3 @@
1
- <style type="text/css">
2
- .ui-widget {
3
- font-size: xx-small;
4
- }
5
- </style>
6
1
  <% form_tag rails_info_server_log_path do %>
7
2
  <%= check_box_tag 'debug' %> debug?
8
3
  <p>
@@ -15,5 +10,15 @@
15
10
  <%= submit_tag 'submit' %>
16
11
  </p>
17
12
  <% end %>
13
+ <ul class="nav nav-tabs nav-stacked">
14
+ <li><a name="top" href="#">1 ) Actions</a></li>
15
+ <li><a href="#writes">2 ) Writes</a></li>
16
+ </ul>
17
+ <hr/>
18
+ <h3><a href="#top">1 ) Actions</a></h3>
19
+ <hr/>
18
20
  <%= raw @rails_info_log.accordion %>
21
+ <hr/>
22
+ <h3><a name="writes" href="#top">2 ) Writes</a></h3>
23
+ <hr/>
19
24
  <%= raw @rails_info_log.write_tabs %>
@@ -2,7 +2,7 @@
2
2
  <p>
3
3
  <%= check_box_tag 'debug' %> debug? &nbsp;&nbsp;
4
4
  <%= label_tag 'log[rails_root]', raw('<strong>Rails root:</strong>') %>
5
- <%= text_field_tag 'log[rails_root]', (params['log']['rails_root'] rescue "#{Rails.root}/"), size: 50 %> &nbsp;&nbsp;
5
+ <%= text_field_tag 'log[rails_root]', (params['log']['rails_root'] rescue "#{Rails.root}/"), size: 75 %> &nbsp;&nbsp;
6
6
  <%= submit_tag 'submit' %>
7
7
  </p>
8
8
  <% end %>
@@ -7,6 +7,7 @@ class RailsInfo::Logs::Server
7
7
  path = options[:log][:path] || "#{Rails.root}/log/"
8
8
  env = options[:log][:env] || Rails.env
9
9
  @body = options[:log][:body]
10
+ @start_after_last_shutdown = options[:log][:start_after_last_shutdown] || true
10
11
 
11
12
  unless @body
12
13
  file_path = "#{path}#{env}.log"
@@ -31,114 +32,67 @@ class RailsInfo::Logs::Server
31
32
  private
32
33
 
33
34
  def process
34
- @start_after_last_shutdown = true
35
- @body = @body.split("\n").map(&:strip)
35
+ @body = @body.split("\n").map{|l| l.gsub(/\e/, '')}.map(&:strip)
36
36
 
37
37
  reset_log
38
-
39
- group_by_action = false
40
-
41
- @body.each do |line|
42
- if line.match('Processing') && line.match('#') && line.match(/\[/) && line.match(/\]/)
43
- # rails 2
44
- group_by_action = true
45
- elsif line.match('Started') && line.match(' for ') && line.match(' at ') && line.split(' ').length == 9
46
- # rails 3
47
- group_by_action = true
48
- elsif line.match('Processing by') && line.match('#') && line.match(' as ') && line.split(' ').length == 5
49
- # rails 3
50
- group_by_action = true
51
- end
52
- end
53
-
54
- unless group_by_action
55
- @action = 'no_action_grouping'
56
- @log[@action] ||= { 'Parameters' => '', 'WRITE' => {}, 'READ' => [], 'views' => [], 'misc' => [], 'errors' => []}
57
- end
38
+ group_by_action?
58
39
 
59
40
  @body.each do |line|
60
41
  process_line(line)
42
+ @last_action = @action
61
43
  end
62
44
 
63
- @log.each do |action,tabs|
64
- tabs.each do |tab,content|
65
- @log[action].delete(tab) if @log[action][tab].blank?
66
- end
67
- end
68
-
69
- @log.each do |action,tabs|
70
- tabs.each do |tab,content|
71
- next unless tab == 'WRITE'
72
-
73
- # define WHERE column as last one
74
- content.each do |table_name,data|
75
- @log[action][tab][table_name]['columns'] << 'WHERE'
76
- end
45
+ delete_empty_tabs
46
+ set_where_column_as_last_one_in_write_tab
47
+ end
48
+
49
+ def reset_log
50
+ @log, @action_indexes, @route, @action, @format, @last_action = {}, {}, '', '', '', ''
51
+ end
52
+
53
+ def group_by_action?
54
+ group_by_action = false
77
55
 
56
+ @body.each do |line|
57
+ if line.match('Processing by') && line.match('#') && line.match(' as ') && line.split(' ').length == 5
58
+ # rails 3
59
+ group_by_action = true
60
+ #elsif line.match('Processing') && line.match('#') && line.match(/\[/) && line.match(/\]/)
61
+ # rails 2
62
+ # group_by_action = true
63
+ #elsif line.match('Started') && line.match(' for ') && line.match(' at ') && line.split(' ').length == 9
64
+ # rails 3
65
+ # group_by_action = true
78
66
  break
79
67
  end
80
68
  end
81
69
 
82
- @writes.each do |table_name,data|
83
- @writes[table_name]['columns'] << 'WHERE'
70
+ unless group_by_action
71
+ @action = 'no_action_grouping'
72
+ @log[@action] ||= { 'Request' => {}, 'WRITE' => {}, 'READ' => [], 'views' => [], 'misc' => [], 'errors' => []}
84
73
  end
85
74
  end
86
75
 
87
- def reset_log
88
- @log, @action_indexes, @action, @last_action = {}, {}, "", ""
89
- end
90
-
91
76
  # TODO: process test.log which don't have action grouping, too
92
77
  # TODO: look if newrelic & Co. already does that but are only doing it for the last action
93
78
  # TODO: parse stack traces by grouping the lines by file and than method, generate a pseudo web sequence diagram code for files as participants and their methods
94
79
  # TODO: integrate a code snippet for each line of the stack trace like brakeman & co. do
95
80
  # TODO: extend rails stack trace output by code snippets
96
81
  def process_line(line)
97
- if line.match('Ctrl-C to shutdown server') && @start_after_last_shutdown
98
- reset_log
99
- elsif line.match('Processing') && line.match('#') && line.match(/\[/) && line.match(/\]/)
100
- # rails 2 start of action
101
- # Processing Clickworker::DashboardsController#show (for 127.0.0.1 at 2011-08-26 12:22:58) [GET]
102
- @action = line.split(' ')[1]
103
-
104
- init_log_action
105
- #elsif line.match('Started') && line.match(' for ') && line.match(' at ') && line.split(' ').length == 9
106
- # rails 3 start of action
107
- # Started GET "/orders/815?truncate_length=1000" for 127.0.0.1 at 2011-10-04 19:58:44 +0200
108
- elsif line.match('Processing by') && line.match('#') && line.match(' as ') && line.split(' ').length == 5
109
- # rails 3 start of action
110
- # Processing by OrdersController#show as HTML
111
- @action = line.split(' ')[2]
112
-
113
- init_log_action
114
- elsif @action.blank?
115
- elsif line.match('Parameters:') && line.match('{') && line.match('}')
116
- line = line.split(' ')
117
- line.pop
118
- @log[@action]['Parameters'] = line.join(' ').strip
119
- elsif line.match('INSERT INTO') || line.match('UPDATE')
120
- table_name = table_name_from_line(line)
121
-
122
- data = line.match('INSERT INTO') ? process_insert(line) : process_update(table_name, line)
123
-
124
- # TaskTemplate Create (0.2ms) INSERT INTO `task_templates` (`slug`, `name`, `created_at`, `product_id`, `updated_at`, `customer_id`, `state`) VALUES('the code', 'a customer name', '2011-08-26 10:22:54', 2, '2011-08-26 10:22:54', 1002, 'draft')
125
- #
126
- # InputDataItem Update (0.3ms) UPDATE `data_items` SET `input` = '<opt>\n <input>\n <__dynamic_form__>\n <df_create>\n <the_input></the_input>\n <the_output>Output field 1</the_output>\n </df_create>\n </__dynamic_form__>\n </input>\n</opt>\n', `updated_at` = '2011-08-26 10:22:55' WHERE `id` = 5485
127
-
128
-
129
- @log[@action]['WRITE'][table_name] ||= { 'columns' => ['id'], 'rows' => [] }
130
- @writes[table_name] ||= { 'columns' => ['id'], 'rows' => [] }
131
-
132
- @log[@action]['WRITE'][table_name]['columns'] = @log[@action]['WRITE'][table_name]['columns'].concat(data.keys).uniq
133
- @writes[table_name]['columns'] = @writes[table_name]['columns'].concat(data.keys).uniq
134
- @log[@action]['WRITE'][table_name]['rows'] << data
135
- @writes[table_name]['rows'] << data
136
- elsif (line.match('Load') && line.match('SELECT')) || (line.match('CACHE') && line.match('\(') && line.match('ms\)'))
137
- line = line.split(')')
138
- line.shift
139
- @log[@action]['READ'] ||= []
140
- @log[@action]['READ'] << line.join(')').strip
141
- elsif line.match('Rendered') && line.match('\(') && line.match('ms\)')
82
+ return if line.blank?
83
+
84
+ reset_log and return if line.match('Ctrl-C to shutdown server') && @start_after_last_shutdown
85
+
86
+ parse_route(line) and return
87
+ parse_action(line) and return
88
+
89
+ return if @action.blank?
90
+
91
+ parse_request(line) and return
92
+ parse_read(line) and return
93
+ parse_write(line) and return
94
+
95
+ if line.match('Rendered') && line.match('\(') && line.match('ms\)')
142
96
  @log[@action]['Views'] ||= []
143
97
  line = line.split('Rendered')
144
98
  line.shift
@@ -154,21 +108,123 @@ class RailsInfo::Logs::Server
154
108
  else
155
109
  @log[@action]['misc'] << line
156
110
  end
157
-
158
- @last_action = @action
159
111
  end
160
112
 
161
- def table_name_from_line(line)
162
- line = line.split(')')
163
- line.shift
164
- line = line.join(')')
113
+ def delete_empty_tabs
114
+ @log.each do |action,tabs|
115
+ tabs.each do |tab,content|
116
+ @log[action].delete(tab) if @log[action][tab].blank?
117
+ end
118
+ end
119
+ end
120
+
121
+ def set_where_column_as_last_one_in_write_tab
122
+ @log.select{|a,t| t['WRITE'].is_a?(Hash) }.each do |action,tabs|
123
+ tabs['WRITE'].each do |table_name,data|
124
+ @log[action]['WRITE'][table_name]['columns'] << 'WHERE'
125
+ end
126
+ end
127
+
128
+ @writes.each {|table_name,data| @writes[table_name]['columns'] << 'WHERE' }
129
+ end
130
+
131
+ def parse_route(line)
132
+ reg_exp = /^Started(.{1,})for/
133
+
134
+ return false unless line.match(reg_exp)
135
+
136
+ @route = line.match(reg_exp)[1].strip
137
+
138
+ true
139
+ end
140
+
141
+ def parse_action(line)
142
+ reg_exp = /^Processing by {1}(.{1,}) {1}as {1}(.{1,})$/
143
+
144
+ return false unless line.match(reg_exp)
145
+
146
+ @action = line.match(reg_exp)[1].strip
147
+ @format = line.match(reg_exp)[2].strip
148
+
149
+ init_log_action unless @action.blank?
150
+
151
+ true
152
+ end
153
+
154
+ def parse_request(line)
155
+ reg_exp = /^Parameters:( ){1}(\{(.)+\}$)/
156
+
157
+ if line.match(reg_exp)
158
+ @log[@action]['Request']['Parameters'] = eval(line.match(reg_exp)[2]) rescue line
159
+
160
+ true
161
+ else
162
+ false
163
+ end
164
+ end
165
+
166
+ def parse_read(line)
167
+ reg_exp_begin = '\[([0-9]+)m( {2}|)(SELECT.+)'
168
+
169
+ #[1mCommunity Load (0.5ms) SELECT `communities`.* FROM `communities` WHERE `communities`.`id` = 2 LIMIT 1
170
+ reg_exp1 = "#{reg_exp_begin}(\\[)"
171
+
172
+ #[1mCACHE (0.0ms) SELECT `communities`.* FROM `communities` WHERE `communities`.`deleted` = 0 AND `communities`.`slug` = 'bronze' LIMIT 1
173
+ reg_exp2 = "#{reg_exp_begin}$"
174
+
175
+ reg_exp = if line.match(reg_exp1)
176
+ reg_exp1
177
+ elsif line.match(reg_exp2)
178
+ reg_exp2
179
+ else
180
+ nil
181
+ end
182
+
183
+ return false unless reg_exp
184
+
185
+ @log[@action]['READ'] ||= []
186
+ @log[@action]['READ'] << line.match(reg_exp)[3].strip
187
+
188
+ true
189
+ end
190
+
191
+ def parse_write(line)
192
+ reg_exp = /([0-9]+)m( ){2}((INSERT INTO|UPDATE|DELETE FROM)(.)+)$/
193
+
194
+ return false unless line.match(reg_exp)
195
+
196
+ table_name = line.match(/(INSERT INTO|UPDATE|DELETE FROM) {1}`([a-zA-Z0-9_]+)`/)[2]
197
+
198
+ data = {}
199
+
200
+ if line.match(/([0-9]+)m( ){2}INSERT INTO( ){1}`(.{1,})`( ){1}(.)+$/)
201
+ data = process_insert(line)
202
+ elsif line.match(/([0-9]+)m( ){2}UPDATE( ){1}`(.{1,})`( ){1}(.)+$/)
203
+ data = process_update(table_name, line)
204
+ elsif line.match(/([0-9]+)m( ){2}DELETE FROM( ){1}`(.{1,})`( ){1}(.)+$/)
205
+ data = process_delete(table_name, line)
206
+ else
207
+ raise NotImplementedError
208
+ end
209
+
210
+ # TaskTemplate Create (0.2ms) INSERT INTO `task_templates` (`slug`, `name`, `created_at`, `product_id`, `updated_at`, `customer_id`, `state`) VALUES('the code', 'a customer name', '2011-08-26 10:22:54', 2, '2011-08-26 10:22:54', 1002, 'draft')
211
+ #
212
+ # InputDataItem Update (0.3ms) UPDATE `data_items` SET `input` = '<opt>\n <input>\n <__dynamic_form__>\n <df_create>\n <the_input></the_input>\n <the_output>Output field 1</the_output>\n </df_create>\n </__dynamic_form__>\n </input>\n</opt>\n', `updated_at` = '2011-08-26 10:22:55' WHERE `id` = 5485
213
+
165
214
 
166
- line = line.split('`')
167
- line[1]
215
+ @log[@action]['WRITE'][table_name] ||= { 'columns' => ['-action-', 'id'], 'rows' => [] }
216
+ @writes[table_name] ||= { 'columns' => ['-action-', 'id'], 'rows' => [] }
217
+
218
+ @log[@action]['WRITE'][table_name]['columns'] = @log[@action]['WRITE'][table_name]['columns'].concat(data.keys).uniq
219
+ @writes[table_name]['columns'] = @writes[table_name]['columns'].concat(data.keys).uniq
220
+ @log[@action]['WRITE'][table_name]['rows'] << data
221
+ @writes[table_name]['rows'] << data
222
+
223
+ true
168
224
  end
169
225
 
170
226
  def process_insert(line)
171
- data = {}
227
+ data = {'-action-' => 'INSERT'}
172
228
 
173
229
  columns = line.match(/\(`(.)+\)(( |)VALUES)/)[0].split('VALUES').first.strip.gsub('`', '')[1..-2].split(',').map(&:strip)
174
230
 
@@ -191,18 +247,17 @@ class RailsInfo::Logs::Server
191
247
  end
192
248
 
193
249
  def process_update(table_name, line)
194
- data = {}
250
+ data = {'-action-' => 'UPDATE'}
251
+
252
+ # "`editable` = 0, `updated_at` = '2012-07-09 16:33:31'"
253
+ data_string = line.match(/SET (.+) WHERE/)[1].strip
254
+ conditions = line.match(/WHERE(.+)$/)[1].strip
255
+
256
+ data_string = data_string.gsub(/(', `|, `)/, "||||").gsub(/(` = '|` = )/, "=").gsub(/(`|')/, '').split('||||')
195
257
 
196
- # SET `input` = '<opt>\n <input>\n <__dynamic_form__>\n <df_create>\n <the_input></the_input>\n <the_output>Output field 1</the_output>\n </df_create>\n </__dynamic_form__>\n </input>\n</opt>\n', `updated_at` = '2011-08-26 10:22:55' WHERE `id` = 5485
197
- line = line.split('WHERE')
198
- data_string = line.first
199
- conditions = line.last
200
- data_string = data_string.split(' '); data_string.shift; data_string = data_string.join(' ')
201
- data_string = data_string.gsub("', `", "||||").gsub(", `", '||||').gsub("` = '", "=").split('||||')
202
-
203
258
  data_string.each do |data_element|
204
259
  data_element = data_element.split('=')
205
- data[data_element.shift.gsub('`', '').strip] = data_element.join('=')
260
+ data[data_element.shift.strip] = data_element.join('=')
206
261
  end
207
262
 
208
263
  if conditions.match("`#{table_name}`.`id` = ([0-9]+)")
@@ -216,6 +271,23 @@ class RailsInfo::Logs::Server
216
271
  data
217
272
  end
218
273
 
274
+ def process_delete(table_name, line)
275
+ data = {'-action-' => 'DELETE'}
276
+
277
+ # ... WHERE `id` = 5485
278
+ conditions = line.split('WHERE').last
279
+
280
+ if conditions.match("`#{table_name}`.`id` = ([0-9]+)")
281
+ data['id'] = conditions.match("`#{table_name}`.`id` = ([0-9]+)")[0].split('=').last.strip
282
+ elsif conditions.match(/`id` = ([0-9]+)/)
283
+ data['id'] = conditions.match(/`id` = ([0-9]+)/)[0].split('=').last.strip
284
+ end
285
+
286
+ data['WHERE'] = conditions
287
+
288
+ data
289
+ end
290
+
219
291
  def init_log_action
220
292
  if @action_indexes.has_key?(@action)
221
293
  @action_indexes[@action] = @action_indexes[@action] + 1
@@ -225,6 +297,6 @@ class RailsInfo::Logs::Server
225
297
 
226
298
  @action = "#{@action} ##{@action_indexes[@action]}"
227
299
 
228
- @log[@action] ||= { 'Parameters' => '', 'WRITE' => {}, 'READ' => [], 'views' => [], 'misc' => [], 'errors' => []}
300
+ @log[@action] ||= { 'Request' => {'Route' => @route, 'Format' => @format}, 'WRITE' => {}, 'READ' => [], 'views' => [], 'misc' => [], 'errors' => []}
229
301
  end
230
302
  end
@@ -26,7 +26,11 @@ class RailsInfo::Logs::Test::Rspec
26
26
  end
27
27
 
28
28
  def hash
29
- @log
29
+ @log.keys.any? ? @log : (@body || [''])
30
+ end
31
+
32
+ def number_of_files
33
+ hash.is_a?(Hash) ? hash.keys.length : 0
30
34
  end
31
35
 
32
36
  def rails_root
@@ -97,6 +101,9 @@ class RailsInfo::Logs::Test::Rspec
97
101
  stack_trace << line
98
102
  end
99
103
  end
104
+
105
+ # free memory if log could be read otherwise keep text in memory to show instead
106
+ @body = nil if @log.keys.any?
100
107
  end
101
108
 
102
109
  def add_entry(example, failure_code, exception_class, exception_message, stack_trace, after_stack_trace_entry = nil)
@@ -131,9 +138,10 @@ class RailsInfo::Logs::Test::Rspec
131
138
  end
132
139
 
133
140
  if @log[file_name].has_key?(example)
134
- raise NotImplementedError.new(
135
- "RSpec file #{file_name} not expected to have more than 1 example named #{example.inspect}"
136
- )
141
+ # TODO: increment example tab count in this case
142
+ #raise NotImplementedError.new(
143
+ # "RSpec file #{file_name} not expected to have more than 1 example named #{example.inspect}"
144
+ #)
137
145
  end
138
146
 
139
147
  @log[file_name][example] = {
@@ -1,3 +1,3 @@
1
1
  module RailsInfo
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -7,8 +7,8 @@ require 'rails_info/logs'
7
7
  require 'rails_info/logs/server'
8
8
 
9
9
  describe RailsInfo::Logs::Server do
10
- before do
11
- body = "Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
10
+ =begin
11
+ Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
12
12
  Creating scope :visible. Overwriting existing method Reaction.visible.
13
13
  Processing by DeviseCustomized::RegistrationsController#create as HTML
14
14
  Parameters: {\"utf8\"=>'', \"authenticity_token\"=>\"k4xMIcuqMThMsdlbsVJ7GFgzNDw/HgGGp1ldElFULoY=\", \"user\"=>{\"screen_name\"=>\"mgawlista\", \"email\"=>\"gawlista@googlemail.com\", \"password\"=>\"[FILTERED]\", \"password_confirmation\"=>\"[FILTERED]\"}, \"community_id\"=>\"bronze\"}
@@ -20,31 +20,139 @@ Rendered devise/shared/_header.html.erb (70.4ms)
20
20
  Community Load (0.5ms) SELECT `communities`.* FROM `communities` WHERE `communities`.`id` = 2 LIMIT 1
21
21
  Redirected to http://localhost:3000/bronze
22
22
  SOLR Request (45541.1ms) [ path=#<RSolr::Client:0x007fbf26dc8b28> parameters={data: <?xml version=\"1.0\" encoding=\"UTF-8\"?><commit/>, headers: {\"Content-Type\"=>\"text/xml\"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://localhost:8982/solr/update?wt=ruby} ]
23
- Completed 302 Found in 125493ms"
24
- end
25
-
23
+ Completed 302 Found in 125493ms
24
+ =end
26
25
  describe '#process' do
27
- context 'just read' do
28
- it 'principally works' do
29
- body = "Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
26
+ describe '#parse_request' do
27
+ subject {
28
+ ::RailsInfo::Logs::Server.new(
29
+ log: {
30
+ body: "Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
30
31
  Processing by DeviseCustomized::RegistrationsController#create as HTML
32
+ Parameters: {\"authenticity_token\"=>\"k4xMIcuqMThMsdlbsVJ7GFgzNDw/HgGGp1ldElFULoY=\", \"user\"=>{\"screen_name\"=>\"mgawlista\"}}
33
+  "
34
+ }
35
+ )
36
+ }
37
+
38
+ it 'parses request correctly' do
39
+ subject.hash.should == {
40
+ 'DeviseCustomized::RegistrationsController#create #1' => {
41
+ 'Request' => {
42
+ 'Route' => "POST \"/users/bronze\"",
43
+ 'Format' => 'HTML',
44
+ 'Parameters' => {"authenticity_token"=>"k4xMIcuqMThMsdlbsVJ7GFgzNDw/HgGGp1ldElFULoY=", "user"=>{"screen_name"=>"mgawlista"}},
45
+ }
46
+ }
47
+ }
48
+ end
49
+ end
50
+
51
+ describe '#parse_read' do
52
+ context 'line ending LIMIT 1' do
53
+ subject {
54
+ ::RailsInfo::Logs::Server.new(
55
+ log: {
56
+ body: "Processing by DeviseCustomized::RegistrationsController#create as HTML
31
57
  [1mCACHE (0.0ms) SELECT `communities`.* FROM `communities` WHERE `communities`.`deleted` = 0 AND `communities`.`slug` = 'bronze' LIMIT 1
32
- "
33
- @rails_info_log = ::RailsInfo::Logs::Server.new(log: { body: body })
34
-
35
- raise @rails_info_log.hash.inspect
58
+ "
59
+ }
60
+ )
61
+ }
36
62
 
37
- @rails_info_log.hash.should == {
38
- 'DeviseCustomized::RegistrationsController#create #1' => {
39
- 'READ' => [
40
- "SELECT `communities`.* FROM `communities` WHERE `communities`.`deleted` = 0 AND `communities`.`slug` = 'bronze' LIMIT 1'",
41
- ],
42
- 'misc' => [
43
- 'Processing by DeviseCustomized::RegistrationsController#create as HTML'
44
- ]
63
+ it 'will be parsed correctly' do
64
+ subject.hash.should == {
65
+ 'DeviseCustomized::RegistrationsController#create #1' => {
66
+ 'Request' => { 'Route' => '', 'Format' => 'HTML' },
67
+ 'READ' => [
68
+ "SELECT `communities`.* FROM `communities` WHERE `communities`.`deleted` = 0 AND `communities`.`slug` = 'bronze' LIMIT 1",
69
+ ]
70
+ }
45
71
  }
72
+ end
73
+ end
74
+
75
+ context 'line ending LIMIT 1[.' do
76
+ subject {
77
+ ::RailsInfo::Logs::Server.new(
78
+ log: {
79
+ body: "Processing by DeviseCustomized::RegistrationsController#create as HTML
80
+ [1mCommunity Load (0.5ms) SELECT `communities`.* FROM `communities` WHERE `communities`.`id` = 2 LIMIT 1
81
+ "
82
+ }
83
+ )
46
84
  }
85
+
86
+ it 'will be parsed correctly' do
87
+ subject.hash.should == {
88
+ 'DeviseCustomized::RegistrationsController#create #1' => {
89
+ 'Request' => { 'Route' => '', 'Format' => 'HTML' },
90
+ 'READ' => [
91
+ "SELECT `communities`.* FROM `communities` WHERE `communities`.`id` = 2 LIMIT 1",
92
+ ]
93
+ }
94
+ }
95
+ end
96
+ end
97
+ end
98
+
99
+ describe '#process_insert' do
100
+ subject {
101
+ ::RailsInfo::Logs::Server.new(
102
+ log: {
103
+ body: "Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
104
+ Processing by DeviseCustomized::RegistrationsController#create as HTML
105
+ [1mSQL (276.4ms) INSERT INTO `users` (`city`, `city_permissions`, `confirmation_sent_at`, `confirmation_token`, `confirmed_at`, `created_at`, `current_sign_in_at`, `current_sign_in_ip`, `delete_token`, `deleted`, `developer`, `email`, `encrypted_password`, `facebook`, `facebook_id`, `facebook_permissions`, `failed_attempts`, `forename`, `google_id`, `initial_community_id`, `last_sign_in_at`, `last_sign_in_ip`, `linkedin`, `linkedin_permissions`, `locked_at`, `master`, `name_permissions`, `notification_email`, `password_salt`, `phone`, `phone_permissions`, `photo_content_type`, `photo_file_name`, `photo_file_size`, `photo_updated_at`, `remember_created_at`, `reset_password_sent_at`, `reset_password_token`, `screen_name`, `screen_name_permissions`, `sign_in_count`, `slug`, `street`, `street_permissions`, `surname`, `tagline`, `tagline_permissions`, `twitter`, `twitter_permissions`, `unconfirmed_email`, `unlock_token`, `updated_at`, `url`, `website`, `website_permissions`, `xing`, `xing_permissions`, `zipcode`, `zipcode_permissions`) VALUES (NULL, 0, '2012-07-05 17:33:50', 'xVQj9z8xGm1bzqqJBjUn', NULL, '2012-07-05 17:33:50', NULL, NULL, NULL, 0, NULL, 'gawlista@googlemail.com', '$2a$10$KnrBV6m64g0zqKwUnQRR/exiUN9HtzJCGLSUse.jPTxLp0WQtNec2', NULL, NULL, 0, 0, NULL, NULL, 2, NULL, NULL, NULL, 0, NULL, 0, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'mgawlista', 0, 0, 'mgawlista', NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL, '2012-07-05 17:33:50', NULL, NULL, 0, NULL, 0, NULL, 0)
106
+ "
107
+ }
108
+ )
109
+ }
110
+
111
+ it 'parses INSERT entries correctly' do
112
+ action = 'DeviseCustomized::RegistrationsController#create #1'
113
+ subject.hash[action]['Request'].should == { 'Route' => "POST \"/users/bronze\"", 'Format' => 'HTML' }
114
+
115
+ compare_data(
116
+ subject.hash[action]['WRITE']['users'],
117
+ { '-action-' => 'INSERT', 'id' => nil, 'city' => 'NULL', 'WHERE' => nil }
118
+ )
119
+ end
120
+ end
121
+
122
+ describe '#process_update' do
123
+ subject {
124
+ ::RailsInfo::Logs::Server.new(
125
+ log: {
126
+ body: "Started POST \"/users/bronze\" for 127.0.0.1 at 2012-07-05 19:33:44 +0200
127
+ Processing by DeviseCustomized::RegistrationsController#create as HTML
128
+ [1m (0.4ms) UPDATE `feedbacks` SET `editable` = 0, `updated_at` = '2012-07-09 16:33:31' WHERE `feedbacks`.`type` IN ('Question') AND `feedbacks`.`id` = 3
129
+ "
130
+ }
131
+ )
132
+ }
133
+
134
+ it 'parses UPDATE entries correctly' do
135
+ action = 'DeviseCustomized::RegistrationsController#create #1'
136
+ subject.hash[action]['Request'].should == { 'Route' => "POST \"/users/bronze\"", 'Format' => 'HTML' }
137
+
138
+ compare_data(
139
+ subject.hash[action]['WRITE']['feedbacks'],
140
+ {
141
+ '-action-' => 'UPDATE', 'id' => '3', 'editable' => '0', 'updated_at' => '2012-07-09 16:33:31',
142
+ 'WHERE' => "`feedbacks`.`type` IN ('Question') AND `feedbacks`.`id` = 3"
143
+ }
144
+ )
47
145
  end
48
146
  end
49
147
  end
50
148
  end
149
+
150
+ def compare_data(table, data)
151
+ data.keys.each_index do |current_index|
152
+ index = data.keys[current_index] == 'WHERE' ? table['columns'].length - 1 : current_index
153
+ column = data.keys[current_index]
154
+ table['columns'][index].should == column
155
+
156
+ table['rows'].first[column].should == data[column] unless data[column] == nil
157
+ end
158
+ end
@@ -3,6 +3,10 @@ unless defined? Rails
3
3
  def self.root
4
4
  File.expand_path('dummy', __FILE__)
5
5
  end
6
+
7
+ def self.env
8
+ 'test'
9
+ end
6
10
  end
7
11
  end
8
12
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_info
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-06 00:00:00.000000000 Z
12
+ date: 2012-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70253477230800 !ruby/object:Gem::Requirement
16
+ requirement: &70242337984640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70253477230800
24
+ version_requirements: *70242337984640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: coffee-script
27
- requirement: &70253477230000 !ruby/object:Gem::Requirement
27
+ requirement: &70242337983580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70253477230000
35
+ version_requirements: *70242337983580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: uglifier
38
- requirement: &70253477228920 !ruby/object:Gem::Requirement
38
+ requirement: &70242337982560 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70253477228920
46
+ version_requirements: *70242337982560
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jquery-rails
49
- requirement: &70253477228160 !ruby/object:Gem::Requirement
49
+ requirement: &70242337981960 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70253477228160
57
+ version_requirements: *70242337981960
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jquery-ui-rails
60
- requirement: &70253477227440 !ruby/object:Gem::Requirement
60
+ requirement: &70242337981320 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70253477227440
68
+ version_requirements: *70242337981320
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pygments.rb
71
- requirement: &70253477226720 !ruby/object:Gem::Requirement
71
+ requirement: &70242337980500 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70253477226720
79
+ version_requirements: *70242337980500
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: twitter-bootstrap-rails
82
- requirement: &70253477226040 !ruby/object:Gem::Requirement
82
+ requirement: &70242337979860 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70253477226040
90
+ version_requirements: *70242337979860
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: simple-navigation-bootstrap
93
- requirement: &70253477225320 !ruby/object:Gem::Requirement
93
+ requirement: &70242337979280 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70253477225320
101
+ version_requirements: *70242337979280
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: awesome_print
104
- requirement: &70253477224820 !ruby/object:Gem::Requirement
104
+ requirement: &70242337978780 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70253477224820
112
+ version_requirements: *70242337978780
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rspec-rails
115
- requirement: &70253477224320 !ruby/object:Gem::Requirement
115
+ requirement: &70242337978360 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70253477224320
123
+ version_requirements: *70242337978360
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: mysql2
126
- requirement: &70253477223880 !ruby/object:Gem::Requirement
126
+ requirement: &70242337977840 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70253477223880
134
+ version_requirements: *70242337977840
135
135
  description: Engine for a rails application which extends /rails/info about some information
136
136
  resources in development environment.
137
137
  email:
@@ -177,6 +177,7 @@ files:
177
177
  - app/views/layouts/rails_info.html.erb
178
178
  - app/views/layouts/shared/_navigation.html.erb
179
179
  - app/views/rails_info/data/index.html.erb
180
+ - app/views/rails_info/logs/server/_request.html.erb
180
181
  - app/views/rails_info/logs/server/_table.html.erb
181
182
  - app/views/rails_info/logs/server/new.html.erb
182
183
  - app/views/rails_info/logs/test/rspec/new.html.erb
@@ -256,7 +257,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
257
  version: '0'
257
258
  segments:
258
259
  - 0
259
- hash: 206197979266972554
260
+ hash: -3145686660104229554
260
261
  required_rubygems_version: !ruby/object:Gem::Requirement
261
262
  none: false
262
263
  requirements:
@@ -265,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
266
  version: '0'
266
267
  segments:
267
268
  - 0
268
- hash: 206197979266972554
269
+ hash: -3145686660104229554
269
270
  requirements: []
270
271
  rubyforge_project:
271
272
  rubygems_version: 1.8.17