dbf 1.2.1 → 1.2.2

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,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