card 1.16.4 → 1.16.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/db/migrate_core_cards/20150429090551_search_card_context.rb +34 -0
- data/db/migrate_core_cards/20150824135418_update_file_history.rb +10 -5
- data/db/migrate_core_cards/20150910085603_remove_performance_log_card.rb +10 -0
- data/db/seed/new/card_actions.yml +358 -366
- data/db/seed/new/card_acts.yml +1 -1
- data/db/seed/new/card_changes.yml +1379 -1399
- data/db/seed/new/card_references.yml +1109 -710
- data/db/seed/new/cards.yml +1436 -1454
- data/db/seed/test/fixtures/card_actions.yml +1031 -1039
- data/db/seed/test/fixtures/card_acts.yml +155 -155
- data/db/seed/test/fixtures/card_changes.yml +4148 -4168
- data/db/seed/test/fixtures/card_references.yml +1577 -1178
- data/db/seed/test/fixtures/cards.yml +2259 -2277
- data/db/version_core_cards.txt +1 -1
- data/lib/card.rb +3 -2
- data/lib/card/env.rb +66 -0
- data/lib/card/format.rb +3 -38
- data/lib/card/loader.rb +0 -4
- data/lib/card/location.rb +38 -0
- data/lib/card/set.rb +1 -3
- data/lib/card/success.rb +2 -3
- data/mod/01_core/format/html_format.rb +0 -48
- data/mod/01_core/set/all/collection.rb +9 -7
- data/mod/01_core/set/all/initialize.rb +5 -0
- data/mod/01_core/set/all/location_history.rb +10 -0
- data/mod/01_core/set/all/phases.rb +2 -1
- data/mod/01_core/set/all/rules.rb +0 -2
- data/mod/01_core/set/all/trash.rb +3 -2
- data/mod/01_core/set/all/utils.rb +12 -0
- data/mod/01_core/spec/set/all/permissions_spec.rb +8 -8
- data/mod/01_core/spec/set/all/type_spec.rb +14 -14
- data/mod/01_history/set/all/content_history.rb +7 -3
- data/mod/01_history/set/all/history.rb +3 -3
- data/mod/02_basic_types/set/type/pointer.rb +8 -1
- data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +39 -0
- data/mod/03_machines/lib/stylesheets/style_cards.scss +12 -2
- data/mod/03_machines/set/right/machine_output.rb +4 -0
- data/mod/03_machines/set/type/css.rb +1 -1
- data/mod/04_settings/spec/set/right/structure_spec.rb +1 -1
- data/mod/05_email/set/all/observer.rb +5 -5
- data/mod/05_email/set/type_plus_right/user/follow.rb +1 -1
- data/mod/05_standard/file/favicon/image-icon.png +0 -0
- data/mod/05_standard/file/favicon/image-large.png +0 -0
- data/mod/05_standard/file/favicon/image-medium.png +0 -0
- data/mod/05_standard/file/favicon/image-original.png +0 -0
- data/mod/05_standard/file/favicon/image-small.png +0 -0
- data/mod/05_standard/lib/carrier_wave/cardmount.rb +8 -2
- data/mod/05_standard/lib/file_uploader.rb +47 -35
- data/mod/05_standard/set/abstract/attachment.rb +87 -35
- data/mod/05_standard/set/all/error.rb +1 -1
- data/mod/05_standard/set/all/links.rb +1 -0
- data/mod/05_standard/set/self/signin.rb +1 -1
- data/mod/05_standard/set/type/file.rb +16 -1
- data/mod/05_standard/set/type/image.rb +2 -0
- data/mod/05_standard/set/type/search_type.rb +2 -2
- data/mod/05_standard/spec/chunk/link_spec.rb +42 -32
- data/mod/05_standard/spec/set/all/links_spec.rb +15 -0
- data/mod/05_standard/spec/set/self/head_spec.rb +3 -3
- data/mod/05_standard/spec/set/type/email_template_spec.rb +39 -39
- data/mod/05_standard/spec/set/type/file_spec.rb +0 -12
- data/mod/05_standard/spec/set/type/image_spec.rb +26 -2
- data/spec/lib/card/content_spec.rb +169 -154
- data/spec/lib/card/format_spec.rb +7 -7
- data/spec/lib/card/success_spec.rb +1 -1
- metadata +7 -6
- data/lib/card/log.rb +0 -545
- data/mod/05_standard/set/self/performance_log.rb +0 -92
- data/spec/lib/card/log_spec.rb +0 -270
@@ -10,24 +10,24 @@ describe Card::Format do
|
|
10
10
|
expect(format.show_view?( :menu, :default_visibility=>:hide )).to be_falsey
|
11
11
|
expect(format.show_view?( :menu, {} )).to be_truthy
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "should respect developer default overrides" do
|
15
15
|
expect(format.show_view?( :menu, :optional_menu=>:show, :default_visibility=>:hide )).to be_truthy
|
16
16
|
expect(format.show_view?( :menu, :optional_menu=>:hide, :default_visibility=>:show )).to be_falsey
|
17
17
|
expect(format.show_view?( :menu, :optional_menu=>:hide )).to be_falsey
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it "should handle args from inclusions" do
|
21
21
|
expect(format.show_view?( :menu, :show=>'menu', :default_visibility=>:hide )).to be_truthy
|
22
22
|
expect(format.show_view?( :menu, :hide=>'menu, paging', :default_visibility=>:show )).to be_falsey
|
23
|
-
expect(format.show_view?( :menu, :show=>'menu', :optional_menu=>:hide )).to be_truthy
|
23
|
+
expect(format.show_view?( :menu, :show=>'menu', :optional_menu=>:hide )).to be_truthy
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it "should handle hard developer overrides" do
|
27
27
|
expect(format.show_view?( :menu, :optional_menu=>:always, :hide=>'menu' )).to be_truthy
|
28
28
|
expect(format.show_view?( :menu, :optional_menu=>:never, :show=>'menu' )).to be_falsey
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
end
|
32
32
|
|
33
33
|
describe 'format helpers and link building' do
|
@@ -61,11 +61,11 @@ describe Card::Format do
|
|
61
61
|
|
62
62
|
it "should format html links" do
|
63
63
|
cobj = Card::Content.new url_text1, html_format
|
64
|
-
expect(cobj.to_s).to eq "with external free link <a class=\"external-link\" href=\"http://localhost:2020/path?cgi=foo&bar=baz\">http://localhost:2020/path?cgi=foo&bar=baz</a>"
|
64
|
+
expect(cobj.to_s).to eq "with external free link <a target=\"_blank\" class=\"external-link\" href=\"http://localhost:2020/path?cgi=foo&bar=baz\">http://localhost:2020/path?cgi=foo&bar=baz</a>"
|
65
65
|
cobj = Card::Content.new url_text2+url_text3+url_text4, html_format
|
66
66
|
expect(cobj.to_s).to eq url_text2+url_text3+url_text4
|
67
67
|
cobj = Card::Content.new url_text5, html_format
|
68
|
-
expect(cobj.to_s).to eq "external with port: <a class=\"external-link\" href=\"http://localhost:2020/path?cgi=foo+bar=baz\">http://localhost:2020/path?cgi=foo+bar=baz</a> after "
|
68
|
+
expect(cobj.to_s).to eq "external with port: <a target=\"_blank\" class=\"external-link\" href=\"http://localhost:2020/path?cgi=foo+bar=baz\">http://localhost:2020/path?cgi=foo+bar=baz</a> after "
|
69
69
|
end
|
70
70
|
|
71
71
|
it "formats page_path" do
|
@@ -5,8 +5,8 @@ describe Card::Success do
|
|
5
5
|
let(:previous) { '/B' }
|
6
6
|
let(:home) { Card['Home'] }
|
7
7
|
def success_params params
|
8
|
+
Card::Env.save_location Card['B']
|
8
9
|
@success = Card::Success.new(context, params)
|
9
|
-
@success.stub(:previous_location) { previous }
|
10
10
|
end
|
11
11
|
describe '#target' do
|
12
12
|
subject { @success.target }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: card
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.16.
|
4
|
+
version: 1.16.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan McCutchen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-09-
|
14
|
+
date: 2015-09-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: smartname
|
@@ -291,6 +291,7 @@ files:
|
|
291
291
|
- db/migrate_core_cards/20150317162412_bootstrap_themes.rb
|
292
292
|
- db/migrate_core_cards/20150326205655_bootswatch_themes.rb
|
293
293
|
- db/migrate_core_cards/20150331135745_new_card_menu.rb
|
294
|
+
- db/migrate_core_cards/20150429090551_search_card_context.rb
|
294
295
|
- db/migrate_core_cards/20150508212032_menu_compatibility.rb
|
295
296
|
- db/migrate_core_cards/20150510031118_fix_skin_images.rb
|
296
297
|
- db/migrate_core_cards/20150528084659_add_session_cardtype.rb
|
@@ -304,6 +305,7 @@ files:
|
|
304
305
|
- db/migrate_core_cards/20150807205221_create_references_for_search_cards.rb
|
305
306
|
- db/migrate_core_cards/20150824135418_update_file_history.rb
|
306
307
|
- db/migrate_core_cards/20150903130006_attachment_upload_cards.rb
|
308
|
+
- db/migrate_core_cards/20150910085603_remove_performance_log_card.rb
|
307
309
|
- db/migrate_core_cards/data/1.11_help_text.json
|
308
310
|
- db/migrate_core_cards/data/1.12_stylesheets/classic_cards.scss
|
309
311
|
- db/migrate_core_cards/data/1.12_stylesheets/common.scss
|
@@ -390,7 +392,7 @@ files:
|
|
390
392
|
- lib/card/exceptions.rb
|
391
393
|
- lib/card/format.rb
|
392
394
|
- lib/card/loader.rb
|
393
|
-
- lib/card/
|
395
|
+
- lib/card/location.rb
|
394
396
|
- lib/card/mailer.rb
|
395
397
|
- lib/card/migration.rb
|
396
398
|
- lib/card/name.rb
|
@@ -443,6 +445,7 @@ files:
|
|
443
445
|
- mod/01_core/set/all/fetch.rb
|
444
446
|
- mod/01_core/set/all/haml.rb
|
445
447
|
- mod/01_core/set/all/initialize.rb
|
448
|
+
- mod/01_core/set/all/location_history.rb
|
446
449
|
- mod/01_core/set/all/name.rb
|
447
450
|
- mod/01_core/set/all/pattern.rb
|
448
451
|
- mod/01_core/set/all/permissions.rb
|
@@ -702,7 +705,6 @@ files:
|
|
702
705
|
- mod/05_standard/set/self/head.rb
|
703
706
|
- mod/05_standard/set/self/navbox.rb
|
704
707
|
- mod/05_standard/set/self/now.rb
|
705
|
-
- mod/05_standard/set/self/performance_log.rb
|
706
708
|
- mod/05_standard/set/self/recent.rb
|
707
709
|
- mod/05_standard/set/self/search.rb
|
708
710
|
- mod/05_standard/set/self/signin.rb
|
@@ -740,6 +742,7 @@ files:
|
|
740
742
|
- mod/05_standard/spec/set/all/error_spec.rb
|
741
743
|
- mod/05_standard/spec/set/all/event_viz_spec.rb
|
742
744
|
- mod/05_standard/spec/set/all/history_spec.rb
|
745
|
+
- mod/05_standard/spec/set/all/links_spec.rb
|
743
746
|
- mod/05_standard/spec/set/all/rich_html/editing_spec.rb
|
744
747
|
- mod/05_standard/spec/set/all/rich_html/form_spec.rb
|
745
748
|
- mod/05_standard/spec/set/all/rich_html/wrapper_spec.rb
|
@@ -955,7 +958,6 @@ files:
|
|
955
958
|
- spec/lib/card/diff_spec.rb
|
956
959
|
- spec/lib/card/format_spec.rb
|
957
960
|
- spec/lib/card/loader_spec.rb
|
958
|
-
- spec/lib/card/log_spec.rb
|
959
961
|
- spec/lib/card/name_spec.rb
|
960
962
|
- spec/lib/card/query_spec.rb
|
961
963
|
- spec/lib/card/reference_spec.rb
|
@@ -1184,7 +1186,6 @@ test_files:
|
|
1184
1186
|
- spec/lib/card/diff_spec.rb
|
1185
1187
|
- spec/lib/card/format_spec.rb
|
1186
1188
|
- spec/lib/card/loader_spec.rb
|
1187
|
-
- spec/lib/card/log_spec.rb
|
1188
1189
|
- spec/lib/card/name_spec.rb
|
1189
1190
|
- spec/lib/card/query_spec.rb
|
1190
1191
|
- spec/lib/card/reference_spec.rb
|
data/lib/card/log.rb
DELETED
@@ -1,545 +0,0 @@
|
|
1
|
-
require 'csv'
|
2
|
-
|
3
|
-
class Card::Log
|
4
|
-
|
5
|
-
class Request
|
6
|
-
|
7
|
-
def self.path
|
8
|
-
path = (Card.paths['request_log'] && Card.paths['request_log'].first) || File.dirname(Card.paths['log'].first)
|
9
|
-
filename = "#{Date.today}_#{Rails.env}.csv"
|
10
|
-
File.join path, filename
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.write_log_entry controller
|
14
|
-
return if controller.env["REQUEST_URI"] =~ %r{^/files?/}
|
15
|
-
|
16
|
-
controller.instance_eval do
|
17
|
-
log = []
|
18
|
-
log << (Card::Env.ajax? ? "YES" : "NO")
|
19
|
-
log << env["REMOTE_ADDR"]
|
20
|
-
log << Card::Auth.current_id
|
21
|
-
log << card.name
|
22
|
-
log << action_name
|
23
|
-
log << params['view'] || (s = params['success'] and s['view'])
|
24
|
-
log << env["REQUEST_METHOD"]
|
25
|
-
log << status
|
26
|
-
log << env["REQUEST_URI"]
|
27
|
-
log << DateTime.now.to_s
|
28
|
-
log << env['HTTP_ACCEPT_LANGUAGE'].to_s.scan(/^[a-z]{2}/).first
|
29
|
-
log << env["HTTP_REFERER"]
|
30
|
-
|
31
|
-
File.open(Card::Log::Request.path, "a") do |f|
|
32
|
-
f.write CSV.generate_line(log)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
class Performance
|
41
|
-
# To enable logging add a performance_logger hash to your configuration
|
42
|
-
#
|
43
|
-
# Example:
|
44
|
-
# config.performance_logger = {
|
45
|
-
# :min_time => 100, # show only method calls that are slower than 100ms
|
46
|
-
# :max_depth => 3, # show nested method calls only up to depth 3
|
47
|
-
# :details=> true, # show method arguments and sql
|
48
|
-
# :methods => [:event, :search, :fetch, :view], # choose methods to log
|
49
|
-
# :log_level => :info
|
50
|
-
# }
|
51
|
-
#
|
52
|
-
# If you give :methods a hash you can log arbitrary methods. The syntax is as follows:
|
53
|
-
# class => method type => method name => log options
|
54
|
-
#
|
55
|
-
# Example:
|
56
|
-
# Card => {
|
57
|
-
# :instance => [ :fetch, :search ],
|
58
|
-
# :singleton => { :fetch => { :title => 'Card.fetch' } },
|
59
|
-
# :all => {
|
60
|
-
# :fetch => {
|
61
|
-
# :message => 2 # use second argument passed to fetch
|
62
|
-
# :details => :to_s # use return value of to_s in method context
|
63
|
-
# :title => proc { |method_context| method_context.name }
|
64
|
-
# },
|
65
|
-
# },
|
66
|
-
# },
|
67
|
-
#
|
68
|
-
# class, method type and log options are optional.
|
69
|
-
# Default values are 'Card', ':all' and { :title => method name, :message => first argument, :details=> remaining arguments }.
|
70
|
-
# For example [:fetch] is equivalent to Card => { :all => { :fetch => { :message=>1, :details=>1..-1 } }
|
71
|
-
|
72
|
-
DEFAULT_CLASS = Card
|
73
|
-
DEFAULT_METHOD_TYPE = :all
|
74
|
-
DEFAULT_LOG_LEVEL = :info
|
75
|
-
DEFAULT_METHOD_OPTIONS = {
|
76
|
-
:title => :method_name,
|
77
|
-
:message => 1,
|
78
|
-
:details => 1..-1,
|
79
|
-
:context => nil
|
80
|
-
}
|
81
|
-
|
82
|
-
SPECIAL_METHODS = [:search, :view, :event] # these methods have already a Wagn.with_logging block
|
83
|
-
# we don't have to monkey patch them, only turn the logging on with adding the symbol to the methods hash
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
TAB_SIZE = 3
|
88
|
-
@@log = []
|
89
|
-
@@context_entries = []
|
90
|
-
@@active_entries = []
|
91
|
-
@@current_level = 0
|
92
|
-
|
93
|
-
|
94
|
-
class << self
|
95
|
-
def params_to_config args
|
96
|
-
args[:details] = args[:details] == 'true' ? true : false
|
97
|
-
args[:max_depth] &&= args[:max_depth].to_i
|
98
|
-
args[:min_time] &&= args[:min_time].to_i
|
99
|
-
args[:output] &&= args[:output].to_sym
|
100
|
-
if args[:methods]
|
101
|
-
if args[:methods].kind_of?(String) && args[:methods].match(/^\[.+\]$/)
|
102
|
-
args[:methods] = JSON.parse(args[:methods]).map(&:to_sym)
|
103
|
-
elsif args[:methods].kind_of?(Array)
|
104
|
-
args[:methods].map!(&:to_sym)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
args
|
108
|
-
end
|
109
|
-
|
110
|
-
def load_config args
|
111
|
-
args = params_to_config args
|
112
|
-
@details = args[:details] || false
|
113
|
-
@max_depth = args[:max_depth] || false
|
114
|
-
@min_time = args[:min_time] || false
|
115
|
-
@log_level = args[:log_level] || DEFAULT_LOG_LEVEL
|
116
|
-
@output = args[:output] || :text
|
117
|
-
@enabled_methods = ::Set.new
|
118
|
-
prepare_methods_for_logging args[:methods] if args[:methods]
|
119
|
-
end
|
120
|
-
|
121
|
-
def start args={}
|
122
|
-
@@current_level = 0
|
123
|
-
@@log = []
|
124
|
-
@@context_entries = []
|
125
|
-
@@active_entries = []
|
126
|
-
@@first_entry = new_entry(args)
|
127
|
-
end
|
128
|
-
|
129
|
-
def stop
|
130
|
-
while (entry = @@context_entries.pop) do
|
131
|
-
finish_entry entry
|
132
|
-
end
|
133
|
-
if @@first_entry
|
134
|
-
@@first_entry.save_duration
|
135
|
-
finish_entry @@first_entry
|
136
|
-
end
|
137
|
-
print_log
|
138
|
-
end
|
139
|
-
|
140
|
-
|
141
|
-
def with_timer method, args, &block
|
142
|
-
if args[:context]
|
143
|
-
|
144
|
-
# if the previous context was created by an entry on the same level
|
145
|
-
# then finish the current context if it's a different context
|
146
|
-
if @@context_entries.last && @@current_level == @@context_entries.last.level+1 &&
|
147
|
-
args[:context] != @@context_entries.last.context
|
148
|
-
finish_entry @@context_entries.pop
|
149
|
-
end
|
150
|
-
|
151
|
-
# start new context if it's different from the parent context
|
152
|
-
if @@context_entries.empty? || args[:context] != @@context_entries.last.context
|
153
|
-
@@context_entries << new_entry( :title=>'process', :message=>args[:context], :context=>args[:context] )
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
timer = new_entry args.merge(:method=>method )
|
158
|
-
begin
|
159
|
-
result = block.call
|
160
|
-
ensure
|
161
|
-
timer.save_duration
|
162
|
-
finish_entry timer
|
163
|
-
|
164
|
-
# finish all deeper nested contexts
|
165
|
-
while @@context_entries.last && @@context_entries.last.level >= @@current_level
|
166
|
-
finish_entry @@context_entries.pop
|
167
|
-
end
|
168
|
-
# we don't know whether the next entry will belong to the same context or will start a new one
|
169
|
-
# so we save the time
|
170
|
-
@@context_entries.last.save_duration if @@context_entries.last
|
171
|
-
end
|
172
|
-
result
|
173
|
-
end
|
174
|
-
|
175
|
-
|
176
|
-
def enable_method method_name
|
177
|
-
@enabled_methods ||= ::Set.new
|
178
|
-
@enabled_methods << method_name
|
179
|
-
end
|
180
|
-
|
181
|
-
def enabled_method? method_name
|
182
|
-
@enabled_methods && @enabled_methods.include?(method_name)
|
183
|
-
end
|
184
|
-
|
185
|
-
private
|
186
|
-
|
187
|
-
def print_log
|
188
|
-
if @output == :card && Card[:performance_log]
|
189
|
-
Card[:performance_log].add_log_entry @@log.first.message, html_log
|
190
|
-
elsif @output == :html
|
191
|
-
html_log
|
192
|
-
else
|
193
|
-
text_log
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def text_log
|
198
|
-
@@log.each do |entry|
|
199
|
-
Rails.logger.send @log_level, entry.to_s! if entry.valid
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def html_log
|
204
|
-
@html_log ||= begin
|
205
|
-
list = @@log.inject([]) do |tree, entry|
|
206
|
-
if entry.parent
|
207
|
-
#entry.parent.children << entry
|
208
|
-
else
|
209
|
-
tree << entry
|
210
|
-
end
|
211
|
-
tree
|
212
|
-
end
|
213
|
-
|
214
|
-
list_to_accordion list
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def list_to_accordion list
|
219
|
-
list.map do |entry|
|
220
|
-
if entry.children && entry.children.present?
|
221
|
-
accordion_entry entry
|
222
|
-
else
|
223
|
-
"<li class='list-group-item'>#{simple_entry entry}</li>"
|
224
|
-
end
|
225
|
-
end.join "\n"
|
226
|
-
end
|
227
|
-
|
228
|
-
def simple_entry entry
|
229
|
-
entry.to_html
|
230
|
-
end
|
231
|
-
|
232
|
-
def accordion_entry entry
|
233
|
-
panel_body = list_to_accordion entry.children
|
234
|
-
collapse_id = entry.hash.to_s
|
235
|
-
%{
|
236
|
-
<div class="panel-group" id="accordion-#{collapse_id}" role="tablist" aria-multiselectable="true">
|
237
|
-
<div class="panel panel-default #{'panel-danger' if entry.duration > 100 }">
|
238
|
-
<div class="panel-heading" role="tab" id="heading-#{collapse_id}">
|
239
|
-
<h4 class="panel-title">
|
240
|
-
<a data-toggle="collapse" data-parent="#accordion-#{collapse_id}" href="##{collapse_id}" aria-expanded="true" aria-controls="#{collapse_id}">
|
241
|
-
#{ simple_entry entry }
|
242
|
-
</a>
|
243
|
-
</h4>
|
244
|
-
</div>
|
245
|
-
<div id="#{collapse_id}" class="panel-collapse collapse #{'in' if entry.duration > 100}" role="tabpanel" aria-labelledby="heading-#{collapse_id}">
|
246
|
-
<div class="panel-body">
|
247
|
-
#{ panel_body }
|
248
|
-
</div>
|
249
|
-
</div>
|
250
|
-
</div>
|
251
|
-
</div>
|
252
|
-
}
|
253
|
-
end
|
254
|
-
|
255
|
-
|
256
|
-
def new_entry args
|
257
|
-
args.delete(:details) unless @details
|
258
|
-
level = @@current_level
|
259
|
-
|
260
|
-
last_entry = @@active_entries.last
|
261
|
-
parent = if last_entry
|
262
|
-
last_entry.level == level ? last_entry.parent : last_entry
|
263
|
-
end
|
264
|
-
|
265
|
-
@@log << Card::Log::Performance::Entry.new(parent, level, args )
|
266
|
-
@@current_level += 1
|
267
|
-
@@active_entries << @@log.last
|
268
|
-
|
269
|
-
@@log.last
|
270
|
-
end
|
271
|
-
|
272
|
-
def finish_entry entry
|
273
|
-
if (@max_depth && entry.level > @max_depth) || (@min_time && entry.duration < @min_time)
|
274
|
-
entry.delete
|
275
|
-
end
|
276
|
-
@@active_entries.pop
|
277
|
-
@@current_level -= 1
|
278
|
-
end
|
279
|
-
|
280
|
-
def prepare_methods_for_logging args
|
281
|
-
classes = hashify_and_verify_keys( args, DEFAULT_CLASS ) do |key|
|
282
|
-
key.kind_of?(Class) || key.kind_of?(Module)
|
283
|
-
end
|
284
|
-
|
285
|
-
classes.each do |klass, method_types|
|
286
|
-
klass.extend BigBrother # add watch methods
|
287
|
-
|
288
|
-
method_types = hashify_and_verify_keys( method_types, DEFAULT_METHOD_TYPE ) do |key|
|
289
|
-
[:all, :instance, :singleton].include? key
|
290
|
-
end
|
291
|
-
|
292
|
-
method_types.each do |method_type, methods|
|
293
|
-
methods = hashify_and_verify_keys methods
|
294
|
-
methods.each do |method_name, options|
|
295
|
-
klass.watch_method method_name, method_type, DEFAULT_METHOD_OPTIONS.merge(options)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
|
303
|
-
def hashify_and_verify_keys args, default_key=nil
|
304
|
-
if default_key
|
305
|
-
case args
|
306
|
-
when Symbol
|
307
|
-
{ default_key => [ args ] }
|
308
|
-
when Array
|
309
|
-
{ default_key => args }
|
310
|
-
when Hash
|
311
|
-
if block_given?
|
312
|
-
args.keys.select{ |key| !(yield(key)) }.each do |key|
|
313
|
-
args[default_key] = { key => args[key] }
|
314
|
-
args.delete key
|
315
|
-
end
|
316
|
-
end
|
317
|
-
args
|
318
|
-
end
|
319
|
-
else
|
320
|
-
case args
|
321
|
-
when Symbol
|
322
|
-
{ args => {} }
|
323
|
-
when Array
|
324
|
-
args.inject({}) do |h, key|
|
325
|
-
h[key] = {}
|
326
|
-
h
|
327
|
-
end
|
328
|
-
else
|
329
|
-
args
|
330
|
-
end
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
end
|
335
|
-
|
336
|
-
|
337
|
-
class Entry
|
338
|
-
attr_accessor :level, :valid, :context, :parent, :children_cnt, :duration, :children
|
339
|
-
attr_reader :message
|
340
|
-
|
341
|
-
def initialize( parent, level, args )
|
342
|
-
@start = Time.new
|
343
|
-
@message = "#{ args[:title] || args[:method] || '' }"
|
344
|
-
@message += ": #{ args[:message] }" if args[:message]
|
345
|
-
@details = args[:details]
|
346
|
-
@context = args[:context]
|
347
|
-
@level = level
|
348
|
-
@duration = nil
|
349
|
-
@valid = true
|
350
|
-
@parent = parent
|
351
|
-
@children_cnt = 0
|
352
|
-
@children = []
|
353
|
-
if @parent
|
354
|
-
@parent.add_children self
|
355
|
-
#@sibling_nr = @parent.children_cnt
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
def add_children child=false
|
360
|
-
@children_cnt += 1
|
361
|
-
@children << child if child
|
362
|
-
end
|
363
|
-
|
364
|
-
def delete_children child=false
|
365
|
-
@children_cnt -= 1
|
366
|
-
@children.delete child if child
|
367
|
-
|
368
|
-
end
|
369
|
-
|
370
|
-
def has_younger_siblings?
|
371
|
-
@parent && @parent.children_cnt > 0 #@sibling_nr
|
372
|
-
end
|
373
|
-
|
374
|
-
def save_duration
|
375
|
-
@duration = (Time.now - @start) * 1000
|
376
|
-
end
|
377
|
-
|
378
|
-
def delete
|
379
|
-
@valid = false
|
380
|
-
@parent.delete_children(self) if @parent
|
381
|
-
end
|
382
|
-
|
383
|
-
|
384
|
-
# deletes the children counts in order to print the tree;
|
385
|
-
# must be called in the right order
|
386
|
-
#
|
387
|
-
# More robuts but more expensive approach: use @sibling_nr instead of counting @children_cnt down,
|
388
|
-
# but @sibling_nr has to be updated for all siblings of an entry if the entry gets deleted due to
|
389
|
-
# min_time or max_depth restrictions in the config, so we have to save all children relations for that
|
390
|
-
def to_s!
|
391
|
-
@to_s ||= begin
|
392
|
-
msg = indent
|
393
|
-
msg += "(%d.2ms) " % @duration if @duration
|
394
|
-
msg += @message if @message
|
395
|
-
|
396
|
-
if @details
|
397
|
-
msg += ", " + @details.to_s.gsub( "\n", "\n#{ indent(false) }#{' '* TAB_SIZE}" )
|
398
|
-
end
|
399
|
-
@parent.delete_children if @parent
|
400
|
-
msg
|
401
|
-
end
|
402
|
-
end
|
403
|
-
def to_html
|
404
|
-
@to_html ||= begin
|
405
|
-
msg = "<span title='#{@details}'>"
|
406
|
-
msg += @message if @message
|
407
|
-
msg += "<span class='badge #{"badge-danger" if @duration > 100}'> %d.2ms </span>" % @duration if @duration
|
408
|
-
msg += '</span>'
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
private
|
413
|
-
|
414
|
-
def indent link=true
|
415
|
-
@indent ||= begin
|
416
|
-
if @level == 0
|
417
|
-
"\n"
|
418
|
-
else
|
419
|
-
res = ' '
|
420
|
-
res += (1..level-1).inject('') do |msg, index|
|
421
|
-
if younger_siblings[index]
|
422
|
-
msg << '|' + ' ' * (TAB_SIZE-1)
|
423
|
-
else
|
424
|
-
msg << ' ' * TAB_SIZE
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
res += link ? '|--' : ' '
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
def younger_siblings
|
434
|
-
res = []
|
435
|
-
next_parent = self
|
436
|
-
while (next_parent)
|
437
|
-
res << next_parent.has_younger_siblings?
|
438
|
-
next_parent = next_parent.parent
|
439
|
-
end
|
440
|
-
res.reverse
|
441
|
-
end
|
442
|
-
|
443
|
-
end
|
444
|
-
|
445
|
-
|
446
|
-
module BigBrother
|
447
|
-
|
448
|
-
def watch_method method_name, method_type=:all, options={}
|
449
|
-
Card::Log::Performance.enable_method method_name
|
450
|
-
|
451
|
-
if !SPECIAL_METHODS.include? method_name
|
452
|
-
if method_type == :all || method_type == :singleton
|
453
|
-
add_singleton_logging method_name, options
|
454
|
-
end
|
455
|
-
if method_type == :all || method_type == :instance
|
456
|
-
add_instance_logging method_name, options
|
457
|
-
end
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
def watch_instance_method *names
|
462
|
-
names.each do |name|
|
463
|
-
watch_method name, :instance
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
def watch_singleton_method *names
|
468
|
-
names.each do |name|
|
469
|
-
watch_method name, :singleton
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
|
-
def watch_all_instance_methods
|
474
|
-
watch_instance_method *instance_methods
|
475
|
-
end
|
476
|
-
|
477
|
-
def watch_all_singleton_methods
|
478
|
-
fragile_methods = [:default_scope, :default_scopes, :default_scopes=] # if I touch these methods ActiveRecord breaks
|
479
|
-
watch_singleton_method *(singleton_methods - fragile_methods)
|
480
|
-
end
|
481
|
-
|
482
|
-
def watch_all_methods
|
483
|
-
watch_all_instance_methods
|
484
|
-
watch_all_singleton_methods
|
485
|
-
end
|
486
|
-
|
487
|
-
private
|
488
|
-
|
489
|
-
def add_singleton_logging method_name, options
|
490
|
-
return unless singleton_class.method_defined? method_name
|
491
|
-
m = method(method_name)
|
492
|
-
add_logging method_name, :define_singleton_method, options do |bind_object, args, &block|
|
493
|
-
m.call(*args, &block)
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
def add_instance_logging method_name, options
|
498
|
-
return unless method_defined? method_name
|
499
|
-
m = instance_method(method_name)
|
500
|
-
add_logging method_name, :define_method, options do |bind_object, args, &block|
|
501
|
-
m.bind(bind_object).(*args, &block)
|
502
|
-
end
|
503
|
-
end
|
504
|
-
|
505
|
-
def add_logging method_name, define_method, options, &bind_block
|
506
|
-
send(define_method, method_name) do |*args, &block|
|
507
|
-
log_args = {}
|
508
|
-
options.each do |key,value|
|
509
|
-
log_args[key] = case value
|
510
|
-
when Integer then args[value-1]
|
511
|
-
when Range then args[value]
|
512
|
-
when Symbol then eval(value.to_s)
|
513
|
-
when Proc then value.call(self)
|
514
|
-
else value
|
515
|
-
end
|
516
|
-
end
|
517
|
-
Card::Log::Performance.with_timer(method_name, log_args) do
|
518
|
-
bind_block.call(self, args, &block)
|
519
|
-
end
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
def log_options_variable_name method_name, define_method
|
524
|
-
"@_#{self.class.name}_#{method_name.hash.to_s.sub(/^-/,'_')}_#{define_method}_logging_options".to_sym
|
525
|
-
end
|
526
|
-
|
527
|
-
end
|
528
|
-
|
529
|
-
|
530
|
-
end
|
531
|
-
|
532
|
-
end
|
533
|
-
|
534
|
-
class Card
|
535
|
-
def self.with_logging method, opts, &block
|
536
|
-
if Card::Log::Performance.enabled_method? method
|
537
|
-
Card::Log::Performance.with_timer(method, opts) do
|
538
|
-
block.call
|
539
|
-
end
|
540
|
-
else
|
541
|
-
block.call
|
542
|
-
end
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|