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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 743fac27121ba7755e9bd504da03a4dd5067c5ee
4
- data.tar.gz: 6132d6430e369e4252bc398095b66a30ec5e1f2d
3
+ metadata.gz: 55c6c7c1cdcb9921dfebf67418cd17e2fdac1bb1
4
+ data.tar.gz: ddc03a93b64636f6db253f639e49030429864c11
5
5
  SHA512:
6
- metadata.gz: ace168b10d293ad77f5527730ade2d549f4869ebfc73baafcb6220d4d4f42f8257575e601202df3204dbcf11be335e91204e6fc7eb09b8af10b3ba2f523fa679
7
- data.tar.gz: 39a9b268a36d122bc14005a64ee5448e8e43f076699b1b3e79bf1da538781e8f74a7d8deb5f6cfdabaee908db9b830ab02ff94c7d629ff7a9cecfd70536eddde
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
@@ -1,48 +1,54 @@
1
- require 'tempfile'
2
- require 'shellwords'
3
- require 'open3'
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) { |csv| csv.readline.map(&:to_sym) }
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 if `which mdb-export 2> /dev/null`.empty?
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
- Open3.popen3(command) do |stdin, stdout, stderr|
110
- yield CSV.new(stdout, col_sep: delimiter)
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
- stdout = `#{command} 2> /dev/null`
118
-
119
- # !todo: add fixture data and a test to prove this code
120
- if stdout.respond_to?(:force_encoding)
121
- stdout.force_encoding("Windows-1252")
122
- stdout.encode!("utf-8")
123
- end
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
@@ -1,3 +1,3 @@
1
1
  module Mdb
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
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", ">= 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
Binary file
Binary file
@@ -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 => 4,
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.1
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: 2014-02-06 00:00:00.000000000 Z
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.2.1
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)