activemdb 0.2.0 → 0.2.1

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.
@@ -1,4 +1,8 @@
1
- == 0.1.0 / 2007-02-22
1
+ == 0.2.1 / 2007-04-10
2
+
3
+ Added typecasting so that the strings returned from mdb-sql become happy appropriate Ruby things.
2
4
 
5
+ == 0.2.0 / 2007-04-05
6
+ == 0.1.0 / 2007-02-22
3
7
 
4
8
 
@@ -17,6 +17,7 @@ lib/active_mdb/table.rb
17
17
  support/a.insert
18
18
  test/test_activemdb.rb
19
19
  test/test_base.rb
20
+ test/test_column.rb
20
21
  test/test_helper.rb
21
22
  test/test_mdb.rb
22
23
  test/test_mdb_tools.rb
data/Rakefile CHANGED
@@ -8,10 +8,10 @@ Hoe.new('activemdb', ActiveMDB::VERSION) do |p|
8
8
  p.rubyforge_name = 'activemdb'
9
9
  p.author = 'Matthew King'
10
10
  p.email = 'automatthew@gmail.com'
11
- p.summary = 'ActiveRecordy wrapper around MDB Tools, which lets POSIX platforms read MS Access (.mdb) files'
11
+ p.summary = 'ActiveRecordy wrapper around MDB Tools, allowing POSIX platforms to read MS Access (.mdb) files'
12
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")
13
+ p.url = 'http://activemdb.rubyforge.org/'
14
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
15
  end
16
16
 
17
17
  # vim: syntax=Ruby
@@ -1,6 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
  module ActiveMDB
3
- VERSION = '0.2.0'
3
+ VERSION = '0.2.1'
4
4
  end
5
5
 
6
6
 
@@ -1,11 +1,10 @@
1
1
  module ActiveMDB
2
+ # Hi, I am an imitation of ActiveRecord.
2
3
  class Base
3
4
 
4
5
  def initialize(attributes=nil)
5
6
  @attributes = attributes unless attributes.nil?
6
7
  end
7
-
8
-
9
8
 
10
9
  cattr_accessor :pluralize_table_names, :instance_writer => false
11
10
  @@pluralize_table_names = true
@@ -14,11 +13,13 @@ module ActiveMDB
14
13
  attr_accessor :mdb_file
15
14
  attr_reader :mdb
16
15
 
16
+ # set the path to the MDB file
17
17
  def set_mdb_file(file)
18
18
  @mdb_file = file
19
19
  @mdb = MDB.new(file)
20
20
  end
21
-
21
+
22
+ # set the name of the table in the MDB file
22
23
  def table_name
23
24
  table_name = Inflector.underscore(Inflector.demodulize(self.to_s))
24
25
  table_name = Inflector.pluralize(table_name) if pluralize_table_names
@@ -44,10 +45,14 @@ module ActiveMDB
44
45
  @mdb.column_names(table_name)
45
46
  end
46
47
 
48
+ # returns 'id' unless you overwrite this method using set_primary_key
47
49
  def primary_key
48
50
  'id'
49
51
  end
50
52
 
53
+ # specify the field to be used as a primary key for those
54
+ # operations that require one. At this time, that isn't really
55
+ # anything except count.
51
56
  def set_primary_key(value = nil, &block)
52
57
  define_attr_method :primary_key, value, &block
53
58
  end
@@ -57,20 +62,31 @@ module ActiveMDB
57
62
  @mdb.tables.include? table_name
58
63
  end
59
64
 
65
+ # How many? Requires that the primary_key return a valid field.
60
66
  def count
61
67
  @mdb.count(table_name, primary_key)
62
68
  end
63
69
 
70
+ # the conditions hash keys are column names, the values are search values
71
+ # find_first :superhero_name => 'The Ironist', :powers => 'Wit'
72
+ #
73
+ # mdb-sql doesn't implement LIMIT yet, so this method pulls all results and
74
+ # calls Array#first on them. Ooky.
64
75
  def find_first(conditions_hash)
65
76
  # rekey_hash(conditions_hash)
66
- sql_search(conditions_hash).first
77
+ find_from_hash(conditions_hash).first
67
78
  end
68
79
 
80
+ # the conditions hash keys are column names, the values are search values
81
+ # find_all :superhero_name => 'The Ironist', :powers => 'Wit'
82
+ #
83
+ # mdb-sql doesn't implement LIMIT yet, so this method pulls all results and
84
+ # calls Array#first on them. Ooky.
69
85
  def find_all(conditions_hash)
