dbf 0.5.4 → 1.0.0

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,38 +1,47 @@
1
1
  describe DBF, :shared => true do
2
- specify "sum of field lengths should equal record length specified in header" do
3
- header_record_length = @reader.instance_eval {@record_length}
4
- sum_of_field_lengths = @reader.fields.inject(1) {|sum, field| sum + field.length}
2
+ specify "sum of column lengths should equal record length specified in header" do
3
+ header_record_length = @table.instance_eval {@record_length}
4
+ sum_of_column_lengths = @table.columns.inject(1) {|sum, column| sum + column.length}
5
5
 
6
- header_record_length.should == sum_of_field_lengths
6
+ header_record_length.should == sum_of_column_lengths
7
7
  end
8
8
 
9
9
  specify "records should be instances of DBF::Record" do
10
- @reader.records.all? {|record| record.should be_an_instance_of(DBF::Record)}
10
+ @table.records.all? {|record| record.should be_an_instance_of(DBF::Record)}
11
11
  end
12
12
 
13
- specify "fields should be instances of DBF::Field" do
14
- @reader.fields.all? {|field| field.should be_an_instance_of(DBF::Field)}
13
+ specify "columns should be instances of DBF::Column" do
14
+ @table.columns.all? {|column| column.should be_an_instance_of(DBF::Column)}
15
15
  end
16
16
 
17
- specify "field names should not be blank" do
18
- @reader.fields.all? {|field| field.name.should_not be_empty}
17
+ specify "column names should not be blank" do
18
+ @table.columns.all? {|column| column.name.should_not be_empty}
19
19
  end
20
20
 
21
- specify "field types should be valid" do
22
- valid_field_types = %w(C N L D M F B G P Y T I V X @ O +)
23
- @reader.fields.all? {|field| valid_field_types.should include(field.type)}
21
+ specify "column types should be valid" do
22
+ valid_column_types = %w(C N L D M F B G P Y T I V X @ O +)
23
+ @table.columns.all? {|column| valid_column_types.should include(column.type)}
24
24
  end
25
25
 
26
- specify "field lengths should be instances of Fixnum" do
27
- @reader.fields.all? {|field| field.length.should be_an_instance_of(Fixnum)}
26
+ specify "column lengths should be instances of Fixnum" do
27
+ @table.columns.all? {|column| column.length.should be_an_instance_of(Fixnum)}
28
28
  end
29
29
 
30
- specify "field lengths should be larger than 0" do
31
- @reader.fields.all? {|field| field.length.should > 0}
30
+ specify "column lengths should be larger than 0" do
31
+ @table.columns.all? {|column| column.length.should > 0}
32
32
  end
33
33
 
34
- specify "field decimals should be instances of Fixnum" do
35
- @reader.fields.all? {|field| field.decimal.should be_an_instance_of(Fixnum)}
34
+ specify "column decimals should be instances of Fixnum" do
35
+ @table.columns.all? {|column| column.decimal.should be_an_instance_of(Fixnum)}
36
+ end
37
+
38
+ specify "column read accessors should return the attribute after typecast" do
39
+ if @table.options[:accessors]
40
+ @table.columns do |column|
41
+ record = table.records.first
42
+ record.send(column.name).should == record[column.name]
43
+ end
44
+ end
36
45
  end
37
46
 
38
47
  end
@@ -3,21 +3,21 @@ require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 03 (dBase III without memo file)" do
5
5
  before(:each) do
6
- @reader = DBF::Reader.new "#{DB_PATH}/dbase_03.dbf"
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_03.dbf"
7
7
  end
8
8
 
9
9
  it_should_behave_like "DBF"
10
10
 
11
11
  it "should report the correct version number" do
12
- @reader.version.should == "03"
12
+ @table.version.should == "03"
13
13
  end
14
14
 
15
15
  it "should have a memo file" do
16
- @reader.should_not have_memo_file
16
+ @table.should_not have_memo_file
17
17
  end
18
18
 
19
19
  it "should report the correct memo type" do
20
- @reader.memo_file_format.should be_nil
20
+ @table.memo_file_format.should be_nil
21
21
  end
