mdb 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/lib/mdb.rb +3 -3
- data/lib/mdb/database.rb +70 -66
- data/lib/mdb/version.rb +1 -1
- data/mdb.gemspec +1 -1
- data/test/data/Example2000.mdb +0 -0
- data/test/data/Example2003.mdb +0 -0
- data/test/database_test.rb +37 -24
- metadata +23 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55c6c7c1cdcb9921dfebf67418cd17e2fdac1bb1
|
4
|
+
data.tar.gz: ddc03a93b64636f6db253f639e49030429864c11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b456701c7e7d5868ffe856f5b3330a551d357e52b63e902b40f903dcdf64f0fdcbba8c0a5a0c62695164ff050dbb5cb8f32c4873d3340e8caf7dfba1ed7ae8f
|
7
|
+
data.tar.gz: 6186198dc546f16abea449e60e384e941be21339174c655b467e7e9df609062a1376296f5be7610c74b058e354151caf0a9e70767d75d0974d7ebd8299edbf3c
|
data/README.md
CHANGED
@@ -31,6 +31,14 @@ database.tables
|
|
31
31
|
database[:Movies]
|
32
32
|
```
|
33
33
|
|
34
|
+
## Heroku
|
35
|
+
|
36
|
+
mdb-tools on heroku requires a custom buildpack.
|
37
|
+
|
38
|
+
Here is a sample project using this gem on heroku with configuration instructions:
|
39
|
+
|
40
|
+
https://github.com/jkotchoff/heroku_rails_microsoft_access_mdb_example
|
41
|
+
|
34
42
|
## Contributing
|
35
43
|
|
36
44
|
1. Fork it
|
data/lib/mdb.rb
CHANGED
@@ -2,7 +2,7 @@ require "mdb/version"
|
|
2
2
|
require "mdb/database"
|
3
3
|
|
4
4
|
module Mdb
|
5
|
-
|
5
|
+
|
6
6
|
class FileDoesNotExistError < ArgumentError; end
|
7
7
|
class TableDoesNotExistError < ArgumentError; end
|
8
8
|
class MdbToolsNotInstalledError < ArgumentError
|
@@ -11,9 +11,9 @@ module Mdb
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
class Error < RuntimeError; end
|
14
|
-
|
14
|
+
|
15
15
|
def self.open(file)
|
16
16
|
Mdb::Database.new(file)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
end
|
data/lib/mdb/database.rb
CHANGED
@@ -1,48 +1,54 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'csv'
|
1
|
+
require "tempfile"
|
2
|
+
require "shellwords"
|
3
|
+
require "csv"
|
5
4
|
|
6
5
|
|
7
6
|
module Mdb
|
8
7
|
class Database
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
|
9
|
+
|
10
|
+
|
12
11
|
def initialize(file, options={})
|
13
12
|
file = file.to_path if file.respond_to?(:to_path)
|
14
13
|
raise FileDoesNotExistError, "\"#{file}\" does not exist" unless File.exist?(file)
|
15
|
-
|
14
|
+
|
16
15
|
@file = file
|
17
|
-
@delimiter = options.fetch :delimiter,
|
16
|
+
@delimiter = options.fetch :delimiter, "|"
|
18
17
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
|
19
|
+
|
20
|
+
|
22
21
|
attr_reader :file, :delimiter
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
|
23
|
+
|
24
|
+
|
26
25
|
def tables
|
27
26
|
@tables ||= execute("mdb-tables -1 #{file_name}").scan(/[^\n]+/)
|
28
27
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
|
29
|
+
|
30
|
+
|
32
31
|
def columns(table)
|
33
|
-
open_csv(table)
|
32
|
+
open_csv(table) do |csv|
|
33
|
+
line = csv.readline
|
34
|
+
unless line || tables.member?(table.to_s)
|
35
|
+
raise TableDoesNotExistError, "#{table.inspect} does not exist in #{file_name.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
(line || []).map(&:to_sym)
|
39
|
+
end
|
34
40
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
|
42
|
+
|
43
|
+
|
38
44
|
def read_csv(table)
|
39
|
-
csv = execute "mdb-export -D '%F %T' -d \\| #{file_name} #{table}"
|
45
|
+
csv = execute "mdb-export -D '%F %T' -d \\| #{file_name} #{Shellwords.escape(table)}"
|
40
46
|
empty_table!(table) if csv.empty?
|
41
47
|
csv
|
42
48
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
49
|
+
|
50
|
+
|
51
|
+
|
46
52
|
# Yields a hash for each record
|
47
53
|
def each_record(table, &block)
|
48
54
|
columns = nil
|
@@ -55,9 +61,9 @@ module Mdb
|
|
55
61
|
end
|
56
62
|
end
|
57
63
|
alias :each :each_record
|
58
|
-
|
59
|
-
|
60
|
-
|
64
|
+
|
65
|
+
|
66
|
+
|
61
67
|
# Returns an array of hashes. Each hash represents a record
|
62
68
|
def read_records(table)
|
63
69
|
hashes = []
|
@@ -66,66 +72,64 @@ module Mdb
|
|
66
72
|
end
|
67
73
|
alias :read :read_records
|
68
74
|
alias :[] :read_records
|
69
|
-
|
70
|
-
|
71
|
-
|
75
|
+
|
76
|
+
|
77
|
+
|
72
78
|
private
|
73
|
-
|
74
|
-
|
75
|
-
|
79
|
+
|
80
|
+
|
81
|
+
|
76
82
|
def read_each(table, &block)
|
77
83
|
count = 0
|
78
|
-
|
84
|
+
|
79
85
|
open_csv(table) do |csv|
|
80
86
|
while line = csv.readline
|
81
87
|
yield line
|
82
88
|
count += 1
|
83
89
|
end
|
84
90
|
end
|
85
|
-
|
91
|
+
|
86
92
|
empty_table!(table) if count == 0
|
87
|
-
|
93
|
+
|
88
94
|
count
|
89
95
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
96
|
+
|
97
|
+
|
98
|
+
|
93
99
|
def empty_table!(table)
|
94
|
-
raise MdbToolsNotInstalledError
|
100
|
+
raise MdbToolsNotInstalledError unless system("which mdb-export")
|
95
101
|
raise TableDoesNotExistError, "#{table.inspect} does not exist in #{file_name.inspect}" if !tables.member?(table.to_s)
|
96
102
|
raise Error, "An error occurred when reading #{table.inspect} in #{file_name.inspect}"
|
97
103
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
104
|
+
|
105
|
+
|
106
|
+
|
101
107
|
def file_name
|
102
108
|
Shellwords.escape(file)
|
103
109
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
110
|
+
|
111
|
+
|
112
|
+
|
107
113
|
def open_csv(table)
|
108
|
-
command = "mdb-export -D '%F %T' -d #{Shellwords.escape(delimiter)} #{file_name} #{table}"
|
109
|
-
|
110
|
-
yield CSV.new(
|
114
|
+
command = "mdb-export -D '%F %T' -d #{Shellwords.escape(delimiter)} #{file_name} #{Shellwords.escape(table)}"
|
115
|
+
execute(command) do |file|
|
116
|
+
yield CSV.new(file, col_sep: delimiter)
|
111
117
|
end
|
112
118
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
119
|
+
|
120
|
+
|
121
|
+
|
116
122
|
def execute(command)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
stdout
|
123
|
+
file = Tempfile.new("mdb")
|
124
|
+
system "#{command} > #{file.path} 2> /dev/null"
|
125
|
+
return file.read unless block_given?
|
126
|
+
yield file
|
127
|
+
ensure
|
128
|
+
file.close
|
129
|
+
file.unlink
|
126
130
|
end
|
127
|
-
|
128
|
-
|
129
|
-
|
131
|
+
|
132
|
+
|
133
|
+
|
130
134
|
end
|
131
135
|
end
|
data/lib/mdb/version.rb
CHANGED
data/mdb.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "rails", ">= 3.2.0"
|
23
|
+
spec.add_development_dependency "rails", ">= 3.2.0", "< 4.1.0"
|
24
24
|
spec.add_development_dependency "turn"
|
25
25
|
spec.add_development_dependency "pry"
|
26
26
|
end
|
data/test/data/Example2000.mdb
CHANGED
Binary file
|
data/test/data/Example2003.mdb
CHANGED
Binary file
|
data/test/database_test.rb
CHANGED
@@ -1,37 +1,37 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class MdbTest < ActiveSupport::TestCase
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
|
6
6
|
{ "Access 2000" => "Example2000.mdb",
|
7
7
|
"Acesss 2003" => "Example2003.mdb" }.each do |format, file|
|
8
8
|
path = "#{File.dirname(__FILE__)}/data/#{file}"
|
9
|
-
|
9
|
+
|
10
10
|
test "should identify three tables in #{file} (#{format})" do
|
11
11
|
database = Mdb.open(path)
|
12
12
|
assert_equal %w{Actors EmptyTable Movies}, database.tables.sort
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
test "should find all the rows in each table (#{format})" do
|
16
16
|
database = Mdb.open(path)
|
17
|
-
|
17
|
+
|
18
18
|
expected_counts = {
|
19
|
-
:Actors =>
|
19
|
+
:Actors => 5,
|
20
20
|
:Movies => 7 }
|
21
21
|
expected_counts.each do |table, expected_count|
|
22
22
|
assert_equal expected_count, database[table].count, "The count of '#{table}' is off"
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
|
27
|
+
|
28
|
+
|
29
29
|
test "should raise an exception when instatiated with a missing database" do
|
30
30
|
assert_raises(Mdb::FileDoesNotExistError) do
|
31
31
|
Mdb.open "#{File.dirname(__FILE__)}/data/nope.mdb"
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
test "should raise an exception when mdb-tools is not installed" do
|
36
36
|
assert_raises(Mdb::MdbToolsNotInstalledError) do
|
37
37
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
@@ -40,44 +40,57 @@ class MdbTest < ActiveSupport::TestCase
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
test "should raise an exception if a table is not found" do
|
45
45
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
46
46
|
assert_raises(Mdb::TableDoesNotExistError) do
|
47
47
|
database.read :Villains
|
48
48
|
end
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
test "should return an empty array if a table is empty" do
|
52
52
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
53
53
|
assert_equal [], database.read(:EmptyTable)
|
54
54
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
|
56
|
+
|
57
|
+
|
58
58
|
test "should return an array of columns for at able" do
|
59
59
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
60
60
|
assert_equal [:ID, :FirstName, :LastName, :Birthdate], database.columns(:Actors)
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
|
+
test "should raise an exception if asked for the columns of a nonexistent table" do
|
64
|
+
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
65
|
+
assert_raises(Mdb::TableDoesNotExistError) do
|
66
|
+
database.columns :Directors
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
63
70
|
test "should treat quotation marks correctly" do
|
64
71
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
65
72
|
actor = database.read(:Actors).first
|
66
73
|
assert_equal "Chris", actor[:FirstName] # as opposed to "\"Chris\""
|
67
74
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
|
76
|
+
test "should treat non-ASCII characters correctly" do
|
77
|
+
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
78
|
+
actor = database.read(:Actors).last
|
79
|
+
assert_equal "Skarsgård", actor[:LastName]
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
71
84
|
test "should format dates ISO 8601" do
|
72
85
|
database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
|
73
86
|
actor = database.read(:Actors).first
|
74
87
|
assert_equal "1981-06-13 00:00:00", actor[:Birthdate]
|
75
88
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
89
|
+
|
90
|
+
|
91
|
+
|
79
92
|
private
|
80
|
-
|
93
|
+
|
81
94
|
def with_env(new_env)
|
82
95
|
begin
|
83
96
|
old_env = ENV.to_hash
|
@@ -87,5 +100,5 @@ private
|
|
87
100
|
ENV.replace(old_env)
|
88
101
|
end
|
89
102
|
end
|
90
|
-
|
103
|
+
|
91
104
|
end
|
metadata
CHANGED
@@ -1,83 +1,89 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rails
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 3.2.0
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 4.1.0
|
48
51
|
type: :development
|
49
52
|
prerelease: false
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
51
54
|
requirements:
|
52
|
-
- -
|
55
|
+
- - ">="
|
53
56
|
- !ruby/object:Gem::Version
|
54
57
|
version: 3.2.0
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 4.1.0
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: turn
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
|
-
- -
|
65
|
+
- - ">="
|
60
66
|
- !ruby/object:Gem::Version
|
61
67
|
version: '0'
|
62
68
|
type: :development
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
|
-
- -
|
72
|
+
- - ">="
|
67
73
|
- !ruby/object:Gem::Version
|
68
74
|
version: '0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: pry
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
|
-
- -
|
79
|
+
- - ">="
|
74
80
|
- !ruby/object:Gem::Version
|
75
81
|
version: '0'
|
76
82
|
type: :development
|
77
83
|
prerelease: false
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
79
85
|
requirements:
|
80
|
-
- -
|
86
|
+
- - ">="
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: '0'
|
83
89
|
description: A library for reading Microsoft Access databases
|
@@ -87,8 +93,8 @@ executables: []
|
|
87
93
|
extensions: []
|
88
94
|
extra_rdoc_files: []
|
89
95
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .travis.yml
|
96
|
+
- ".gitignore"
|
97
|
+
- ".travis.yml"
|
92
98
|
- Gemfile
|
93
99
|
- LICENSE.txt
|
94
100
|
- README.md
|
@@ -111,17 +117,17 @@ require_paths:
|
|
111
117
|
- lib
|
112
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|
113
119
|
requirements:
|
114
|
-
- -
|
120
|
+
- - ">="
|
115
121
|
- !ruby/object:Gem::Version
|
116
122
|
version: '0'
|
117
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
124
|
requirements:
|
119
|
-
- -
|
125
|
+
- - ">="
|
120
126
|
- !ruby/object:Gem::Version
|
121
127
|
version: '0'
|
122
128
|
requirements: []
|
123
129
|
rubyforge_project:
|
124
|
-
rubygems_version: 2.
|
130
|
+
rubygems_version: 2.4.5.1
|
125
131
|
signing_key:
|
126
132
|
specification_version: 4
|
127
133
|
summary: Wraps mdb-tools for reading and Microsoft Access databases (MDB)
|