dbf 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,4 +1,13 @@
1
+ == 1.0.5
2
+
3
+ * Strip non-ascii characters from column names
4
+
5
+ == 1.0.4
6
+
7
+ * Underscore column names when dumping schemas (FieldId becomes field_id)
8
+
1
9
  == 1.0.3
10
+
2
11
  * Add support for Visual Foxpro Integer and Datetime columns
3
12
 
4
13
  == 1.0.2
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'hoe'
2
2
  require 'spec/rake/spectask'
3
3
 
4
4
  PKG_NAME = "dbf"
5
- PKG_VERSION = "1.0.3"
5
+ PKG_VERSION = "1.0.5"
6
6
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
7
7
 
8
8
  Hoe.new PKG_NAME, PKG_VERSION do |p|
data/lib/dbf/column.rb CHANGED
@@ -6,7 +6,47 @@ module DBF
6
6
 
7
7
  def initialize(name, type, length, decimal)
8
8
  raise ColumnLengthError, "field length must be greater than 0" unless length > 0
9
- @name, @type, @length, @decimal = name.gsub(/\0/, ''), type, length, decimal
9
+ @name, @type, @length, @decimal = strip_non_ascii_chars(name), type, length, decimal
10
+ end
11
+
12
+ def schema_definition
13
+ "\"#{underscore(name)}\", " +
14
+ case type
15
+ when "N" # number
16
+ if decimal > 0
17
+ ":float"
18
+ else
19
+ ":integer"
20
+ end
21
+ when "D" # date
22
+ ":datetime"
23
+ when "L" # boolean
24
+ ":boolean"
25
+ when "M" # memo
26
+ ":text"
27
+ else
28
+ ":string, :limit => #{length}"
29
+ end +
30
+ "\n"
31
+ end
32
+
33
+ private
34
+
35
+ def underscore(camel_cased_word)
36
+ camel_cased_word.to_s.gsub(/::/, '/').
37
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
38
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
39
+ tr("-", "_").
40
+ downcase
41
+ end
42
+
43
+ def strip_non_ascii_chars(s)
44
+ clean = ''
45
+ s.each_byte do |char|
46
+ clean << char if char > 31 && char < 128
47
+ end
48
+ clean
10
49
  end
11
50
  end
51
+
12
52
  end
data/lib/dbf/globals.rb CHANGED
@@ -23,4 +23,6 @@ module DBF
23
23
  MS_PER_HOUR = MS_PER_MINUTE * 60
24
24
 
25
25
  class DBFError < StandardError; end
26
+ class InvalidColumnName < DBFError; end
27
+ class InvalidColumnLength < DBFError; end
26
28
  end
data/lib/dbf/record.rb CHANGED
@@ -29,31 +29,30 @@ module DBF
29
29
 
30
30
  def initialize_values(columns)
31
31
  columns.each do |column|
32
- case column.type
32
+ @attributes[column.name] = case column.type
33
33
  when 'N' # number
34
- @attributes[column.name] = column.decimal.zero? ? unpack_string(column).to_i : unpack_string(column).to_f
34
+ column.decimal.zero? ? unpack_string(column).to_i : unpack_string(column).to_f
35
35
  when 'D' # date
36
36
  raw = unpack_string(column).strip
37
37
  unless raw.empty?
38
+ parts = raw.match(DATE_REGEXP).captures.map {|n| n.to_i}
38
39
  begin
39
- parts = raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i}
40
- @attributes[column.name] = Time.gm(*parts)
40
+ Time.gm(*parts)
41
41
  rescue
42
- parts = raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i}
43
- @attributes[column.name] = Date.new(*parts)
42
+ Date.new(*parts)
44
43
  end
45
44
  end
46
45
  when 'M' # memo
47
46
  starting_block = unpack_string(column).to_i
48
- @attributes[column.name] = read_memo(starting_block)
47
+ read_memo(starting_block)
49
48
  when 'L' # logical
50
- @attributes[column.name] = unpack_string(column) =~ /^(y|t)$/i ? true : false
49
+ unpack_string(column) =~ /^(y|t)$/i ? true : false
51
50
  when 'I' # integer
52
- @attributes[column.name] = unpack_integer(column)
51
+ unpack_integer(column)
53
52
  when 'T' # datetime
54
- @attributes[column.name] = unpack_datetime(column)
53
+ unpack_datetime(column)
55
54
  else
56
- @attributes[column.name] = unpack_string(column).strip
55
+ unpack_string(column).strip
57
56
  end
58
57
  end
59
58
  end
data/lib/dbf/table.rb CHANGED
@@ -105,19 +105,15 @@ module DBF
105
105
  # for the record to be returned. The equivalent SQL would be "WHERE key1 = 'value1'
106
106
  # AND key2 = 'value2'".