70
- sql_search(conditions_hash)
86
+ find_from_hash(conditions_hash)
71
87
  end
72
88
 
73
- # borrowed from ActiveRecord
89
+ # borrowed from ActiveRecord.
74
90
  def define_attr_method(name, value=nil, &block)
75
91
  sing = class << self; self; end
76
92
  sing.send :alias_method, "original_#{name}", name
@@ -94,18 +110,54 @@ module ActiveMDB
94
110
  end
95
111
  end
96
112
  end
113
+
114
+ # supply a conditions string that would nestle gently in a
115
+ # WHERE clause, after the WHERE but before the.
116
+ def find_where(conditions)
117
+ MDBTools.sql_select_where(mdb_file, table_name, nil, conditions).collect! { |record| instantiate(record) }
118
+ end
119
+
120
+ # takes a hash where the keys are column names (string or symbol)
121
+ # and the values are the associated values.
122
+ def find_from_hash(hash)
123
+ conditions = conditions_from_hash(hash)
124
+ find_where(conditions)
125
+ end
97
126
 
98
127
  # the conditions hash keys are column names, the values are search values
99
- # e.g. sql_search(:first_name => 'Matthew', :last_name => 'King')
100
- def sql_search(conditions_hash)
101
- conditions = MDBTools.compile_conditions(conditions_hash)
102
- MDBTools.sql_select(mdb_file, table_name, nil, conditions).collect! { |record| instantiate(record) }
128
+ # e.g. search_with_hash(:first_name => 'Matthew', :last_name => 'King')
129
+ def conditions_from_hash(hash)
130
+ MDBTools.compile_conditions(hash) do |column_name, value|
131
+ column = column_for(column_name)
132
+ case column.klass.to_s
133
+ when 'Fixnum', 'Float'
134
+ "#{column_name} = #{value}"
135
+ when 'String'
136
+ "#{column_name} LIKE '%#{value}%'"
137
+ when 'Object'
138
+ value = value ? 1 : 0
139
+ "#{column_name} IS #{value}"
140
+ end
141
+ end
142
+ end
143
+
144
+ # given the name of a column, return the Column object
145
+ def column_for(column_name)
146
+ columns.detect {|c| c.name == column_name.to_s}
103
147
  end
104
148
 
105
149
  private
106
150
 
107
151
  def instantiate(record)
108
- new(record)
152
+ new_hash = {}
153
+ record.each do |name,value|
154
+ begin
155
+ new_hash[name] = column_for(name).type_cast(value)
156
+ rescue
157
+ raise "No column for #{name}"
158
+ end
159
+ end
160
+ self.new new_hash
109
161
  end
110
162
 
111
163
 
@@ -8,6 +8,8 @@ class Column
8
8
  @method_name, @size = methodize(name), size.to_i
9
9
  end
10
10
 
11
+ # returns a new Column from a hash with the keys:
12
+ # 'Column Name', 'Type', and 'Size'
11
13
  def self.new_from_describe(describe_hash)
12
14
  self.new(describe_hash["Column Name"], describe_hash["Type"], describe_hash["Size"])
13
15
  end
@@ -18,6 +20,7 @@ class Column
18
20
  case type
19
21
  when 'Text', 'Character' then String
20
22
  when 'Long Integer' then Fixnum
23
+ when 'Double' then Float
21
24
  when 'Currency', 'Float' then Float
22
25
  when 'DateTime (Short)' then Time
23
26
  when 'Boolean' then Object
@@ -34,6 +37,7 @@ class Column
34
37
  when 'Text', 'Character' then value
35
38
  when 'Long Integer' then value.to_i rescue value ? 1 : 0
36
39
  when 'Currency', 'Float' then value.to_f
40
+ when 'Double' then value.to_f
37
41
  when 'DateTime (Short)' then self.class.string_to_time(value)
38
42
  when 'Boolean' then self.class.value_to_boolean(value)
39
43
  when 'Decimal' then self.class.value_to_decimal(value)
@@ -42,6 +46,8 @@ class Column
42
46
  end
43
47
  end
44
48
 
49
+ # provided any argument, returns the mdb-tools version
50
+ # of truth (which is to say, 1 or 0)
45
51
  def self.value_to_boolean(value)
46
52
  if value == true || value == false
47
53
  value
@@ -50,8 +56,9 @@ class Column
50
56
  end
51
57
  end
52
58
 
59
+ # Are you a Boolean?
53
60
  def boolean?
54
- self.type == 'boolean'
61
+ self.type == 'Boolean'
55
62
  end
56
63
 
57
64
 
@@ -14,6 +14,7 @@ class MDB
14
14
  # @tables = create_table_objects
15
15
  end
16
16
 
17
+ # consumer of poor, weak MDBTools.faked_count
17
18
  def count(table_name, attribute)
18
19
  MDBTools.faked_count(@mdb_file, table_name, attribute)
19
20
  end
@@ -7,6 +7,7 @@ module MDBTools
7
7
  SANITIZER = /^\w\.\_/ # dumb filter for SQL arguments
8
8
  BACKENDS = %w{ access mysql oracle postgres sybase }
9
9
 
10
+ # test for existence and usability of file
10
11
  def check_file(mdb_file)
11
12
  raise ArgumentError, "File not found: #{mdb_file}" unless File.exist?(mdb_file)
12
13
  @mdb_version = `mdb-ver #{mdb_file} 2>&1`.chomp
@@ -16,6 +17,7 @@ module MDBTools
16
17
  mdb_file
17
18
  end
18
19
 
20
+ # runs mdb_version. A blank version indicates an unusable file
19
21
  def valid_file?(file)
20
22
  !mdb_version(file).blank?
21
23
  end
@@ -24,6 +26,8 @@ module MDBTools
24
26
  `mdb-ver #{file} 2> /dev/null`.chomp
25
27
  end
26
28
 
29
+ # raises an ArgumentError unless the mdb file contains a table with the specified name.
30
+ # returns the table name, otherwise.
27
31
  def check_table(mdb_file, table_name)
28
32
  unless mdb_tables(mdb_file).include?(table_name)
29
33
  raise ArgumentError, "mdbtools does not think a table named \"#{table_name}\" exists"
@@ -31,7 +35,15 @@ module MDBTools
31
35
  table_name
32
36
  end
33
37
 
34
-
38
+ # uses mdb-tables tool to return an array of table names.
39
+ # You can filter the tables by passing an array of strings as
40
+ # either the :exclude or :include key to the options hash.
41
+ # The strings will be ORed into a regex. Only one or the other of
42
+ # :exclude or :include, please.
43
+ #
44
+ # ex. mdb_tables('thing.mdb', :exclude => ['_Lookup'])
45
+ #
46
+ # ex. mdb_tables('thing.mdb', :include => ['tbl'])
35
47
  def mdb_tables(mdb_file, options = {})
36
48
  included, excluded = options[:include], options[:exclude]
37
49
  return `mdb-tables -1 #{mdb_file}`.split(LINEBREAK) if not (included || excluded)
@@ -46,8 +58,10 @@ module MDBTools
46
58
  end
47
59
  tables
48
60
  end
49
-
50
- def sql_select(mdb_file, table_name, attributes = nil, conditions=nil)
61
+
62
+ # takes an array of field names
63
+ # and some conditions to append in a WHERE clause
64
+ def sql_select_where(mdb_file, table_name, attributes = nil, conditions=nil)
51
65
  if attributes.respond_to?(:join)
52
66
  fields = attributes.join(' ')
53
67
  else
@@ -58,8 +72,12 @@ module MDBTools
58
72
  mdb_sql(mdb_file, sql)
59
73
  end
60
74
 
75
+ # forks an IO.popen running mdb-sql and discarding STDERR to /dev/null.
76
+ # The sql argument should be a single statement, 'cause I don't know
77
+ # what will happen otherwise. mdb-sql uses "\ngo" as the command terminator.
61
78
  def mdb_sql(mdb_file,sql)
62
- command = "mdb-sql -Fp -d '#{DELIMITER}' #{mdb_file}\n"
79
+ # libMDB barks on stderr quite frequently, so discard stderr entirely
80
+ command = "mdb-sql -Fp -d '#{DELIMITER}' #{mdb_file} 2> /dev/null \n"
63
81
  array = []
64
82
  IO.popen(command, 'r+') do |pipe|
65
83
  pipe << "#{sql}\ngo\n"
@@ -77,20 +95,27 @@ module MDBTools
77
95
  end
78
96
  array
79
97
  end
