mdb 0.0.2 → 0.0.3.rc1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3480b9c2fc35ed39f57547a63d49b16fd9d30acb
4
+ data.tar.gz: 4325aff61e2ba6ea7e7fbd7bcfb9007464c07868
5
+ SHA512:
6
+ metadata.gz: 239876d157dbaa9ed429b1a832f1a0a83a12ef17c8e796e4cd09b185dfcde35fc4159f3e618d37fe105fe37590b8ad0374bf07d6c8acf93ea8ad2c7987bfb403
7
+ data.tar.gz: 294d967caecee1bb7b0081ae500d60e3e21f009240d783c748cfcb71970a4b1b06ae9a8e7e0042e101e1b544f8cbba0ecc24474d30edb0b7fd741f70b6fcf022
@@ -0,0 +1,8 @@
1
+ # .travis.yml
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ script:
6
+ - bundle exec rake test
7
+ before_install:
8
+ - sudo apt-get install mdbtools
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Mdb
2
2
 
3
+ [![Build Status](https://travis-ci.org/concordia-publishing-house/mdb.png?branch=master)](https://travis-ci.org/concordia-publishing-house/mdb)
4
+ [![Code Climate](https://codeclimate.com/github/concordia-publishing-house/mdb.png)](https://codeclimate.com/github/concordia-publishing-house/mdb)
5
+
3
6
  Wraps [mdb-tools](https://github.com/brianb/mdbtools) for reading Microsoft Access databases
4
7
 
5
8
  ## Installation
data/lib/mdb.rb CHANGED
@@ -5,6 +5,11 @@ module Mdb
5
5
 
6
6
  class FileDoesNotExistError < ArgumentError; end
7
7
  class TableDoesNotExistError < ArgumentError; end
8
+ class MdbToolsNotInstalledError < ArgumentError
9
+ def message
10
+ "mdbtools is not installed"
11
+ end
12
+ end
8
13
  class Error < RuntimeError; end
9
14
 
10
15
  def self.open(file)
@@ -1,20 +1,24 @@
1
1
  require 'tempfile'
2
+ require 'shellwords'
3
+ require 'open3'
4
+ require 'csv'
5
+
2
6
 
3
7
  module Mdb
4
8
  class Database
5
9
 
6
10
 
7
11
 
8
- def initialize(file)
12
+ def initialize(file, options={})
9
13
  raise FileDoesNotExistError, "\"#{file}\" does not exist" unless File.exist?(file)
10
14
 
11
15
  @file = file
12
- @delim = '|' # We're going to assume no pipes in data
16
+ @delimiter = options.fetch :delimiter, '|'
13
17
  end
14
18
 
15
19
 
16
20
 
17
- attr_reader :file
21
+ attr_reader :file, :delimiter
18
22
 
19
23
 
20
24
 
@@ -25,32 +29,27 @@ module Mdb
25
29
 
26
30
 
27
31
  def columns(table)
28
- csv = read_csv(table)
29
- first_line = csv[/^(.*)$/]
30
- parse_columns(first_line)
32
+ open_csv(table) { |csv| csv.readline.map(&:to_sym) }
31
33
  end
32
34
 
33
35
 
34
36
 
35
37
  def read_csv(table)
36
38
  csv = execute "mdb-export -d \\| #{file_name} #{table}"
37
- if csv.empty?
38
- raise TableDoesNotExistError, "#{table.inspect} does not exist in #{file_name.inspect}" if !tables.member?(table.to_s)
39
- raise Error, "An error occurred when reading #{table.inspect} in #{file_name.inspect}"
40
- end
39
+ empty_table!(table) if csv.empty?
41
40
  csv
42
41
  end
43
42
 
44
43
 
45
44
 
46
- # Returns an array of hashes. Each hash represents a record
45
+ # Yields a hash for each record
47
46
  def each_record(table, &block)
48
47
  columns = nil
49
48
  read_each(table) do |line|
50
49
  if columns
51
- yield map_to_hash(line.split(@delim), columns)
50
+ yield Hash[columns.zip(line)]
52
51
  else
53
- columns = parse_columns(line)
52
+ columns = line.map(&:to_sym)
54
53
  end
55
54
  end
56
55
  end
@@ -73,61 +72,50 @@ module Mdb
73
72
 
74
73
 
75
74
 
76
- def parse_columns(line)
77
- line.split(@delim).map {|name| name.empty? ? nil : name.to_sym }
78
- end
79
-
80
-
81
-
82
- def map_to_hash(values, columns)
83
- hash = {}
84
- (0...columns.length).each do |i|
85
- column = columns[i]
86
- next if column.nil?
87
- value = values[i]
88
- hash[column] = value && value.delete("\"")
75
+ def read_each(table, &block)
76
+ count = 0
77
+
78
+ open_csv(table) do |csv|
79
+ while line = csv.readline
80
+ yield line
81
+ count += 1
82
+ end
89
83
  end
90
- hash
84
+
85
+ empty_table!(table) if count == 0
86
+
87
+ count
91
88
  end
92
89
 
93
90
 
94
91
 
95
- def read_each(table, &block)
96
- count = 0
97
- read_csv(table).each_line do |line|
98
- yield line.chomp
99
- count += 1
100
- end
101
- count # don't return the result of read_csv; discard it
92
+ def empty_table!(table)
93
+ raise MdbToolsNotInstalledError if `which mdb-export 2> /dev/null`.empty?
94
+ raise TableDoesNotExistError, "#{table.inspect} does not exist in #{file_name.inspect}" if !tables.member?(table.to_s)
95
+ raise Error, "An error occurred when reading #{table.inspect} in #{file_name.inspect}"
102
96
  end
103
97
 
104
98
 
105
99
 
106
- def parse(csv)
107
- csv.split /\n/
100
+ def file_name
101
+ Shellwords.escape(file)
108
102
  end
109
103
 
110
104
 
111
105
 
112
- def file_name
113
- @file.gsub(' ', '\ ')
106
+ def open_csv(table)
107
+ command = "mdb-export -d #{Shellwords.escape(delimiter)} #{file_name} #{table}"
108
+ Open3.popen3(command) do |stdin, stdout, stderr|
109
+ yield CSV.new(stdout, col_sep: delimiter)
110
+ end
114
111
  end
115
112
 
116
113
 
117
114
 
118
115
  def execute(command)
119
- stdout = ""
120
- (1..5).each do |try|
121
- Tempfile.open(rand(99999999).to_s) do |t|
122
- stdout = `#{command} 2> #{t.path}`
123
- t.rewind
124
- stderr = t.read.strip
125
- break if stderr.empty?
126
-
127
- # Rails.logger.error("[mdb-tools] executed `#{command}`; got \"#{stderr}\"")
128
- end
129
- end
116
+ stdout = `#{command} 2> /dev/null`
130
117
 
118
+ # !todo: add fixture data and a test to prove this code
131
119
  if stdout.respond_to?(:force_encoding)
132
120
  stdout.force_encoding("Windows-1252")
133
121
  stdout.encode!("utf-8")
@@ -1,3 +1,3 @@
1
1
  module Mdb
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3.rc1"
3
3
  end
@@ -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"
23
+ spec.add_development_dependency "rails", ">= 3.2.0"
24
24
  spec.add_development_dependency "turn"
25
25
  spec.add_development_dependency "pry"
26
26
  end
File without changes
File without changes
@@ -32,6 +32,18 @@ class MdbTest < ActiveSupport::TestCase
32
32
  end
33
33
  end
34
34
 
35
+ test "should raise an exception when mdb-tools is not installed" do
36
+ assert_raises(Mdb::MdbToolsNotInstalledError) do
37
+ database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
38
+
39
+ # This test assumes that the tool `which` is in `/usr/bin`
40
+ # while `mdb-export` et al are installed elsewhere.
41
+ with_env "PATH" => "/usr/bin" do
42
+ database.read :Villains
43
+ end
44
+ end
45
+ end
46
+
35
47
  test "should raise an exception if a table is not found" do
36
48
  database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
37
49
  assert_raises(Mdb::TableDoesNotExistError) do
@@ -46,4 +58,29 @@ class MdbTest < ActiveSupport::TestCase
46
58
 
47
59
 
48
60
 
61
+ test "should return an array of columns for at able" do
62
+ database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
63
+ assert_equal [:ID, :FirstName, :LastName], database.columns(:Actors)
64
+ end
65
+
66
+ test "should treat quotation marks correctly" do
67
+ database = Mdb.open "#{File.dirname(__FILE__)}/data/Example2000.mdb"
68
+ actor = database.read(:Actors).first
69
+ assert_equal "Chris", actor[:FirstName] # as opposed to "\"Chris\""
70
+ end
71
+
72
+
73
+
74
+ private
75
+
76
+ def with_env(new_env)
77
+ begin
78
+ old_env = ENV.to_hash
79
+ ENV.replace(old_env.merge(new_env))
80
+ yield
81
+ ensure
82
+ ENV.replace(old_env)
83
+ end
84
+ end
85
+
49
86
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.3.rc1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Robert Lail
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-08 00:00:00.000000000 Z
11
+ date: 2013-10-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,65 +27,57 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rails
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
- version: '0'
47
+ version: 3.2.0
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
- version: '0'
54
+ version: 3.2.0
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: turn
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: pry
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  description: A library for reading Microsoft Access databases
@@ -99,7 +88,7 @@ extensions: []
99
88
  extra_rdoc_files: []
100
89
  files:
101
90
  - .gitignore
102
- - Example2003.mdb
91
+ - .travis.yml
103
92
  - Gemfile
104
93
  - LICENSE.txt
105
94
  - README.md
@@ -115,33 +104,26 @@ files:
115
104
  homepage: ''
116
105
  licenses:
117
106
  - MIT
107
+ metadata: {}
118
108
  post_install_message:
119
109
  rdoc_options: []
120
110
  require_paths:
121
111
  - lib
122
112
  required_ruby_version: !ruby/object:Gem::Requirement
123
- none: false
124
113
  requirements:
125
- - - ! '>='
114
+ - - '>='
126
115
  - !ruby/object:Gem::Version
127
116
  version: '0'
128
- segments:
129
- - 0
130
- hash: 3387175660756308767
131
117
  required_rubygems_version: !ruby/object:Gem::Requirement
132
- none: false
133
118
  requirements:
134
- - - ! '>='
119
+ - - '>'
135
120
  - !ruby/object:Gem::Version
136
- version: '0'
137
- segments:
138
- - 0
139
- hash: 3387175660756308767
121
+ version: 1.3.1
140
122
  requirements: []
141
123
  rubyforge_project:
142
- rubygems_version: 1.8.25
124
+ rubygems_version: 2.0.3
143
125
  signing_key:
144
- specification_version: 3
126
+ specification_version: 4
145
127
  summary: Wraps mdb-tools for reading and Microsoft Access databases (MDB)
146
128
  test_files:
147
129
  - test/data/Example2000.mdb
Binary file