dbf 0.5.4 → 1.0.0

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