activemdb 0.2.0 → 0.2.1

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