Dex 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -1,3 +1,3 @@
1
1
  class Dex
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -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 == "One"
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
- 300.times { |i| Dex.insert except(i.to_s) }
150
- Dex.keep_only
151
- Dex.count.should == 250
152
- Dex.recent(1)[:message].should == '299'
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
- 300.times { |i| Dex.insert except(i.to_s) }
157
- Dex.keep_only 12
158
- Dex.table.count.should == 12
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
@@ -1,13 +1,100 @@
1
1
 
2
2
  bins = Dir.glob("bin/*")
3
3
 
4
- unless bins.empty?
5
- describe "permissions of bin/" do
6
- bins.each { |file|
7
- it "should chmod 755 for: #{file}" do
8
- `stat -c %a #{file}`.strip
9
- .should.be == "755"
10
- end
11
- }
12
- end # === permissions of bin/
13
- end # === unless bins.empty?
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
+
@@ -20,7 +20,11 @@ require 'pry'
20
20
  require 'Exit_0'
21
21
  require 'Dex'
22
22
 
23
- Dex.db ":memory:"
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
- raise name
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 dex
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.3.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-08 00:00:00.000000000 Z
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