mdb 0.0.2 → 0.0.3.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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