107
107
  def find(command, options = {})
108
+ results = options.empty? ? records : records.select {|record| all_values_match?(record, options)}
109
+
108
110
  case command
109
111
  when Fixnum
110
112
  record(command)
111
113
  when :all
112
- return records if options.empty?
113
- records.select do |record|
114
- options.map {|key, value| record.attributes[key.to_s] == value}.all?
115
- end
114
+ results
116
115
  when :first
117
- return records.first if options.empty?
118
- records.detect do |record|
119
- options.map {|key, value| record.attributes[key.to_s] == value}.all?
120
- end
116
+ results.first
121
117
  end
122
118
  end
123
119
 
@@ -151,24 +147,7 @@ module DBF
151
147
  s = "ActiveRecord::Schema.define do\n"
152
148
  s << " create_table \"#{File.basename(@data.path, ".*")}\" do |t|\n"
153
149
  columns.each do |column|
154
- s << " t.column \"#{column.name}\""
155
- case column.type
156
- when "N" # number
157
- if column.decimal > 0
158
- s << ", :float"
159
- else
160
- s << ", :integer"
161
- end
162
- when "D" # date
163
- s << ", :datetime"
164
- when "L" # boolean
165
- s << ", :boolean"
166
- when "M" # memo
167
- s << ", :text"
168
- else
169
- s << ", :string, :limit => #{column.length}"
170
- end
171
- s << "\n"
150
+ s << " t.column #{column.schema_definition}"
172
151
  end
173
152
  s << " end\nend"
174
153
 
@@ -206,8 +185,8 @@ module DBF
206
185
  @columns = []
207
186
  @column_count.times do
208
187
  name, type, length, decimal = @data.read(32).unpack('a10 x a x4 C2')
209
- if length > 0 && name.strip.any?
210
- @columns << Column.new(name, type, length, decimal)
188
+ if length > 0
189
+ @columns << Column.new(name.strip, type, length, decimal)
211
190
  end
212
191
  end
213
192
  # Reset the column count
@@ -263,6 +242,10 @@ module DBF
263
242
  end
264
243
  end
265
244
  end
245
+
246
+ def all_values_match?(record, options)
247
+ options.map {|key, value| record.attributes[key.to_s] == value}.all?
248
+ end
266
249
  end
267
250
 
268
251
  end
@@ -1,19 +1,19 @@
1
1
  ActiveRecord::Schema.define do
2
2
  create_table "dbase_83" do |t|
3
- t.column "ID", :integer
4
- t.column "CATCOUNT", :integer
5
- t.column "AGRPCOUNT", :integer
6
- t.column "PGRPCOUNT", :integer
7
- t.column "ORDER", :integer
8
- t.column "CODE", :string, :limit => 50
9
- t.column "NAME", :string, :limit => 100
10
- t.column "THUMBNAIL", :string, :limit => 254
11
- t.column "IMAGE", :string, :limit => 254
12
- t.column "PRICE", :float
13
- t.column "COST", :float
14
- t.column "DESC", :text
15
- t.column "WEIGHT", :float
16
- t.column "TAXABLE", :boolean
17
- t.column "ACTIVE", :boolean
3
+ t.column "id", :integer
4
+ t.column "catcount", :integer
5
+ t.column "agrpcount", :integer
6
+ t.column "pgrpcount", :integer
7
+ t.column "order", :integer
8
+ t.column "code", :string, :limit => 50
9
+ t.column "name", :string, :limit => 100
10
+ t.column "thumbnail", :string, :limit => 254
11
+ t.column "image", :string, :limit => 254
12
+ t.column "price", :float
13
+ t.column "cost", :float
14
+ t.column "desc", :text
15
+ t.column "weight", :float
16
+ t.column "taxable", :boolean
17
+ t.column "active", :boolean
18
18
  end
19
19
  end
@@ -26,8 +26,8 @@ describe DBF::Column, "when initialized" do
26
26
  lambda { column = DBF::Column.new "ColumnName", "N", -1, 0 }.should raise_error(DBF::ColumnLengthError)
27
27
  end
28
28
 
29
- it "should strip null characters from the name" do
30
- column = DBF::Column.new "Column\0Name\0", "N", 1, 0
29
+ it "should strip non-ascii characters from the name" do
30
+ column = DBF::Column.new "Col\200umn\0Name\037", "N", 1, 0
31
31
  column.name.should == "ColumnName"
32
32
  end
33
33
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: dbf
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.3
7
- date: 2007-09-02 00:00:00 -07:00
6
+ version: 1.0.5
7
+ date: 2007-11-27 00:00:00 -08:00
8
8
  summary: A small fast library for reading dBase, xBase, Clipper and FoxPro database files.
9
9
  require_paths:
10
10
  - lib