80
-
81
- def old_mdb_sql(mdb_file, sql)
82
- result = `echo -n #{sql} | mdb-sql -Fp -H -d '#{DELIMITER}' #{mdb_file}`.strip
83
- delimited_to_arrays(result)
84
- end
85
-
98
+
99
+ # uses mdb-sql to retrieve an array of the table's field names
86
100
  def field_names_for(mdb_file, table)
87
101
  fields = `echo -n 'select * from #{table} where 1 = 2' | mdb-sql -Fp -d '#{DELIMITER}' #{mdb_file}`.chomp.sub(/^\n+/, '')
88
102
  fields.split(DELIMITER)
89
103
  end
90
104
 
91
105
 
92
-
93
- def compile_conditions(conditions_hash, *args)
106
+ # takes a hash where keys are column names, values are search values
107
+ # and returns a string that you can use in a WHERE clause
108
+ #
109
+ # ex. compile_conditions(:first_name => 'Summer', :last_name => 'Roberts')
110
+ # gives "first_name like '%Summer%' AND last_name like '%Roberts%'
111
+ #
112
+ # if you want to use an operator other than LIKE, give compile_conditions
113
+ # a block that accepts column_name and value and does something interesting
114
+ #
115
+ # compile_conditions(:age => 18) {|name, value| "#{name} = #{value}"}
116
+ #
117
+ # the condition phrases are all ANDed together before insertion into a WHERE clause
118
+ def compile_conditions(conditions_hash)
94
119
  conditions = conditions_hash.sort_by{|k,v| k.to_s}.map do |column_name, value|
95
120
  if block_given?
96
121
  yield column_name, value
@@ -100,10 +125,15 @@ module MDBTools
100
125
  end.join(' AND ')
101
126
  end
102
127
 
128
+ # really dumb way to get a count. Does a SELECT and call size on the results
103
129
  def faked_count(*args)
104
- sql_select(*args).size
130
+ sql_select_where(*args).size
105
131
  end
106
132
 
133
+ # convenience method, not really used with ActiveMDB.
134
+ # Valid options are :format, :headers, and :sanitize,
135
+ # which correspond rather directly to the underlying mdb-export arguments.
136
+ # Defaults to :format => 'sql', :headers => false, :sanitize => true
107
137
  def mdb_export(mdb_file, table_name, options = {})