22
22
 
23
23
  end
@@ -3,21 +3,21 @@ require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 30 (Visual FoxPro)" do
5
5
  before(:each) do
6
- @reader = DBF::Reader.new "#{DB_PATH}/dbase_30.dbf"
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
7
7
  end
8
8
 
9
9
  it_should_behave_like "DBF"
10
10
 
11
11
  it "should report the correct version number" do
12
- @reader.version.should == "30"
12
+ @table.version.should == "30"
13
13
  end
14
14
 
15
15
  it "should have a memo file" do
16
- @reader.should have_memo_file
16
+ @table.should have_memo_file
17
17
  end
18
18
 
19
19
  it "should report the correct memo type" do
20
- @reader.memo_file_format.should == :fpt
20
+ @table.memo_file_format.should == :fpt
21
21
  end
22
22
 
23
23
  end
@@ -3,21 +3,21 @@ require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 83 (dBase III with memo file)" do
5
5
  before(:each) do
6
- @reader = DBF::Reader.new "#{DB_PATH}/dbase_83.dbf"
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
7
7
  end
8
8
 
9
9
  it_should_behave_like "DBF"
10
10
 
11
11
  it "should report the correct version number" do
12
- @reader.version.should == "83"
12
+ @table.version.should == "83"
13
13
  end
14
14
 
15
15
  it "should have a memo file" do
16
- @reader.should have_memo_file
16
+ @table.should have_memo_file
17
17
  end
18
18
 
19
19
  it "should report the correct memo type" do
20
- @reader.memo_file_format.should == :dbt
20
+ @table.memo_file_format.should == :dbt
21
21
  end
22
22
 
23
23
  end
@@ -3,21 +3,21 @@ require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 8b (dBase IV with memo file)" do
5
5
  before(:each) do
6
- @reader = DBF::Reader.new "#{DB_PATH}/dbase_8b.dbf"
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_8b.dbf"
7
7
  end
8
8
 
9
9
  it_should_behave_like "DBF"
10
10
 
11
11
  it "should report the correct version number" do
12
- @reader.version.should == "8b"
12
+ @table.version.should == "8b"
13
13
  end
14
14
 
15
15
  it "should have a memo file" do
16
- @reader.should have_memo_file
16
+ @table.should have_memo_file
17
17
  end
18
18
 
19
19
  it "should report the correct memo type" do
20
- @reader.memo_file_format.should == :dbt
20
+ @table.memo_file_format.should == :dbt
21
21
  end
22
22
 
23
23
  end
@@ -3,21 +3,21 @@ require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type f5 (FoxPro with memo file)" do
5
5
  before(:each) do
6
- @reader = DBF::Reader.new "#{DB_PATH}/dbase_f5.dbf"
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_f5.dbf"
7
7
  end
8
8
 
9
9
  it_should_behave_like "DBF"
10
10
 
11
11
  it "should report the correct version number" do
12
- @reader.version.should == "f5"
12
+ @table.version.should == "f5"
13
13
  end
14
14
 
15
15
  it "should have a memo file" do
16
- @reader.should have_memo_file
16
+ @table.should have_memo_file
17
17
  end
18
18
 
19
19
  it "should report the correct memo type" do
20
- @reader.memo_file_format.should == :fpt
20
+ @table.memo_file_format.should == :fpt
21
21
  end
22
22
 
23
23
  end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe DBF::Column, "when initialized" do
4
+
5
+ before(:each) do
6
+ @column = DBF::Column.new "ColumnName", "N", 1, 0
7
+ end
8
+
9
+ it "should set the #name accessor" do
10
+ @column.name.should == "ColumnName"
11
+ end
12
+
13
+ it "should set the #type accessor" do
14
+ @column.type.should == "N"
15
+ end
16
+
17
+ it "should set the #length accessor" do
18
+ @column.length.should == 1
19
+ end
20
+
21
+ it "should set the #decimal accessor" do
22
+ @column.decimal.should == 0
23
+ end
24
+
25
+ it "should raise an error if length is greater than 0" do
26
+ lambda { column = DBF::Column.new "ColumnName", "N", -1, 0 }.should raise_error(DBF::ColumnLengthError)
27
+ end
28
+
29
+ it "should strip null characters from the name" do
30
+ column = DBF::Column.new "Column\0Name\0", "N", 1, 0
31
+ column.name.should == "ColumnName"
32
+ end
33
+
34
+ end
@@ -2,30 +2,30 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
 
