Dex 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Dex.gemspec +4 -0
- data/bin/Dex +155 -0
- data/lib/Dex/version.rb +1 -1
- data/spec/Dex.rb +12 -8
- data/spec/bin.rb +97 -10
- data/spec/libs/main.rb +40 -5
- metadata +69 -3
data/Dex.gemspec
CHANGED
@@ -29,5 +29,9 @@ Gem::Specification.new do |s|
|
|
29
29
|
# Specify any dependencies here; for example:
|
30
30
|
s.add_runtime_dependency 'sqlite3'
|
31
31
|
s.add_runtime_dependency 'sequel'
|
32
|
+
s.add_runtime_dependency 'terminal-table'
|
33
|
+
s.add_runtime_dependency 'chronic_duration'
|
34
|
+
s.add_runtime_dependency 'trollop'
|
35
|
+
s.add_runtime_dependency 'term-ansicolor'
|
32
36
|
|
33
37
|
end
|
data/bin/Dex
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
#
|
4
|
+
|
5
|
+
require "Dex"
|
6
|
+
require 'terminal-table'
|
7
|
+
require 'chronic_duration'
|
8
|
+
require 'trollop'
|
9
|
+
require 'term/ansicolor'
|
10
|
+
include Term::ANSIColor
|
11
|
+
|
12
|
+
module Kernal
|
13
|
+
private
|
14
|
+
|
15
|
+
end # === Kernal
|
16
|
+
|
17
|
+
SUB_COMMANDS = %w{ filter toggle show info delete }
|
18
|
+
STATUS = %w{ r unr both }
|
19
|
+
opts = Trollop::options do
|
20
|
+
opt :db, "Path to database file.", :default=>Dex.default(:db_name).to_s
|
21
|
+
opt :table, "DB table.", :default=>Dex.default(:table_name).to_s
|
22
|
+
opt :action, "Must be in: #{SUB_COMMANDS.join ', '}", :default=>'filter'
|
23
|
+
opt :reverse_order, "Field to reverse order.", :default=>'created_at'
|
24
|
+
opt :limit, "DB limit", :type=>:int
|
25
|
+
opt :offset, "DB limit. If specified, default limit is 1.", :type=>:int
|
26
|
+
opt :status, "Either: #{STATUS.join ', '}", :default=>'unr'
|
27
|
+
opt :toggle, "Equivalent to: --action toggle --offset N", :type=>:int
|
28
|
+
opt :show, "Equivalent to: --action show --offset N", :type=>:int
|
29
|
+
opt :delete, "Equivalent to: --action delete --offset N", :type=>:int
|
30
|
+
opt :backtrace, "Show backtrace. Used for --show. Ignored otherwise." , :default=>false
|
31
|
+
end
|
32
|
+
|
33
|
+
[:toggle, :show, :delete].each { |k|
|
34
|
+
if opts[k]
|
35
|
+
opts[:action] = k.to_s
|
36
|
+
opts[:offset] = opts[k]
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
Trollop::die :status, "must be either: #{STATUS.join ', '}" unless STATUS.include?(opts[:status])
|
42
|
+
Trollop::die :action, "must be either: #{SUB_COMMANDS.join ', '}." unless SUB_COMMANDS.include?(opts[:action])
|
43
|
+
Trollop::die "Unknown options: #{ARGV.inspect}" unless ARGV.empty?
|
44
|
+
|
45
|
+
Dex.db opts[:db], opts[:table]
|
46
|
+
OPTS = opts.dup
|
47
|
+
OPTS.update :ds=> Dex.table
|
48
|
+
|
49
|
+
OPTS[:status]=[0,1] if OPTS[:status]=='both'
|
50
|
+
OPTS[:status]=0 if OPTS[:status]=='unr'
|
51
|
+
OPTS[:status]=1 if OPTS[:status]=='r'
|
52
|
+
(OPTS[:limit] ||=1) if OPTS[:offset]
|
53
|
+
|
54
|
+
def raise_arg v
|
55
|
+
raise ArgumentError, (v.is_a?(Symbol) ? "Unknown argument: #{v.inspect}": v)
|
56
|
+
end
|
57
|
+
|
58
|
+
puts ''
|
59
|
+
|
60
|
+
case OPTS[:action]
|
61
|
+
when 'filter'
|
62
|
+
|
63
|
+
ds = OPTS[:ds].filter( :status=>OPTS[:status] ).reverse_order(OPTS[:reverse_order])
|
64
|
+
|
65
|
+
if OPTS[:limit] || OPTS[:offset]
|
66
|
+
ds = ds.limit(*[OPTS[:limit] || ds.count + 1, OPTS[:offset]].compact)
|
67
|
+
end
|
68
|
+
|
69
|
+
results = []
|
70
|
+
ds_results = ds.to_a
|
71
|
+
ds_results.each_index { |i|
|
72
|
+
h = ds_results[i]
|
73
|
+
offset = ds_results.size - i - 1
|
74
|
+
results << [
|
75
|
+
offset,
|
76
|
+
h[:exception],
|
77
|
+
h[:message],
|
78
|
+
ChronicDuration.output(Time.now.to_i - h[:created_at].to_i, :format=>:short) + " ago",
|
79
|
+
h[:id]
|
80
|
+
]
|
81
|
+
}
|
82
|
+
|
83
|
+
if results.empty?
|
84
|
+
puts "No unresolved exceptions."
|
85
|
+
else
|
86
|
+
puts Terminal::Table.new(:headings=>%w{-o Exception Message Time ID}, :rows=> results)
|
87
|
+
end
|
88
|
+
|
89
|
+
when :toggle.to_s
|
90
|
+
Trollop::die :offset, "must be specified" unless OPTS[:offset]
|
91
|
+
|
92
|
+
r = OPTS[:ds].filter(:status=>OPTS[:status]).order(OPTS[:reverse_order]).limit( 1, OPTS[:offset] ).first
|
93
|
+
|
94
|
+
raise_arg "Record not found." unless r
|
95
|
+
stat = r[:status] == 0 ? 1 : 0
|
96
|
+
OPTS[:ds].filter(:id=>r[:id]).update(:status=>stat)
|
97
|
+
puts "#{r[:id]} => #{stat}"
|
98
|
+
|
99
|
+
when 'delete'
|
100
|
+
r = OPTS[:ds].filter(:status=>OPTS[:status]).reverse_order(OPTS[:reverse_order]).limit( 1, OPTS[:offset]).first
|
101
|
+
Trollop::die "No record found with offset: #{OPTS[:offset]}" unless r
|
102
|
+
OPTS[:ds].filter(:id=>r[:id]).delete
|
103
|
+
puts "Record (id: #{r[:id]}) with offset #{OPTS[:offset]} has been deleted."
|
104
|
+
|
105
|
+
when 'show'
|
106
|
+
r = OPTS[:ds].filter(:status=>OPTS[:status]).reverse_order(OPTS[:reverse_order]).limit( 1, OPTS[:offset]).first
|
107
|
+
raise_args "Record not found with offset: #{OPTS[:offset]}" unless r
|
108
|
+
|
109
|
+
b = r.delete :backtrace
|
110
|
+
|
111
|
+
puts Terminal::Table.new(:rows=>r.to_a)
|
112
|
+
|
113
|
+
if OPTS[:backtrace]
|
114
|
+
puts "Backtrace:"
|
115
|
+
current_line = nil
|
116
|
+
rows = []
|
117
|
+
b.each_line { |l|
|
118
|
+
pieces = l.split(%r!:(\d+):!)
|
119
|
+
line = pieces.shift
|
120
|
+
num = pieces.shift
|
121
|
+
code = pieces.join("")
|
122
|
+
|
123
|
+
if current_line != line
|
124
|
+
rows << [line]
|
125
|
+
current_line = line
|
126
|
+
puts ''
|
127
|
+
puts bold(line.sub(Dir.pwd, '.').sub(File.expand_path('~'), '~'))
|
128
|
+
end
|
129
|
+
|
130
|
+
rows << [num, code]
|
131
|
+
|
132
|
+
puts "#{yellow "#{num}:"} #{code}"
|
133
|
+
}
|
134
|
+
|
135
|
+
puts
|
136
|
+
end
|
137
|
+
|
138
|
+
when 'info'
|
139
|
+
t = [
|
140
|
+
[ :db_name, Dex.db_name ],
|
141
|
+
[ :table_name, Dex.table_name ],
|
142
|
+
[ 'Total:', Dex.count ],
|
143
|
+
[ 'Unresolved:', Dex.filter(:status=>0).count ],
|
144
|
+
[ 'Resolved:' , Dex.filter(:status=>1).count ]
|
145
|
+
]
|
146
|
+
puts Terminal::Table.new(:rows=>t)
|
147
|
+
|
148
|
+
else
|
149
|
+
raise_arg "Unknown action: #{OPTS[:action]}"
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
data/lib/Dex/version.rb
CHANGED
data/spec/Dex.rb
CHANGED
@@ -48,7 +48,7 @@ describe "Dex :recent" do
|
|
48
48
|
it "returns first result if n = 1" do
|
49
49
|
e = except "One"
|
50
50
|
Dex.insert e
|
51
|
-
Dex.recent( 1 )[:message].should ==
|
51
|
+
Dex.recent( 1 )[:message].should == e.message
|
52
52
|
end
|
53
53
|
|
54
54
|
it "returns a dataset if n > 1" do
|
@@ -146,16 +146,20 @@ describe "Dex :keep_only" do
|
|
146
146
|
behaves_like 'Test DB'
|
147
147
|
|
148
148
|
it "deletes oldest records leaving most recent 250" do
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
rollback {
|
150
|
+
300.times { |i| Dex.insert except(i.to_s) }
|
151
|
+
Dex.keep_only
|
152
|
+
Dex.count.should == 250
|
153
|
+
Dex.recent(1)[:message].should == '299'
|
154
|
+
}
|
153
155
|
end
|
154
156
|
|
155
157
|
it "accepts a limit argument" do
|
156
|
-
|
157
|
-
|
158
|
-
|
158
|
+
rollback {
|
159
|
+
300.times { |i| Dex.insert except(i.to_s) }
|
160
|
+
Dex.keep_only 12
|
161
|
+
Dex.table.count.should == 12
|
162
|
+
}
|
159
163
|
end
|
160
164
|
|
161
165
|
end # === Dex :keep_only
|
data/spec/bin.rb
CHANGED
@@ -1,13 +1,100 @@
|
|
1
1
|
|
2
2
|
bins = Dir.glob("bin/*")
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
describe "permissions of bin/" do
|
5
|
+
bins.each { |file|
|
6
|
+
it "should chmod 775 for: #{file}" do
|
7
|
+
`stat -c %a #{file}`.strip
|
8
|
+
.should.be == "775"
|
9
|
+
end
|
10
|
+
}
|
11
|
+
end # === permissions of bin/
|
12
|
+
|
13
|
+
|
14
|
+
describe "Dex" do
|
15
|
+
|
16
|
+
it "lists unresolved exceptions" do
|
17
|
+
rollback! do
|
18
|
+
errs = [0,1,2].map { |i|
|
19
|
+
e = except
|
20
|
+
Dex.insert e
|
21
|
+
e
|
22
|
+
}
|
23
|
+
|
24
|
+
o = bin
|
25
|
+
errs.each { |e|
|
26
|
+
o.should.match %r!#{e.exception}!
|
27
|
+
o.should.match %r!#{e.message}!
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "puts a menu number in reversed order" do
|
33
|
+
insert_excepts(3) { |ids, errs|
|
34
|
+
bin.scan( %r!^\|\ +(\d)\ +\|!).flatten
|
35
|
+
.should == %w( 2 1 0)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not list resolved exceptions" do
|
40
|
+
rollback! do
|
41
|
+
|
42
|
+
errs = [0,1,2].map { |i|
|
43
|
+
Dex.insert except, :status => 1
|
44
|
+
}
|
45
|
+
|
46
|
+
bin().should == 'No unresolved exceptions.'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end # === dex NAME
|
52
|
+
|
53
|
+
describe "Dex toggle N" do
|
54
|
+
|
55
|
+
it "toggles Nth exception from the bottom" do
|
56
|
+
rollback! do
|
57
|
+
errs = [1,2,3].map { |i| Dex.insert( e = except, :created_at=>Time.parse("2012/0#{i}/0#{i} 01:01:01") ) && e }
|
58
|
+
|
59
|
+
bin "--toggle 0"
|
60
|
+
|
61
|
+
Dex.select(:status).reverse_order(:created_at).to_a.map { |r| r[:status] }
|
62
|
+
.should == [0 , 0 , 1]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end # === dex toggle N
|
67
|
+
|
68
|
+
|
69
|
+
describe "Dex --show N" do
|
70
|
+
|
71
|
+
it "displays a single exception" do
|
72
|
+
rollback! do
|
73
|
+
errs = [0,1,2,3].map { |i| Dex.insert(e=except); e }
|
74
|
+
o = bin "--show 1"
|
75
|
+
o.should.match %r!#{Regexp.escape errs[1].message}!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it "displays a backtrace with arg: --backtrace" do
|
80
|
+
insert_excepts(4) do |ids, errs|
|
81
|
+
o = bin "--show 1 --backtrace"
|
82
|
+
o.should.match %r!#{Regexp.escape errs[1].backtrace[2].split(':').first.sub(File.expand_path( '.', ''), '')}!
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end # === Dex --show N
|
87
|
+
|
88
|
+
describe "Dex --delete N" do
|
89
|
+
|
90
|
+
it "deletes exception from database" do
|
91
|
+
rollback! do
|
92
|
+
ids = []
|
93
|
+
errs = [0,1,2,3].map { |i| ids << Dex.insert(e=except); e }
|
94
|
+
o = bin "--delete 1"
|
95
|
+
o.should == "Record (id: #{ids[1]}) with offset 1 has been deleted."
|
96
|
+
Dex.filter(:id=>ids[1]).first.should.be == nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end # === Dex --delete N
|
100
|
+
|
data/spec/libs/main.rb
CHANGED
@@ -20,7 +20,11 @@ require 'pry'
|
|
20
20
|
require 'Exit_0'
|
21
21
|
require 'Dex'
|
22
22
|
|
23
|
-
Dex.db "
|
23
|
+
Dex.db "/tmp/dex.db"
|
24
|
+
|
25
|
+
def dex
|
26
|
+
Dex
|
27
|
+
end
|
24
28
|
|
25
29
|
def new_dex db = nil
|
26
30
|
@t ||= Class.new { include Dex::DSL }
|
@@ -32,22 +36,53 @@ def new_dex db = nil
|
|
32
36
|
dex
|
33
37
|
end
|
34
38
|
|
35
|
-
def except name
|
39
|
+
def except name = nil
|
40
|
+
@counter ||= 0
|
41
|
+
name ||= "Error: #{(@counter+=1)}"
|
36
42
|
err = nil
|
37
43
|
begin
|
38
|
-
|
44
|
+
raise ArgumentError, name
|
39
45
|
rescue Object => e
|
40
46
|
err = e
|
41
47
|
end
|
42
48
|
err
|
43
49
|
end
|
44
50
|
|
45
|
-
def rollback
|
46
|
-
dex.db.transaction(:rollback=>:always) {
|
51
|
+
def rollback sequel = nil
|
52
|
+
(sequel || dex).db.transaction(:rollback=>:always) {
|
47
53
|
yield
|
48
54
|
}
|
49
55
|
end
|
50
56
|
|
57
|
+
def rollback!
|
58
|
+
# Dex.db.rollback(:rollback=>:always) {
|
59
|
+
dex.table.delete
|
60
|
+
yield
|
61
|
+
end
|
62
|
+
|
63
|
+
def bin cmd = ""
|
64
|
+
bin_path = File.expand_path(File.dirname(__FILE__) + '/../../bin/Dex')
|
65
|
+
bin_path = "Dex"
|
66
|
+
|
67
|
+
o = `#{bin_path} --db #{dex.db_name} #{cmd} 2>&1`.strip
|
68
|
+
|
69
|
+
if $?.exitstatus != 0
|
70
|
+
raise o
|
71
|
+
end
|
72
|
+
o
|
73
|
+
end
|
74
|
+
|
75
|
+
def insert_excepts n
|
76
|
+
rollback! {
|
77
|
+
ids = []
|
78
|
+
errs = [0,1,2].map { |i|
|
79
|
+
ids << Dex.insert(e=except)
|
80
|
+
e
|
81
|
+
}
|
82
|
+
yield ids, errs
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
51
86
|
def last dex
|
52
87
|
dex.reverse_order(:id).limit(1).first
|
53
88
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Dex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bacon
|
@@ -123,10 +123,75 @@ dependencies:
|
|
123
123
|
- - ! '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: terminal-table
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: chronic_duration
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :runtime
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: trollop
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :runtime
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: term-ansicolor
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :runtime
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
126
190
|
description: ! "\n A simple function to log errors to sqlite3.\n "
|
127
191
|
email:
|
128
192
|
- i-hate-spam-45671204@mailinator.com
|
129
|
-
executables:
|
193
|
+
executables:
|
194
|
+
- Dex
|
130
195
|
extensions: []
|
131
196
|
extra_rdoc_files: []
|
132
197
|
files:
|
@@ -135,6 +200,7 @@ files:
|
|
135
200
|
- Gemfile
|
136
201
|
- README.md
|
137
202
|
- Rakefile
|
203
|
+
- bin/Dex
|
138
204
|
- db.db
|
139
205
|
- lib/Dex.rb
|
140
206
|
- lib/Dex/version.rb
|