108
138
  defaults = { :format => 'sql',
109
139
  :headers => false,
@@ -126,16 +156,18 @@ module MDBTools
126
156
  `mdb-export #{args} #{mdb_file} #{table_name.to_s.dump}`
127
157
  end
128
158
 
159
+ # wrapper for DESCRIBE TABLE using mdb-sql
129
160
  def describe_table(mdb_file, table_name)
130
161
  command = "describe table \"#{table_name}\""
131
162
  mdb_sql(mdb_file,command)
132
163
  end
133
164
 
165
+ # wrapper for mdb-schema, returns SQL statements
134
166
  def mdb_schema(mdb_file, table_name)
135
167
  schema = `mdb-schema -T #{table_name.dump} #{mdb_file}`
136
168
  end
137
169
 
138
-
170
+ # convenience method for mdb_export to output CSV with headers.
139
171
  def table_to_csv(mdb_file, table_name)
140
172
  mdb_export(mdb_file, table_name, :format => 'csv', :headers => true)
141
173
  end
@@ -158,7 +190,8 @@ module MDBTools
158
190
  end
159
191
 
160
192
 
161
-
193
+ # helper to turn table names into standard format method names.
194
+ # Inside, it's just ActionView::Inflector.underscore
162
195
  def methodize(table_name)
163
196
  Inflector.underscore table_name
164
197
  end
@@ -167,10 +200,13 @@ module MDBTools
167
200
  BACKENDS
168
201
  end
169
202
 
203
+ # poor, weakly sanitizing gsub!.
170
204
  def sanitize!(string)
171
205
  string.gsub!(SANITIZER, '')
172
206
  end
173
207
 
208
+ # mdb-tools recognizes 1 and 0 as the boolean values.
209
+ # Make it so.
174
210
  def mdb_truth(value)
175
211
  case value
176
212
  when false
@@ -1,5 +1,6 @@
1
1
  # require 'mdb_tools'
2
2
 
3
+ # Deprecated way more than Table
3
4
  class Record
4
5
  include MDBTools
5
6
  include Enumerable
@@ -1,5 +1,6 @@
1
1
  # require 'mdb_tools'
2
2
 
3
+ # Deprecated. So very deprecated.
3
4
  class Table
4
5
  include MDBTools
5
6
 
@@ -22,6 +23,7 @@ class Table
22
23
  self.columns.detect {|c| c.method_name == method_name }
23
24
  end
24
25
 
26
+ # returns an array of column names
25
27
  def column_names
26
28
  columns.collect {|x| methodize(x.method_name).to_sym}
27
29
  end
@@ -34,20 +36,24 @@ class Table
34
36
  def to_csv
35
37
  table_to_csv(mdb_file, table_name)
36
38
  end
37
-
38
- def to_sql
39
- raise 'not implemented'
40
- end
41
-
39
+
40
+ # returns the first record that meets the equality (sometimes LIKE) conditions
41
+ # of the supplied hash. No comparison operators available at the moment.
42
+ #
43
+ # find_first :superhero_name => 'The Ironist', :powers => 'Wit'
44
+ #
45
+ # mdb-sql doesn't implement LIMIT yet, so this method pulls all results and
46
+ # calls Array#first on them. Ooky.
42
47
  def find_first(conditions_hash)
43
48
  rekey_hash(conditions_hash)
44
49
  result = sql_search(conditions_hash).first
45
50
  create_record(result)
46
51
  end
47
52
 
53
+
48
54
  def find_all(conditions_hash={})
49
55
  if conditions_hash.empty?
50
- return sql_select(mdb_file, table_name, nil, '1 = 1').collect {|r| create_record(r)}
56
+ return sql_select_where(mdb_file, table_name, nil, '1 = 1').collect {|r| create_record(r)}
51
57
  end
52
58
  rekey_hash(conditions_hash)
53
59
  sql_search(conditions_hash).collect {|r| create_record(r) }
@@ -81,7 +87,7 @@ class Table
81
87
  "#{column.name} like '%#{value}%'"
82
88
  end
83
89
  end
84
- sql_select(mdb_file, table_name, nil, conditions)
90
+ sql_select_where(mdb_file, table_name, nil, conditions)
85
91
  end
86
92
 
87
93
 
@@ -18,8 +18,6 @@ class BaseTest < Test::Unit::TestCase
18
18
  set_primary_key 'Room'
19
19
  end
20
20
 
21
-
22
-
23
21
  def test_setting_mdb_file
24
22
  assert_equal TEST_DB, Employee.mdb_file
25
23
  end
@@ -60,18 +58,37 @@ class BaseTest < Test::Unit::TestCase
60
58
  end
61
59
 
62
60
  def test_instantiate
63
- hash = [{"Department"=>"Engineering", "Gender"=>"M", "Room"=>"6072", "Title"=>"Programmer", "Emp_Id"=>"1045", "First_Name"=>"Robert", "Last_Name"=>"Weinfeld"}]
61
+ hash = {"Department"=>"Engineering", "Gender"=>"M", "Room"=>"6072", "Title"=>"Programmer", "Emp_Id"=>"1045", "First_Name"=>"Robert", "Last_Name"=>"Weinfeld"}
64
62
  record = Employee.send(:instantiate, hash)
65
63
  assert_equal hash, record.instance_variable_get('@attributes')
64
+ hash = {"Area"=>"135.38","Entity_Handle"=>"9D7A","Room"=>"6004","Room_Type"=>"STOR-GEN"}
65
+ record = Room.send(:instantiate, hash)
66
+ assert_kind_of Float, record.instance_variable_get('@attributes')['Area']
66
67
  end
67
68
 
68
- def test_sql_search
69
- record = Employee.sql_search(:Room => '6072').first
69
+ def test_find_from_hash
70
+ record = Employee.find_from_hash(:Room => '6072').first
70
71
  assert_kind_of Employee, record
72
+ record = Room.find_first(:Area => 135.38)
73
+ assert_kind_of Room, record
74
+ end
75
+
76
+ def test_find_where
77
+ weinstein = Employee.find_where( "Last_Name = 'Weinfeld'").first
78
+ assert_equal 'Robert', weinstein.First_Name
79
+ end
80
+
81
+ def test_conditions_from_hash
82
+ hash = {:Room => '6072'}
83
+ conditions = "Room LIKE '%6072%'"
84
+ assert_equal conditions, Employee.conditions_from_hash(hash)
85
+ hash = {:Area => 45}
86
+ conditions = "Area = 45"
87
+ assert_equal conditions, Room.conditions_from_hash(hash)
71
88
  end
72
89
 
73
90
  def test_attribute_magic
74
- record = Employee.sql_search(:Room => '6072').first
91
+ record = Employee.find_from_hash(:Room => '6072').first
75
92
  assert_equal '6072', record.Room
76
93
  end
77
94
 
@@ -80,7 +97,10 @@ class BaseTest < Test::Unit::TestCase
80
97
  assert_equal 2, Employee.find_all(:First_Name => 'G').size
81
98
  end
82
99
 
83
-
100
+ def test_column_for
101
+ assert_kind_of Column, Employee.column_for(:Room)
102
+ assert_nil Employee.column_for('foo')
103
+ end
84
104
 
85
105
 
86
106
  end
@@ -0,0 +1,19 @@
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 ColumnTest < Test::Unit::TestCase
6
+
7
+
8
+
9
+ def setup
10
+ @c1 = Column.new('is_available', 'Boolean', 0)
11
+ end
12
+
13
+ def test_boolean_column
14
+ assert_equal false, @c1.type_cast(0)
15
+ end
16
+
17
+
18
+
19
+ end
@@ -97,9 +97,9 @@ class MDBToolsTest < Test::Unit::TestCase
97
97
  # assert_equal TORBATI_Y, employee_hash.first
98
98
  # end
99
99
 
100
- def test_sql_select
100
+ def test_sql_select_where
101
101
  yo = {"Department"=>"Engineering", "Gender"=>"F", "Room"=>"6044", "Title"=>"Programmer", "Emp_Id"=>"1000", "First_Name"=>"Yolanda", "Last_Name"=>"Torbati"}
102
- assert_equal yo, sql_select(TEST_DB, 'Employee', ['*'], "First_Name LIKE 'Yolanda'" ).first
102
+ assert_equal yo, sql_select_where(TEST_DB, 'Employee', ['*'], "First_Name LIKE 'Yolanda'" ).first
103
103
  end
104
104
 
105
105
  def test_compile_conditions
@@ -107,8 +107,8 @@ class MDBToolsTest < Test::Unit::TestCase
107
107
  assert_equal "baz like '%1%' AND foo like '%bar%' AND nark like '%noo%'", compile_conditions(conditions)
108
108
  end
109
109
 
110
- def test_compiled_sql_select
111
- sql_select(TEST_DB, 'Employee', nil, compile_conditions(:first_name => 'Yolanda'))
110
+ def test_compiled_sql_select_where
111
+ sql_select_where(TEST_DB, 'Employee', nil, compile_conditions(:first_name => 'Yolanda'))
112
112
  end
113
113
 
114
114
  def test_count
metadata CHANGED
@@ -3,13 +3,13 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: activemdb
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
7
- date: 2007-04-05 00:00:00 -05:00
8
- summary: ActiveRecordy wrapper around MDB Tools, which lets POSIX platforms read MS Access (.mdb) files
6
+ version: 0.2.1
7
+ date: 2007-04-10 00:00:00 -05:00
8
+ summary: ActiveRecordy wrapper around MDB Tools, allowing POSIX platforms to read MS Access (.mdb) files
9
9
  require_paths:
10
10
  - lib
11
11
  email: automatthew@gmail.com
12
- homepage: http://rubyforge.org/projects/activemdb/
12
+ homepage: http://activemdb.rubyforge.org/
13
13
  rubyforge_project: activemdb
14
14
  description: Intended for exploration and migration, not production. And it's *READ ONLY*, so don't try to get fresh. ActiveMDB provides a wrapper of varying thickness around the utilities from Brian Bruns's MDB Tools project (http://mdbtools.sourceforge.net/). Kudos to Mr. Bruns.
15
15
  autorequire:
@@ -48,6 +48,7 @@ files:
48
48
  - support/a.insert
49
49
  - test/test_activemdb.rb
50
50
  - test/test_base.rb
51
+ - test/test_column.rb
51
52
  - test/test_helper.rb
52
53
  - test/test_mdb.rb
53
54
  - test/test_mdb_tools.rb
@@ -56,6 +57,7 @@ files:
56
57
  test_files:
57
58
  - test/test_activemdb.rb
58
59
  - test/test_base.rb
60
+ - test/test_column.rb
59
61
  - test/test_helper.rb
60
62
  - test/test_mdb.rb
61
63
  - test/test_mdb_tools.rb