3
3
  describe DBF::Record, "when initialized" do
4
4
 
5
- it "should typecast number fields with decimals == 0 to Integer" do
6
- reader = DBF::Reader.new "#{DB_PATH}/dbase_83.dbf"
7
- reader.field("ID").type.should == "N"
8
- reader.field("ID").decimal.should == 0
9
- reader.records.all? {|record| record["ID"].should be_kind_of(Integer)}
5
+ it "should typecast number columns with decimals == 0 to Integer" do
6
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
7
+ table.column("ID").type.should == "N"
8
+ table.column("ID").decimal.should == 0
9
+ table.records.all? {|record| record.attributes['ID'].should be_kind_of(Integer)}
10
10
  end
11
11
 
12
- it "should typecast number fields with decimals > 0 to Float" do
13
- reader = DBF::Reader.new "#{DB_PATH}/dbase_83.dbf"
14
- reader.field("ID").type.should == "N"
15
- reader.field("COST").decimal.should == 2
16
- reader.records.all? {|record| record["COST"].should be_kind_of(Float)}
12
+ it "should typecast number columns with decimals > 0 to Float" do
13
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
14
+ table.column("ID").type.should == "N"
15
+ table.column("COST").decimal.should == 2
16
+ table.records.all? {|record| record.attributes['COST'].should be_kind_of(Float)}
17
17
  end
18
18
 
19
- it "should typecast memo fields to String" do
20
- reader = DBF::Reader.new "#{DB_PATH}/dbase_83.dbf"
21
- reader.field("DESC").type.should == "M"
22
- reader.records.all? {|record| record["DESC"].should be_kind_of(String)}
19
+ it "should typecast memo columns to String" do
20
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
21
+ table.column("DESC").type.should == "M"
22
+ table.records.all? {|record| record.attributes['DESC'].should be_kind_of(String)}
23
23
  end
24
24
 
25
- it "should typecast logical fields to True or False" do
26
- reader = DBF::Reader.new "#{DB_PATH}/dbase_30.dbf"
27
- reader.field("WEBINCLUDE").type.should == "L"
28
- reader.records.all? {|record| record["WEBINCLUDE"].should satisfy {|v| v == true || v == false}}
25
+ it "should typecast logical columns to True or False" do
26
+ table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
27
+ table.column("WEBINCLUDE").type.should == "L"
28
+ table.records.all? {|record| record.attributes["WEBINCLUDE"].should satisfy {|v| v == true || v == false}}
29
29
  end
30
30
 
31
31
  end
@@ -0,0 +1,168 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe DBF::Table, "when initialized" do
4
+
5
+ before(:all) do
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
7
+ end
8
+
9
+ it "should load the data file" do
10
+ @table.data.should be_kind_of(File)
11
+ end
12
+
13
+ it "should locate load the memo file" do
14
+ @table.has_memo_file?.should be_true
15
+ @table.instance_eval("@memo").should be_kind_of(File)
16
+ end
17
+
18
+ it "should determine the memo file format" do
19
+ @table.memo_file_format.should == :dbt
20
+ end
21
+
22
+ it "should determine the memo block size" do
23
+ @table.memo_block_size.should == 512
24
+ end
25
+
26
+ it "should default to loading all records into memory" do
27
+ @table.options[:in_memory].should be_true
28
+ end
29
+
30
+ it "should determine the number of columns in each record" do
31
+ @table.columns.size.should == 15
32
+ end
33
+
34
+ it "should determine the number of records in the database" do
35
+ @table.record_count.should == 67
36
+ end
37
+
38
+ it "should determine the database version" do
39
+ @table.version.should == "83"
40
+ end
41
+
42
+ it "should set the in_memory option" do
43
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf", :in_memory => false
44
+ table.options[:in_memory].should be_false
45
+ end
46
+
47
+ end
48
+
49
+ describe DBF::Table, "when the in_memory flag is true" do
50
+
51
+ before(:each) do
52
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
53
+ end
54
+
55
+ it "should build the records array from disk only on the first request" do
56
+ @table.expects(:get_all_records_from_file).at_most_once.returns([])
57
+ 3.times { @table.records }
58
+ end
59
+
60
+ it "should read from the records array when using the record() method" do
61
+ @table.expects(:get_all_records_from_file).at_most_once.returns([])
62
+ @table.expects(:get_record_from_file).never
63
+ @table.expects(:records).times(2).returns([])
64
+ @table.record(1)
65
+ @table.record(10)
66
+ end
67
+
68
+ end
69
+
70
+ describe DBF::Table, "when the in_memory flag is false" do
71
+
72
+ it "should read the records from disk on every request" do
73
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf", :in_memory => false
74
+ table.expects(:get_all_records_from_file).times(3).returns([])
75
+ 3.times { table.records }
76
+ end
77
+ end
78
+
79
+ describe DBF::Table, "schema" do
80
+
81
+ it "should match test schema " do
82
+ table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
83
+ control_schema = File.read(File.dirname(__FILE__) + '/../fixtures/dbase_83_schema.txt')
84
+
85
+ table.schema.should == control_schema
86
+ end
87
+
88
+ end
89
+
90
+ describe DBF::Table, "find(index)" do
91
+
92
+ before(:all) do
93
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
94
+ end
95
+
96
+ it "should return the correct record" do
97
+ @table.find(5).should == @table.record(5)
98
+ end
99
+
100
+ end
101
+
102
+ describe DBF::Table, "find(:all)" do
103
+
104
+ before(:all) do
105
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
106
+ end
107
+
108
+ it "should return all records if options are empty" do
109
+ @table.find(:all).should == @table.records
110
+ end
111
+
112
+ it "should return matching records when used with options" do
113
+ @table.find(:all, "WEIGHT" => 0.0).should == @table.records.select {|r| r.attributes["WEIGHT"] == 0.0}
114
+ end
115
+
116
+ it "with multiple options should search for all search terms as if using AND" do
117
+ @table.find(:all, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg").should == []
118
+ end
119
+ end
120
+
121
+ describe DBF::Table, "find(:first)" do
122
+
123
+ before(:all) do
124
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
125
+ end
126
+
127
+ it "should return the first record if options are empty" do
128
+ @table.find(:first).should == @table.records.first
129
+ end
130
+
131
+ it "should return the first matching record when used with options" do
132
+ @table.find(:first, "CODE" => "C").should == @table.record(5)
133
+ end
134
+
135
+ it "with multiple options should search for all search terms as if using AND" do
136
+ @table.find(:first, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg").should be_nil
137
+ end
138
+ end
139
+
140
+ describe DBF::Table do
141
+
142
+ before(:each) do
143
+ @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
144
+ end
145
+
146
+ it "should reload all data when sent #reload!" do
147
+ @table.records
148
+ @table.instance_eval("@records").should be_kind_of(Array)
149
+ @table.reload!
150
+ @table.instance_eval("@records").should be_nil
151
+ end
152
+
153
+ it "should return a DBF::Field object when sent #column with a valid column_name given as a string or symbol" do
154
+ @table.column("IMAGE").should be_kind_of(DBF::Column)
155
+ @table.column(:IMAGE).should be_kind_of(DBF::Column)
156
+ end
157
+
158
+ it "should return nil when sent #column with an invalid column_name given as a string or symbol" do
159
+ @table.column("NOTANIMAGE").should be_nil
160
+ @table.column(:NOTANIMAGE).should be_nil
161
+ end
162
+
163
+ it "should return a text description of the database type when sent #version_description" do
164
+ @table.version_description.should == "dBase III with memo file"
165
+ end
166
+
167
+ end
168
+