activemdb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.1.0 / 2007-02-22
2
+
3
+
4
+
@@ -0,0 +1,19 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ db/sample.mdb
6
+ irb.rc
7
+ lib/active_mdb.rb
8
+ lib/active_mdb/column.rb
9
+ lib/active_mdb/mdb.rb
10
+ lib/active_mdb/mdb_tools.rb
11
+ lib/active_mdb/record.rb
12
+ lib/active_mdb/table.rb
13
+ support/a.insert
14
+ test/test_activemdb.rb
15
+ test/test_helper.rb
16
+ test/test_mdb.rb
17
+ test/test_mdb_tools.rb
18
+ test/test_record.rb
19
+ test/test_table.rb
@@ -0,0 +1,57 @@
1
+ ActiveMDB
2
+ by Matthew King
3
+ http://rubyforge.org/projects/activemdb/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Lib for getting info out of MS Access (.mdb) files, which uses ActiveRecord-ish reflection to parse table and column names.
8
+
9
+ Intended for exploration and migration, not production. ActiveMDB provides a thin wrapper around the mdb-tables, mdb-schema, mdb-sql, and mdb-export binaries from Brian Bruns's MDB Tools project (http://mdbtools.sourceforge.net/).
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * MDB, Table, and Record classes do reflection to provide easy attribute readers
14
+ * I really need to refactor the above classes to something more like ActiveRecord::Base, so that you can subclass to make models.
15
+
16
+ == SYNOPSIS:
17
+
18
+ @mdb = MDB.new('db/sample.mdb', :exclude => 'lookups')
19
+ @employees = @mdb.employees
20
+
21
+ # in the find_* methods, the entries in the hash
22
+ # get turned into "WHERE #{key} like %#{value}%" conditions,
23
+ # unless the column is a boolean, in which case the WHERE uses "="
24
+ @employees.find_first :f_name => 'Matthew', :l_name => 'King'
25
+
26
+ == REQUIREMENTS:
27
+
28
+ * http://mdbtools.sourceforge.net/
29
+
30
+ == INSTALL:
31
+
32
+ * Sadly, no easy install at this time.
33
+
34
+ == LICENSE:
35
+
36
+ (The MIT License)
37
+
38
+ Copyright (c) 2007
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining
41
+ a copy of this software and associated documentation files (the
42
+ 'Software'), to deal in the Software without restriction, including
43
+ without limitation the rights to use, copy, modify, merge, publish,
44
+ distribute, sublicense, and/or sell copies of the Software, and to
45
+ permit persons to whom the Software is furnished to do so, subject to
46
+ the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be
49
+ included in all copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
52
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
54
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
55
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
56
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
57
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/active_mdb.rb'
6
+
7
+ Hoe.new('activemdb', ActiveMDB::VERSION) do |p|
8
+ p.rubyforge_name = 'activemdb'
9
+ p.author = 'Matthew King'
10
+ p.email = 'automatthew@gmail.com'
11
+ p.summary = 'a reflective wrapper around MDB Tools, which lets POSIX platforms read MS Access (.mdb) files'
12
+ p.description = p.paragraphs_of('README.txt', 2).join("\n\n")
13
+ p.url = p.paragraphs_of('README.txt',0).first.split(/\n/)[2..-1]
14
+ # p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
+ end
16
+
17
+ # vim: syntax=Ruby
Binary file
data/irb.rc ADDED
@@ -0,0 +1,4 @@
1
+ require "#{File.dirname(__FILE__)}/lib/active_mdb"
2
+ require 'pp'
3
+ include MDBTools
4
+
@@ -0,0 +1,18 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ module ActiveMDB
3
+ VERSION = '0.1.0'
4
+ end
5
+
6
+
7
+ require 'rubygems'
8
+ require 'active_support/inflector'
9
+ require 'active_mdb/mdb_tools'
10
+ load 'active_mdb/mdb.rb'
11
+ load 'active_mdb/table.rb'
12
+ load 'active_mdb/record.rb'
13
+ load 'active_mdb/column.rb'
14
+ require 'faster_csv'
15
+
16
+
17
+
18
+
@@ -0,0 +1,21 @@
1
+ class Column
2
+ include MDBTools
3
+
4
+ attr_reader :method_name, :name, :type, :size
5
+
6
+ def initialize(name, type, size)
7
+ @name = name
8
+ @method_name, @type, @size = methodize(name), methodize(type), size.to_i
9
+ end
10
+
11
+ def self.new_from_describe(describe_hash)
12
+ self.new(describe_hash["Column Name"], describe_hash["Type"], describe_hash["Size"])
13
+ end
14
+
15
+
16
+ def boolean?
17
+ self.type == 'boolean'
18
+ end
19
+
20
+
21
+ end
@@ -0,0 +1,39 @@
1
+ # require 'mdb_tools'
2
+
3
+ class MDB
4
+ include MDBTools
5
+
6
+ attr_reader :mdb_file, :prefix, :exclude, :table_names
7
+
8
+ def initialize(mdb_file, options = {})
9
+ @mdb_file = check_file(mdb_file)
10
+ @prefix = options[:prefix] || ''
11
+ @exclude, @include = options[:exclude], options[:include]
12
+ @export_syntax = options[:sql_syntax] || 'mysql'
13
+ @table_names = mdb_tables(@mdb_file, :exclude => @exclude, :include => @include)
14
+ @tables = create_table_objects
15
+ end
16
+
17
+ def tables
18
+ @table_names.collect { |table| methodize(table)}
19
+ end
20
+
21
+
22
+
23
+ private
24
+
25
+ def create_table_objects
26
+ tables = {}
27
+ @table_names.each do |table|
28
+ tables[table] = Table.new(self, table, @prefix)
29
+ metaclass = class << self; self; end
30
+ metaclass.send :define_method, methodize(table) do
31
+ tables[table]
32
+ end
33
+ end
34
+ tables
35
+ end
36
+
37
+
38
+ end
39
+
@@ -0,0 +1,149 @@
1
+ module MDBTools
2
+ include Inflector
3
+
4
+ DELIMITER = '::'
5
+ LINEBREAK = "\n"
6
+ SANITIZER = /^\w\.\_/ # dumb filter for SQL arguments
7
+ BACKENDS = %w{ access mysql oracle postgres sybase }
8
+
9
+ def check_file(mdb_file)
10
+ raise ArgumentError, "File not found: #{mdb_file}" unless File.exist?(mdb_file)
11
+ @mdb_version = `mdb-ver #{mdb_file} 2>&1`.chomp
12
+ if $? != 0
13
+ raise ArgumentError, "mdbtools cannot access #{mdb_file}"
14
+ end
15
+ mdb_file
16
+ end
17
+
18
+ def check_table(mdb_file, table_name)
19
+ unless mdb_tables(mdb_file).include?(table_name)
20
+ raise ArgumentError, "mdbtools does not think a table named \"#{table_name}\" exists"
21
+ end
22
+ table_name
23
+ end
24
+
25
+ def mdb_tables(mdb_file, options = {})
26
+ included, excluded = options[:include], options[:exclude]
27
+ return `mdb-tables -1 #{mdb_file}`.split(LINEBREAK) if not (included || excluded)
28
+ raise ArgumentError if (options[:include] && options [:exclude])
29
+ if options[:exclude]
30
+ regex = Regexp.new options[:exclude].to_a.join('|')
31
+ tables = `mdb-tables -1 #{mdb_file}`.split(LINEBREAK).delete_if { |name| name =~ regex }
32
+ end
33
+ if options[:include]
34
+ regex = Regexp.new options[:include].to_a.join('|')
35
+ tables = `mdb-tables -1 #{mdb_file}`.split(LINEBREAK).select { |name| name =~ regex }
36
+ end
37
+ tables
38
+ end
39
+
40
+ def sql_select(mdb_file, table_name, attributes = nil, conditions ={})
41
+ attributes ||= ['*']
42
+ sql = "select #{attributes.join(' ')} from #{table_name} where #{conditions}".dump
43
+ mdb_sql(mdb_file, sql)
44
+ end
45
+
46
+
47
+ def mdb_sql(mdb_file, sql)
48
+ # puts sql
49
+ result = `echo -n #{sql} | mdb-sql -Fp -H -d '#{DELIMITER}' #{mdb_file}`.strip
50
+ arrays = delimited_to_arrays(result)
51
+ end
52
+
53
+ def compile_conditions(conditions_hash, *args)
54
+ conditions = conditions_hash.sort_by{|k,v| k.to_s}.map do |column_name, value|
55
+ if block_given?
56
+ yield column_name, value
57
+ else
58
+ "#{column_name} like '%#{value}%'"
59
+ end
60
+ end.join(' AND ')
61
+ end
62
+
63
+ def mdb_export(mdb_file, table_name, options = {})
64
+ defaults = { :format => 'sql',
65
+ :headers => false,
66
+ :sanitize => true }
67
+ options = defaults.merge options
68
+
69
+ args = []
70
+ if options[:delimiter]
71
+ args << "-d #{options[:delimiter].dump}"
72
+ elsif options[:format] == 'sql'
73
+ args << "-I "
74
+ elsif options[:format] == 'csv'
75
+ args << "-d ',' "
76
+ else
77
+ raise ArgumentError, "Unknown format: #{options[:format]}"
78
+ end
79
+
80
+ args << "-H " unless options[:headers] == true
81
+ args << "-S" unless options[:sanitize] == false
82
+ `mdb-export #{args} #{mdb_file} #{table_name.to_s.dump}`
83
+ end
84
+
85
+ def describe_table(mdb_file, table_name)
86
+ command = "describe table \"#{table_name}\"".dump
87
+ description = `echo -n #{command} | mdb-sql -Fp -d '#{DELIMITER}' #{mdb_file}`.strip
88
+ arrays = delimited_to_arrays(description)
89
+ arrays_to_hashes(arrays.shift, arrays)
90
+ end
91
+
92
+ def mdb_schema(mdb_file, table_name)
93
+ schema = `mdb-schema -T #{table_name.dump} #{mdb_file}`
94
+ end
95
+
96
+
97
+ def table_to_csv(mdb_file, table_name)
98
+ mdb_export(mdb_file, table_name, :format => 'csv', :headers => true)
99
+ end
100
+
101
+ def delimited_to_arrays(text)
102
+ text.gsub!(/\r\n/,' ')
103
+ text.split(LINEBREAK).collect { |row| row.split(DELIMITER)}
104
+ end
105
+
106
+ def arrays_to_hashes(headers, arrays)
107
+ arrays.collect do |record|
108
+ record_hash = Hash.new
109
+ until record.empty? do
110
+ headers.each do |header|
111
+ record_hash[header] = record.shift
112
+ end
113
+ end
114
+ record_hash
115
+ end
116
+ end
117
+
118
+
119
+
120
+ def methodize(table_name)
121
+ underscore table_name
122
+ end
123
+
124
+ def backends
125
+ BACKENDS
126
+ end
127
+
128
+ def sanitize!(string)
129
+ string.gsub!(SANITIZER, '')
130
+ end
131
+
132
+ def mdb_truth(value)
133
+ case value
134
+ when false
135
+ 0
136
+ when true
137
+ 1
138
+ when 0
139
+ 0
140
+ when 1
141
+ 1
142
+ when "0"
143
+ 0
144
+ when "1"
145
+ 1
146
+ end
147
+ end
148
+
149
+ end
@@ -0,0 +1,33 @@
1
+ # require 'mdb_tools'
2
+
3
+ class Record
4
+ include MDBTools
5
+ include Enumerable
6
+
7
+ def initialize(mdb_table, line)
8
+ raise 'no results' unless line
9
+ @struct = mdb_table.record_struct
10
+ @data = @struct.new(*line)
11
+ create_accessors
12
+ end
13
+
14
+ def each(&block)
15
+ @data.members.each {|k| yield k, @data[k] }
16
+ end
17
+
18
+ def compact
19
+ self.select {|k,v| v && !v.empty? && v != "0" }
20
+ end
21
+
22
+ private
23
+
24
+ def create_accessors
25
+ meta = class << self; self; end
26
+ @struct.members.each do |att|
27
+ meta.send :define_method, att do
28
+ @data[att]
29
+ end
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,89 @@
1
+ # require 'mdb_tools'
2
+
3
+ class Table
4
+ include MDBTools
5
+
6
+ attr_reader :mdb_file, :table_name, :columns, :record_struct, :schema
7
+ attr_accessor :primary_key
8
+
9
+
10
+ def initialize(mdb, table_name, prefix)
11
+ @mdb_file = check_file(mdb.mdb_file)
12
+ @table_name = check_table(@mdb_file, table_name)
13
+ # @schema = mdb_schema(@mdb_file, @table_name)
14
+ @columns = describe_table(mdb_file, table_name).map do |column|
15
+ Column.new_from_describe(column)
16
+ end
17
+ @record_struct = create_record_struct
18
+ end
19
+
20
+
21
+ def [](method_name)
22
+ self.columns.detect {|c| c.method_name == method_name }
23
+ end
24
+
25
+ def column_names
26
+ columns.collect {|x| methodize(x.method_name).to_sym}
27
+ end
28
+
29
+ def create_record_struct
30
+ attributes = columns.collect {|column| column.method_name.to_sym}
31
+ Struct.new( *attributes)
32
+ end
33
+
34
+ def to_csv
35
+ table_to_csv(mdb_file, table_name)
36
+ end
37
+
38
+ def to_sql
39
+ raise 'not implemented'
40
+ end
41
+
42
+ def find_first(conditions_hash)
43
+ rekey_hash(conditions_hash)
44
+ result = sql_search(conditions_hash).first
45
+ create_record(result)
46
+ end
47
+
48
+ def find_all(conditions_hash={})
49
+ if conditions_hash.empty?
50
+ return sql_select(mdb_file, table_name, nil, '1 = 1').collect {|r| create_record(r)}
51
+ end
52
+ rekey_hash(conditions_hash)
53
+ sql_search(conditions_hash).collect {|r| create_record(r) }
54
+ end
55
+
56
+ private
57
+
58
+ def create_record(line)
59
+ Record.new(self, line)
60
+ end
61
+
62
+ def rekey_hash(conditions_hash)
63
+ conditions_hash.each do |key,value|
64
+ column = self[key.to_s]
65
+ if column.boolean?
66
+ key = column.name + '!'
67
+ else
68
+ key = column.name
69
+ end
70
+ end
71
+ end
72
+
73
+ # the conditions hash keys are column names, the values are search values
74
+ # e.g. sql_search(:first_name => 'Matthew', :last_name => 'King')
75
+ def sql_search(conditions_hash)
76
+ conditions = compile_conditions(conditions_hash) do |method_name,value|
77
+ column = self[method_name.to_s]
78
+ if column.boolean?
79
+ "#{column.name} = #{mdb_truth(value)}"
80
+ else
81
+ "#{column.name} like '%#{value}%'"
82
+ end
83
+ end
84
+ sql_select(mdb_file, table_name, nil, conditions)
85
+ end
86
+
87
+
88
+ end
89
+
@@ -0,0 +1,7 @@
1
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (1,0000000000000001.,"Conversation","QA conversation with the contact - face to face")
2
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (2,0000000000000002.,"Phone Call","A Phone Call with the contact")
3
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (3,0000000000000003.,"Mail","Sent something to the contact via mail")
4
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (4,0000000000000004.,"eMail","Sent something to the contact via email")
5
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (5,0000000000000005.,"Visit","Visited the contact for a delivery or conversation")
6
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (6,0000000000000006.,"Meeting","Had a meeting with the contact")
7
+ INSERT INTO ActivityLookup (ActivityID, ActivitySeq, ActivityCode, ActivityDesc) VALUES (7,0000000000000007.,"Research","Research is needed on a topic for followup/action")
File without changes
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+
3
+ class Test::Unit::TestCase
4
+
5
+ TEST_DB = File.join(File.dirname(__FILE__), '..', 'db', 'sample.mdb')
6
+
7
+
8
+ protected
9
+
10
+ def create_mdb(options={})
11
+ excluded = options[:exclude]
12
+ included = options[:include]
13
+ assert_nothing_raised { @db = MDB.new(TEST_DB, :exclude => excluded, :include => included ) }
14
+ end
15
+
16
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), "..", 'lib', 'active_mdb')
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__), 'test_helper')
4
+
5
+ class MDBTest < Test::Unit::TestCase
6
+
7
+
8
+
9
+ def setup
10
+
11
+ end
12
+
13
+ def test_table_exclusion
14
+ create_mdb(:exclude => ['Inventory'])
15
+ assert !@db.table_names.include?('Inventory')
16
+ end
17
+
18
+ def test_table_inclusion
19
+ create_mdb(:include => ['Inventory', 'Room'])
20
+ assert_equal ['Inventory', 'Room'], @db.table_names.sort
21
+ end
22
+
23
+ def test_reflection
24
+ create_mdb
25
+ assert_respond_to @db, 'computer'
26
+ assert_respond_to @db, 'employee'
27
+ assert_respond_to @db, 'room'
28
+ end
29
+
30
+
31
+
32
+
33
+
34
+ end
35
+
@@ -0,0 +1,100 @@
1
+ require File.join(File.dirname(__FILE__), "..", 'lib', 'active_mdb')
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__), 'test_helper')
4
+
5
+
6
+ class MDBToolsTest < Test::Unit::TestCase
7
+ include MDBTools
8
+
9
+ EXCLUDE = ['Inventory']
10
+ TEST_TABLES = %w{ Room Computer Employee }
11
+ TORBATI_Y = {"Department"=>"Engineering",
12
+ "Gender"=>"F",
13
+ "Room"=>"6044",
14
+ "Title"=>"Programmer",
15
+ "Emp_Id"=>"1000",
16
+ "First_Name"=>"Yolanda",
17
+ "Last_Name"=>"Torbati"}
18
+ README = File.join(File.dirname(__FILE__), "..", "README")
19
+
20
+ def setup
21
+ @employees_csv = mdb_export(TEST_DB, 'Employee', :format => 'csv', :headers => true)
22
+ end
23
+
24
+ def test_check_file
25
+ assert_nothing_raised { check_file TEST_DB }
26
+ assert_raise(ArgumentError) { check_file 'completely_bogus_filename' }
27
+ # the README file is obviously not an Access database
28
+ assert_raise(ArgumentError) { check_file README}
29
+ end
30
+
31
+ def test_check_table
32
+ assert_nothing_raised { check_table TEST_DB, 'Employee'}
33
+ assert_raises(ArgumentError) { check_table TEST_DB, 'foobarbaz' }
34
+ end
35
+
36
+ def test_mdb_tables
37
+ tables1 = mdb_tables(TEST_DB, :exclude => EXCLUDE)
38
+ assert_equal TEST_TABLES, tables1
39
+
40
+ assert_raises( ArgumentError) { mdb_tables(TEST_DB, :include => [], :exclude => []) }
41
+ tables4 = mdb_tables(TEST_DB, :exclude => 'Room')
42
+ assert_equal %w{Computer Employee Inventory}, tables4
43
+ end
44
+
45
+ def test_mdb_tables_with_include
46
+ tables = mdb_tables(TEST_DB, :include => ['Room', 'Computer'])
47
+ assert_equal ['Room', 'Computer'], tables
48
+ end
49
+
50
+ def test_mdb_tables_with_nils
51
+ assert_nothing_raised do
52
+ tables = mdb_tables(TEST_DB, :include => nil, :exclude => nil)
53
+ assert_not_nil tables
54
+ end
55
+ end
56
+
57
+ def test_mdb_schema
58
+ assert_nothing_raised { @schema = mdb_schema(TEST_DB, 'Employee') }
59
+ assert_match /DROP TABLE/, @schema
60
+ end
61
+
62
+
63
+ # def test_csv_to_hashes
64
+ # employee_hash = csv_to_hashes(@employees_csv)
65
+ # assert_equal TORBATI_Y, employee_hash.first
66
+ # end
67
+
68
+ def test_sql_select
69
+ assert_equal ["Torbati","Yolanda", "F", "Programmer", "Engineering", "6044", "1000"],
70
+ sql_select(TEST_DB, 'Employee', ['*'], "First_Name LIKE 'Yolanda'" ).first
71
+ end
72
+
73
+ def test_compile_conditions
74
+ conditions = {:foo => 'bar', :baz => 1, :nark => 'noo'}
75
+ assert_equal "baz like '%1%' AND foo like '%bar%' AND nark like '%noo%'", compile_conditions(conditions)
76
+ end
77
+
78
+ def test_compiled_sql_select
79
+ sql_select(TEST_DB, 'Employee', nil, compile_conditions(:first_name => 'Yolanda'))
80
+ end
81
+
82
+ def test_export_table_to_sql
83
+ # this test is dependent on specific content in the sample database
84
+ export = mdb_export(TEST_DB, 'Computer', :format => 'sql').split(LINEBREAK)
85
+ assert_equal 172, export.size
86
+ assert export.first =~ /INSERT INTO.*MITSUBISHI.*HL6605ATK/
87
+ end
88
+
89
+ def test_export_table_to_csv
90
+ export = mdb_export(TEST_DB, 'Employee', :format => 'csv').split(LINEBREAK)
91
+ assert_equal 53, export.size
92
+ assert export.first =~ /\"Torbati\",/
93
+ end
94
+
95
+ def test_backends
96
+ assert_nothing_raised { backends }
97
+ end
98
+
99
+
100
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), "..", 'lib', 'active_mdb')
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__), 'test_helper')
4
+
5
+ class RecordTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ create_mdb
9
+ @employee = @db.employee
10
+ @line = ["Torbati","Yolanda", "F", "Programmer", "Engineering", "6044", "1000"]
11
+ assert_nothing_raised { @record = Record.new(@employee, @line) }
12
+ end
13
+
14
+ def test_reflection
15
+ assert_respond_to @record, 'gender'
16
+ assert_respond_to @record, 'emp_id'
17
+ assert_equal 'Yolanda', @record.first_name
18
+ end
19
+
20
+ def test_display
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), "..", 'lib', 'active_mdb')
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__), 'test_helper')
4
+
5
+ class TableTest < Test::Unit::TestCase
6
+
7
+
8
+ def setup
9
+ create_mdb
10
+ @employee = @db.employee
11
+ end
12
+
13
+ def test_columns
14
+ columns = @employee.columns
15
+ assert_kind_of Array, columns
16
+ assert_kind_of Column, columns.first
17
+ assert_equal 7, columns.size
18
+ end
19
+
20
+ def test_create_record_struct
21
+ assert_kind_of Class, @employee.record_struct
22
+ members = @employee.record_struct.members
23
+ assert_equal 7, members.size
24
+ assert members.include?('emp_id')
25
+ end
26
+
27
+ def test_to_csv
28
+ csv_text = @employee.to_csv
29
+ assert_kind_of String, csv_text
30
+ arrays = csv_text.split(MDBTools::LINEBREAK)
31
+
32
+ # grab the headers and test for content
33
+ assert arrays.shift.include?('Emp_Id')
34
+ assert_equal 53, arrays.size
35
+ end
36
+
37
+ def test_find_first
38
+ y = @employee.find_first(:first_name => 'Yolanda')
39
+ assert_kind_of Record, y
40
+ assert_equal 'Yolanda', y.first_name
41
+ end
42
+
43
+ def test_find_all
44
+ a_names = @employee.find_all(:last_name => 'A')
45
+ assert_kind_of Array, a_names
46
+ assert_kind_of Record, a_names.first
47
+ assert_equal 2, a_names.size
48
+ end
49
+
50
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: activemdb
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2007-03-12 00:00:00 -05:00
8
+ summary: a reflective wrapper around MDB Tools, which lets POSIX platforms read MS Access (.mdb) files
9
+ require_paths:
10
+ - lib
11
+ email: automatthew@gmail.com
12
+ homepage: http://rubyforge.org/projects/activemdb/
13
+ rubyforge_project: activemdb
14
+ description: Intended for exploration and migration, not production. ActiveMDB provides a thin wrapper around the mdb-tables, mdb-schema, mdb-sql, and mdb-export binaries from Brian Bruns's MDB Tools project (http://mdbtools.sourceforge.net/).
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Matthew King
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - db/sample.mdb
37
+ - irb.rc
38
+ - lib/active_mdb.rb
39
+ - lib/active_mdb/column.rb
40
+ - lib/active_mdb/mdb.rb
41
+ - lib/active_mdb/mdb_tools.rb
42
+ - lib/active_mdb/record.rb
43
+ - lib/active_mdb/table.rb
44
+ - support/a.insert
45
+ - test/test_activemdb.rb
46
+ - test/test_helper.rb
47
+ - test/test_mdb.rb
48
+ - test/test_mdb_tools.rb
49
+ - test/test_record.rb
50
+ - test/test_table.rb
51
+ test_files:
52
+ - test/test_activemdb.rb
53
+ - test/test_helper.rb
54
+ - test/test_mdb.rb
55
+ - test/test_mdb_tools.rb
56
+ - test/test_record.rb
57
+ - test/test_table.rb
58
+ rdoc_options: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ requirements: []
67
+
68
+ dependencies:
69
+ - !ruby/object:Gem::Dependency
70
+ name: hoe
71
+ version_requirement:
72
+ version_requirements: !ruby/object:Gem::Version::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 1.2.0
77
+ version: