dbf 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ == 1.2.2
2
+
3
+ * Handle invalid date fields
4
+
1
5
  == 1.2.1
2
6
 
3
7
  * Add support for F field type (Float)
@@ -1,5 +1,5 @@
1
1
  ---
2
- :build:
3
- :patch: 1
4
2
  :major: 1
5
3
  :minor: 2
4
+ :build:
5
+ :patch: 2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dbf}
8
- s.version = "1.2.1"
8
+ s.version = "1.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Keith Morrison"]
12
- s.date = %q{2010-03-30}
12
+ s.date = %q{2010-04-01}
13
13
  s.default_executable = %q{dbf}
14
14
  s.description = %q{A small fast library for reading dBase, xBase, Clipper and FoxPro database files.}
15
15
  s.email = %q{keithm@infused.org}
@@ -28,21 +28,31 @@ module DBF
28
28
  case type
29
29
  when 'N' # number
30
30
  unpack_number(value)
31
+ when 'I' # integer
32
+ unpack_integer(value)
31
33
  when 'F' # float
32
34
  unpack_float(value)
33
35
  when 'D' # date
34
- value.to_date unless value.blank?
35
- when 'L' # logical
36
- boolean(value)
37
- when 'I' # integer
38
- unpack_integer(value)
36
+ decode_date(value)
39
37
  when 'T' # datetime
40
38
  decode_datetime(value)
39
+ when 'L' # logical
40
+ boolean(value)
41
41
  else
42
42
  value.to_s.strip
43
43
  end
44
44
  end
45
45
 
46
+ # Decode a Date value
47
+ #
48
+ # @param [String] value
49
+ # @return [Date]
50
+ def decode_date(value)
51
+ unless value.blank?
52
+ value.to_date rescue nil
53
+ end
54
+ end
55
+
46
56
  # Decode a DateTime value
47
57
  #
48
58
  # @param [String] value
@@ -6,7 +6,7 @@ describe DBF::Column do
6
6
  before do
7
7
  @column = DBF::Column.new "ColumnName", "N", 1, 0
8
8
  end
9
-
9
+
10
10
  it "should set the #name accessor" do
11
11
  @column.name.should == "ColumnName"
12
12
  end
@@ -22,83 +22,120 @@ describe DBF::Column do
22
22
  it "should set the #decimal accessor" do
23
23
  @column.decimal.should == 0
24
24
  end
25
-
26
- it "should raise an error if length is greater than 0" do
27
- lambda { DBF::Column.new "ColumnName", "N", -1, 0 }.should raise_error(DBF::ColumnLengthError)
25
+
26
+ context 'with length of 0' do
27
+ specify { lambda { DBF::Column.new "ColumnName", "N", 0, 0 }.should raise_error(DBF::ColumnLengthError) }
28
28
  end
29
29
 
30
- it "should raise error on emtpy column names" do
31
- lambda { DBF::Column.new "\xFF\xFC", "N", 1, 0 }.should raise_error(DBF::ColumnNameError)
30
+ context 'with length less than 0' do
31
+ specify { lambda { DBF::Column.new "ColumnName", "N", -1, 0 }.should raise_error(DBF::ColumnLengthError) }
32
32
  end
33
33
 
34
+ context 'with empty column name' do
35
+ specify { lambda { DBF::Column.new "\xFF\xFC", "N", 1, 0 }.should raise_error(DBF::ColumnNameError) }
36
+ end
34
37
  end
35
38
 
36
39
  context "#type_cast" do
37
- it "should cast numbers with decimals to Float" do
38
- value = "13.5"
39
- column = DBF::Column.new "ColumnName", "N", 2, 1
40
- column.type_cast(value).should == 13.5
41
- end
42
-
43
- it "should cast numbers with no decimals to Integer" do
44
- value = "135"
45
- column = DBF::Column.new "ColumnName", "N", 3, 0
46
- column.type_cast(value).should == 135
47
- end
48
-
49
- it "should cast numbers with decimals to Float" do
50
- value = "13.5"
51
- column = DBF::Column.new "ColumnName", "N", 2, 1
52
- column.type_cast(value).should == 13.5
53
- end
54
-
55
- it "should cast float numbers to Float" do
56
- value = "135"
57
- column = DBF::Column.new "ColumnName", "F", 3, 0
58
- column.type_cast(value).should == 135.0
59
- end
60
-
61
- it "should cast :integer to Integer" do
62
- value = "135"
63
- column = DBF::Column.new "ColumnName", "I", 3, 0
64
- column.type_cast(value).should == 135
65
- end
66
-
67
- it "should cast boolean to True" do
68
- value = "y"
69
- column = DBF::Column.new "ColumnName", "L", 1, 0
70
- column.type_cast(value).should == true
71
- end
72
-
73
- it "should cast boolean to False" do
74
- value = "n"
75
- column = DBF::Column.new "ColumnName", "L", 1, 0
76
- column.type_cast(value).should == false
77
- end
78
-
79
- it "should cast datetime columns to DateTime" do
80
- value = "Nl%\000\300Z\252\003"
81
- column = DBF::Column.new "ColumnName", "T", 16, 0
82
- column.type_cast(value).should == "2002-10-10T17:04:56+00:00"
83
- end
84
-
85
- it "should cast invalid datetime columns to nil" do
86
- value = "Nl%\000\000A\000\999"
87
- column = DBF::Column.new "ColumnName", "T", 16, 0
88
- column.type_cast(value).should be_nil
89
- end
90
-
91
- it "should cast date columns to Date" do
92
- value = "20050712"
93
- column = DBF::Column.new "ColumnName", "D", 8, 0
94
- column.type_cast(value).should == Date.new(2005,7,12)
40
+ context 'with type N (number)' do
41
+ context 'with 0 decimals' do
42
+ it "should cast value to Integer" do
43
+ value = "135"
44
+ column = DBF::Column.new "ColumnName", "N", 3, 0
45
+ column.type_cast(value).should == 135
46
+ end
47
+ end
48
+
49
+ context 'with more than 0 decimals' do
50
+ it "should cast value to Float" do
51
+ value = "13.5"
52
+ column = DBF::Column.new "ColumnName", "N", 2, 1
53
+ column.type_cast(value).should == 13.5
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'with type F (float)' do
59
+ it "should cast value to Float" do
60
+ value = "135"
61
+ column = DBF::Column.new "ColumnName", "F", 3, 0
62
+ column.type_cast(value).should == 135.0
63
+ end
64
+ end
65
+
66
+ context 'with type I (integer)' do
67
+ it "should cast value to Integer" do
68
+ value = "135"
69
+ column = DBF::Column.new "ColumnName", "I", 3, 0
70
+ column.type_cast(value).should == 135
71
+ end
72
+ end
73
+
74
+ context 'with type L (logical/boolean)' do
75
+ it "should cast 'y' to true" do
76
+ value = "y"
77
+ column = DBF::Column.new "ColumnName", "L", 1, 0
78
+ column.type_cast(value).should == true
79
+ end
80
+
81
+ it "should cast 'n' to false" do
82
+ value = "n"
83
+ column = DBF::Column.new "ColumnName", "L", 1, 0
84
+ column.type_cast(value).should == false
85
+ end
86
+ end
87
+
88
+ context 'with type T (datetime)' do
89
+ context 'with valid datetime' do
90
+ it "should cast to DateTime" do
91
+ value = "Nl%\000\300Z\252\003"
92
+ column = DBF::Column.new "ColumnName", "T", 16, 0
93
+ column.type_cast(value).should == "2002-10-10T17:04:56+00:00"
94
+ end
95
+ end
96
+
97
+ context 'with invalid datetime' do
98
+ it "should cast to nil" do
99
+ value = "Nl%\000\000A\000\999"
100
+ column = DBF::Column.new "ColumnName", "T", 16, 0
101
+ column.type_cast(value).should be_nil
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'with type D (date)' do
107
+ context 'with valid date' do
108
+ it "should cast to Date" do
109
+ value = "20050712"
110
+ column = DBF::Column.new "ColumnName", "D", 8, 0
111
+ column.type_cast(value).should == Date.new(2005,7,12)
112
+ end
113
+ end
114
+
115
+ context 'with invalid date' do
116
+ it "should cast to Date" do
117
+ value = "0"
118
+ column = DBF::Column.new "ColumnName", "D", 8, 0
119
+ column.type_cast(value).should be_nil
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'with type M (memo)' do
125
+ it "should typecast memo columns to String" do
126
+ value = 'abc'
127
+ column = DBF::Column.new "ColumnName", "M", 3, 0
128
+ column.type_cast(value).should be_a String
129
+ end
95
130
  end
96
131
  end
97
132
 
98
133
  context "#schema_definition" do
99
- it "should define an integer column if type is (N)umber with 9 decimals" do
100
- column = DBF::Column.new "ColumnName", "N", 1, 0
101
- column.schema_definition.should == "\"column_name\", :integer\n"
134
+ context 'with type N (number)' do
135
+ it "should output an integer column" do
136
+ column = DBF::Column.new "ColumnName", "N", 1, 0
137
+ column.schema_definition.should == "\"column_name\", :integer\n"
138
+ end
102
139
  end
103
140
 
104
141
  it "should define a float colmn if type is (N)umber with more than 0 decimals" do
@@ -20,34 +20,6 @@ describe DBF::Record do
20
20
  end
21
21
  end
22
22
 
23
- context "when initialized" do
24
- it "should typecast number columns no decimal places to Integer" do
25
- table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
26
- table.column("ID").type.should == "N"
27
- table.column("ID").decimal.should == 0
28
- table.record(1).attributes['id'].should be_kind_of(Integer)
29
- end
30
-
31
- it "should typecast number columns with decimals > 0 to Float" do
32
- table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
33
- table.column("ID").type.should == "N"
34
- table.column("COST").decimal.should == 2
35
- table.record(1).attributes['cost'].should be_kind_of(Float)
36
- end
37
-
38
- it "should typecast memo columns to String" do
39
- table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
40
- table.column("DESC").type.should == "M"
41
- table.record(1).attributes['desc'].should be_kind_of(String)
42
- end
43
-
44
- it "should typecast logical columns to True or False" do
45
- table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
46
- table.column("WEBINCLUDE").type.should == "L"
47
- table.record(1).attributes["webinclude"].should satisfy {|v| v == true || v == false}
48
- end
49
- end
50
-
51
23
  describe '#memo_block_content_size' do
52
24
  it "should equal the difference between the table's memo_block_size and 8" do
53
25
  table = mock_table
@@ -68,20 +40,35 @@ describe DBF::Record do
68
40
  end
69
41
 
70
42
  describe '#read_memo' do
71
- it 'should return nil if start_block is less than 1' do
72
- table = mock_table
73
- record = DBF::Record.new(table)
74
-
75
- record.send(:read_memo, 0).should be_nil
76
- record.send(:read_memo, -1).should be_nil
43
+ before do
44
+ @table = mock_table
45
+ @record = DBF::Record.new(@table)
77
46
  end
78
47
 
79
- it 'should return nil if memo file is missing' do
80
- table = mock_table
81
- table.should_receive(:has_memo_file?).and_return(false)
82
- record = DBF::Record.new(table)
48
+ context 'with start_block of 0' do
49
+ specify { @record.send(:read_memo, 0).should be_nil }
50
+ end
51
+
52
+ context 'with start_block less than 0' do
53
+ specify { @record.send(:read_memo, -1).should be_nil }
54
+ end
55
+
56
+ context 'with valid start_block' do
57
+ before do
58
+ @table.stub!(:memo_file_format).and_return(:fpt)
59
+ end
83
60
 
84
- record.send(:read_memo, 5).should be_nil
61
+ it 'should build the fpt memo' do
62
+ @record.should_receive(:build_fpt_memo)
63
+ @record.send(:read_memo, 1)
64
+ end
65
+ end
66
+
67
+ context 'with no memo file' do
68
+ specify do
69
+ @table.should_receive(:has_memo_file?).and_return(false)
70
+ @record.send(:read_memo, 5).should be_nil
71
+ end
85
72
  end
86
73
  end
87
74
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 2
8
- - 1
9
- version: 1.2.1
8
+ - 2
9
+ version: 1.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Keith Morrison
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-30 00:00:00 -07:00
17
+ date: 2010-04-01 00:00:00 -07:00
18
18
  default_executable: dbf
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency