spreadbase 0.1.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.
- data/.gitignore +2 -0
- data/COPYING.LESSER +165 -0
- data/README.md +140 -0
- data/lib/spreadbase/codecs/open_document_12.rb +148 -0
- data/lib/spreadbase/codecs/open_document_12_modules/decoding.rb +169 -0
- data/lib/spreadbase/codecs/open_document_12_modules/encoding.rb +200 -0
- data/lib/spreadbase/document.rb +99 -0
- data/lib/spreadbase/helpers/helpers.rb +138 -0
- data/lib/spreadbase/table.rb +273 -0
- data/lib/spreadbase/version.rb +5 -0
- data/lib/spreadbase.rb +37 -0
- data/spec/codecs/open_document_12_spec.rb +137 -0
- data/spec/elements/document_spec.rb +134 -0
- data/spec/elements/table_spec.rb +267 -0
- data/spec/spec_helpers.rb +47 -0
- data/spreadbase.gemspec +24 -0
- data/utils/convert_sqlite_to_ods.rb +154 -0
- data/utils/prettify_file.rb +46 -0
- data/utils/test_ods_folder.rb +40 -0
- data/utils/test_recoding_file.rb +38 -0
- data/utils/test_recoding_from_content.rb +43 -0
- data/utils/utils_helpers.rb +69 -0
- metadata +89 -0
@@ -0,0 +1,273 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
|
5
|
+
|
6
|
+
This file is part of SpreadBase.
|
7
|
+
|
8
|
+
SpreadBase is free software: you can redistribute it and/or modify it under the
|
9
|
+
terms of the GNU Lesser General Public License as published by the Free Software
|
10
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
11
|
+
version.
|
12
|
+
|
13
|
+
SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
|
14
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
15
|
+
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License along
|
18
|
+
with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
=end
|
20
|
+
|
21
|
+
module SpreadBase # :nodoc:
|
22
|
+
|
23
|
+
# Represents the abstraction of a table and its contents.
|
24
|
+
#
|
25
|
+
# The max width of the table is 1024 cells - the last one being 'AMJ'.
|
26
|
+
#
|
27
|
+
# Row indexing follows the ruby semantics:
|
28
|
+
# - negative indexes represent an access starting from the end of an array
|
29
|
+
# - out-of-bounds access will return nil where a row is accessed as a whole, and raise an error when a cell has to be accessed.
|
30
|
+
#
|
31
|
+
class Table
|
32
|
+
|
33
|
+
include SpreadBase::Helpers
|
34
|
+
|
35
|
+
attr_accessor :name, :data
|
36
|
+
|
37
|
+
# Array of style names; nil when not associated to any column width.
|
38
|
+
#
|
39
|
+
attr_accessor :column_width_styles # :nodoc:
|
40
|
+
|
41
|
+
# _params_:
|
42
|
+
#
|
43
|
+
# +name+:: (required) Name of the table
|
44
|
+
# +data+:: (Array.new) 2d matrix of the data. if not empty, the rows need to be all of the same size
|
45
|
+
#
|
46
|
+
def initialize( name, data=[] )
|
47
|
+
raise "Table name required" if name.nil? || name == ''
|
48
|
+
|
49
|
+
@name = name
|
50
|
+
@data = data
|
51
|
+
@column_width_styles = []
|
52
|
+
end
|
53
|
+
|
54
|
+
# Access a cell value.
|
55
|
+
#
|
56
|
+
# _params_:
|
57
|
+
#
|
58
|
+
# +column_indentifier+:: either an int (0-based) or the excel-format identifier (AA...); limited to the given row size.
|
59
|
+
# +row_index+:: int (0-based). see notes about the rows indexing.
|
60
|
+
#
|
61
|
+
# _returns_ the value, which is automatically converted to the Ruby data type.
|
62
|
+
#
|
63
|
+
def []( column_identifier, row_index )
|
64
|
+
row = row( row_index )
|
65
|
+
column_index = decode_column_identifier( column_identifier )
|
66
|
+
|
67
|
+
check_column_index( row, column_index )
|
68
|
+
|
69
|
+
row[ column_index ]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Writes a value in a cell.
|
73
|
+
#
|
74
|
+
# _params_:
|
75
|
+
#
|
76
|
+
# +column_indentifier+:: either an int (0-based) or the excel-format identifier (AA...); limited to the given row size.
|
77
|
+
# +row_index+:: int (0-based). see notes about the rows indexing.
|
78
|
+
# +value+:: value
|
79
|
+
#
|
80
|
+
def []=( column_identifier, row_index, value )
|
81
|
+
row = row( row_index )
|
82
|
+
column_index = decode_column_identifier( column_identifier )
|
83
|
+
|
84
|
+
check_column_index( row, column_index )
|
85
|
+
|
86
|
+
row[ column_index ] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns an array containing the values of a single row.
|
90
|
+
#
|
91
|
+
# _params_:
|
92
|
+
#
|
93
|
+
# +row_index+:: int (0-based). see notes about the rows indexing.
|
94
|
+
#
|
95
|
+
def row( row_index )
|
96
|
+
check_row_index( row_index )
|
97
|
+
|
98
|
+
@data[ row_index ]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Deletes a row.
|
102
|
+
#
|
103
|
+
# This operation won't modify the column width styles in any case.
|
104
|
+
#
|
105
|
+
# _params_:
|
106
|
+
#
|
107
|
+
# +row_index+:: int (0-based). see notes about the rows indexing.
|
108
|
+
#
|
109
|
+
# _returns_ the deleted row
|
110
|
+
#
|
111
|
+
def delete_row( row_index )
|
112
|
+
check_row_index( row_index )
|
113
|
+
|
114
|
+
@data.slice!( row_index )
|
115
|
+
end
|
116
|
+
|
117
|
+
# Inserts a row.
|
118
|
+
#
|
119
|
+
# This operation won't modify the column width styles in any case.
|
120
|
+
#
|
121
|
+
# _params_:
|
122
|
+
#
|
123
|
+
# +row_index+:: int (0-based). must be between 0 and (including) the table rows size.
|
124
|
+
# +row+:: array of values. if the table is not empty, must have the same size of the table width.
|
125
|
+
#
|
126
|
+
def insert_row( row_index, row )
|
127
|
+
check_row_index( row_index, :allow_append => true )
|
128
|
+
|
129
|
+
@data.insert( row_index, row )
|
130
|
+
end
|
131
|
+
|
132
|
+
# This operation won't modify the column width styles in any case.
|
133
|
+
#
|
134
|
+
def append_row( row )
|
135
|
+
insert_row( @data.size, row )
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns an array containing the values of a single column.
|
139
|
+
#
|
140
|
+
# WATCH OUT! This method doesn't have the range restrictions that axis indexes generally has, that is, it's possible to access a column outside the boundaries of the rows - it will return nil for each of those values.
|
141
|
+
#
|
142
|
+
# _params_:
|
143
|
+
#
|
144
|
+
# +column_indentifier+:: either an int (0-based) or the excel-format identifier (AA...).
|
145
|
+
# when int, follow the same idea of the rows indexing (ruby semantics).
|
146
|
+
#
|
147
|
+
def column( column_identifier )
|
148
|
+
column_index = decode_column_identifier( column_identifier )
|
149
|
+
|
150
|
+
@data.map do | row |
|
151
|
+
row[ column_index ]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Deletes a column.
|
156
|
+
#
|
157
|
+
# WATCH OUT! This method doesn't have the range restrictions that axis indexes generally has, that is, it's possible to delete a column outside the boundaries of the rows - it will return nil for each of those values.
|
158
|
+
#
|
159
|
+
# _params_:
|
160
|
+
#
|
161
|
+
# +column_indentifier+:: either an int (0-based) or the excel-format identifier (AA...).
|
162
|
+
# when int, follow the same idea of the rows indexing (ruby semantics).
|
163
|
+
#
|
164
|
+
# _returns_ the deleted column
|
165
|
+
#
|
166
|
+
def delete_column( column_identifier )
|
167
|
+
column_index = decode_column_identifier( column_identifier )
|
168
|
+
|
169
|
+
@column_width_styles.slice!( column_index )
|
170
|
+
|
171
|
+
@data.map do | row |
|
172
|
+
row.slice!( column_index )
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Inserts a column.
|
177
|
+
#
|
178
|
+
# WATCH OUT! This method doesn't have the range restrictions that axis indexes generally has, that is, it's possible to insert a column outside the boundaries of the rows - it will fill the cells in the middle with nils..
|
179
|
+
#
|
180
|
+
# _params_:
|
181
|
+
#
|
182
|
+
# +column_indentifier+:: either an int (0-based) or the excel-format identifier (AA...).
|
183
|
+
# when int, follow the same idea of the rows indexing (ruby semantics).
|
184
|
+
# +column+:: array of values. if the table is not empty, it must have the same size of the table height.
|
185
|
+
#
|
186
|
+
def insert_column( column_identifier, column )
|
187
|
+
raise "Inserting column size (#{ column.size }) different than existing columns size (#{ @data.size })" if @data.size > 0 && column.size != @data.size
|
188
|
+
|
189
|
+
column_index = decode_column_identifier( column_identifier )
|
190
|
+
|
191
|
+
@column_width_styles.insert( column_index, nil )
|
192
|
+
|
193
|
+
if @data.size > 0
|
194
|
+
@data.zip( column ).each do | row, value |
|
195
|
+
row.insert( column_index, value )
|
196
|
+
end
|
197
|
+
else
|
198
|
+
@data = column.map { | value | [ value ] }
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
def append_column( column )
|
204
|
+
column_index = @data.size > 0 ? @data.first.size : 0
|
205
|
+
|
206
|
+
insert_column( column_index, column )
|
207
|
+
end
|
208
|
+
|
209
|
+
# _returns_ a matrix representation of the tables, with the values being separated by commas.
|
210
|
+
#
|
211
|
+
def to_s( options={} )
|
212
|
+
pretty_print_rows( @data, options )
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
|
217
|
+
# Check that row index points to an existing record, or, in case of :allow_append,
|
218
|
+
# point to one unit above the last row.
|
219
|
+
#
|
220
|
+
# _options_:
|
221
|
+
#
|
222
|
+
# +allow_append+:: Allow pointing to one unit above the last row.
|
223
|
+
#
|
224
|
+
def check_row_index( row_index, options={} )
|
225
|
+
allow_append = options [ :allow_append ]
|
226
|
+
|
227
|
+
positive_limit = allow_append ? @data.size : @data.size - 1
|
228
|
+
|
229
|
+
raise "Invalid row index (#{ row_index }) - allowed 0 to #{ positive_limit }" if row_index < 0 || row_index > positive_limit
|
230
|
+
end
|
231
|
+
|
232
|
+
def check_column_index( row, column_index )
|
233
|
+
raise "Invalid column index (#{ column_index }) for the given row - allowed 0 to #{ row.size - 1 }" if column_index >= row.size
|
234
|
+
end
|
235
|
+
|
236
|
+
# Accepts either an integer, or a MoFoBase26BisexNumber.
|
237
|
+
#
|
238
|
+
# Raises an error for invalid identifiers/indexes.
|
239
|
+
#
|
240
|
+
# _returns_ a 0-based decimal number.
|
241
|
+
#--
|
242
|
+
# Motherf#### base-26 bijective numeration - I would have gladly saved my f* time. At least
|
243
|
+
# there were a few cute ladies at the Charleston lesson.
|
244
|
+
#
|
245
|
+
def decode_column_identifier( column_identifier )
|
246
|
+
if column_identifier.is_a?( Fixnum )
|
247
|
+
raise "Negative column indexes not allowed: #{ column_identifier }" if column_identifier < 0
|
248
|
+
|
249
|
+
column_identifier
|
250
|
+
else
|
251
|
+
letters = column_identifier.upcase.chars.to_a
|
252
|
+
upcase_a_ord = 65
|
253
|
+
|
254
|
+
raise "Invalid letter for in column identifier (allowed 'a/A' to 'z/Z')" if letters.any? { | letter | letter < 'A' || letter > 'Z' }
|
255
|
+
|
256
|
+
base_10_value = letters.inject( 0 ) do | sum, letter |
|
257
|
+
letter_ord = letter.unpack( 'C' ).first
|
258
|
+
sum * 26 + ( letter_ord - upcase_a_ord + 1 )
|
259
|
+
end
|
260
|
+
|
261
|
+
base_10_value -= 1
|
262
|
+
|
263
|
+
# -1 is an empty string
|
264
|
+
#
|
265
|
+
raise "Invalid literal column identifier (allowed 'A' to 'AMJ')" if base_10_value < 0 || 1023 < base_10_value
|
266
|
+
|
267
|
+
base_10_value
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
data/lib/spreadbase.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
|
5
|
+
|
6
|
+
This file is part of SpreadBase.
|
7
|
+
|
8
|
+
SpreadBase is free software: you can redistribute it and/or modify it under the
|
9
|
+
terms of the GNU Lesser General Public License as published by the Free Software
|
10
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
11
|
+
version.
|
12
|
+
|
13
|
+
SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
|
14
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
15
|
+
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License along
|
18
|
+
with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
=end
|
20
|
+
|
21
|
+
require 'rubygems'
|
22
|
+
|
23
|
+
require File.expand_path( '../spreadbase/helpers/helpers', __FILE__ )
|
24
|
+
|
25
|
+
require File.expand_path( '../spreadbase/document', __FILE__ )
|
26
|
+
require File.expand_path( '../spreadbase/table', __FILE__ )
|
27
|
+
|
28
|
+
require File.expand_path( '../spreadbase/codecs/open_document_12_modules/encoding', __FILE__ )
|
29
|
+
require File.expand_path( '../spreadbase/codecs/open_document_12_modules/decoding', __FILE__ )
|
30
|
+
require File.expand_path( '../spreadbase/codecs/open_document_12', __FILE__ )
|
31
|
+
|
32
|
+
# = Spreadbase
|
33
|
+
#
|
34
|
+
# See https://github.com/saveriomiroddi/spreadbase for usage.
|
35
|
+
#
|
36
|
+
module SpreadBase
|
37
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
|
5
|
+
|
6
|
+
This file is part of SpreadBase.
|
7
|
+
|
8
|
+
SpreadBase is free software: you can redistribute it and/or modify it under the
|
9
|
+
terms of the GNU Lesser General Public License as published by the Free Software
|
10
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
11
|
+
version.
|
12
|
+
|
13
|
+
SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
|
14
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
15
|
+
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License along
|
18
|
+
with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
=end
|
20
|
+
|
21
|
+
require File.expand_path( '../../../lib/spreadbase', __FILE__ )
|
22
|
+
require File.expand_path( '../../spec_helpers', __FILE__ )
|
23
|
+
|
24
|
+
require 'date'
|
25
|
+
require 'bigdecimal'
|
26
|
+
|
27
|
+
include SpecHelpers
|
28
|
+
|
29
|
+
# See testing notes.
|
30
|
+
#
|
31
|
+
describe SpreadBase::Codecs::OpenDocument12 do
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
table_1 = SpreadBase::Table.new(
|
35
|
+
'abc', [
|
36
|
+
[ 1, 1.1, T_BIGDECIMAL ],
|
37
|
+
[ T_DATE, T_DATETIME, T_TIME ],
|
38
|
+
[ nil, 'a', nil ]
|
39
|
+
]
|
40
|
+
)
|
41
|
+
|
42
|
+
table_2 = SpreadBase::Table.new( 'cde' )
|
43
|
+
|
44
|
+
@sample_document = SpreadBase::Document.new
|
45
|
+
|
46
|
+
@sample_document.tables << table_1 << table_2
|
47
|
+
end
|
48
|
+
|
49
|
+
# :encode/:decode
|
50
|
+
#
|
51
|
+
it "should encode and decode the sample document" do
|
52
|
+
document_archive = SpreadBase::Codecs::OpenDocument12.new.encode_to_archive( @sample_document )
|
53
|
+
|
54
|
+
document = SpreadBase::Codecs::OpenDocument12.new.decode_archive( document_archive, :floats_as_bigdecimal => true )
|
55
|
+
|
56
|
+
assert_size( document.tables, 2 ) do | table_1, table_2 |
|
57
|
+
|
58
|
+
table_1.name.should == 'abc'
|
59
|
+
|
60
|
+
assert_size( table_1.data, 3 ) do | row_1, row_2, row_3 |
|
61
|
+
|
62
|
+
assert_size( row_1, 3 ) do | value_1, value_2, value_3 |
|
63
|
+
value_1.should == 1
|
64
|
+
value_1.should be_a( Fixnum )
|
65
|
+
value_2.should == 1.1
|
66
|
+
value_2.should be_a( BigDecimal )
|
67
|
+
value_3.should == T_BIGDECIMAL
|
68
|
+
value_3.should be_a( BigDecimal )
|
69
|
+
end
|
70
|
+
|
71
|
+
assert_size( row_2, 3 ) do | value_1, value_2, value_3 |
|
72
|
+
value_1.should == T_DATE
|
73
|
+
value_2.should == T_DATETIME
|
74
|
+
value_3.should == T_DATETIME
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_size( row_3, 3 ) do | value_1, value_2, value_3 |
|
78
|
+
value_1.should == nil
|
79
|
+
value_2.should == 'a'
|
80
|
+
value_3.should == nil
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
table_2.name.should == 'cde'
|
86
|
+
|
87
|
+
assert_size( table_2.data, 0 )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Not worth testing in detail; just ensure that the pref
|
92
|
+
#
|
93
|
+
it "should encode the document with makeup (:prettify) - SMOKE" do
|
94
|
+
formatter = stub_initializer( REXML::Formatters::Pretty )
|
95
|
+
|
96
|
+
formatter.should_receive( :write )
|
97
|
+
|
98
|
+
SpreadBase::Codecs::OpenDocument12.new.encode_to_archive( @sample_document, :prettify => true )
|
99
|
+
end
|
100
|
+
|
101
|
+
# Those methods are actually "utility" (read: testing) methods.
|
102
|
+
#
|
103
|
+
it "should encode/decode the content.xml - SMOKE" do
|
104
|
+
content_xml = SpreadBase::Codecs::OpenDocument12.new.encode_to_content_xml( @sample_document )
|
105
|
+
|
106
|
+
document = SpreadBase::Codecs::OpenDocument12.new.decode_content_xml( content_xml )
|
107
|
+
|
108
|
+
assert_size( document.tables, 2 )
|
109
|
+
end
|
110
|
+
|
111
|
+
# If values are not converted to UTF-8, some encodings cause an error to be
|
112
|
+
# raised when assigning a value to a cell.
|
113
|
+
#
|
114
|
+
# 1.8 tests can't be done, since the official platform is 1.9
|
115
|
+
#
|
116
|
+
it "should convert to utf-8 before saving" do
|
117
|
+
string = "à".encode( 'UTF-16' )
|
118
|
+
|
119
|
+
@sample_document.tables[ 0 ][ 0, 0 ] = string
|
120
|
+
|
121
|
+
# Doesn't encode correctly if the value is not converted
|
122
|
+
#
|
123
|
+
SpreadBase::Codecs::OpenDocument12.new.encode_to_content_xml( @sample_document )
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should decode as BigDecimal" do
|
127
|
+
content_xml = SpreadBase::Codecs::OpenDocument12.new.encode_to_content_xml( @sample_document )
|
128
|
+
|
129
|
+
document = SpreadBase::Codecs::OpenDocument12.new.decode_content_xml( content_xml, :floats_as_bigdecimal => true )
|
130
|
+
|
131
|
+
value = document.tables[ 0 ][ 2, 0 ]
|
132
|
+
|
133
|
+
value.should be_a( BigDecimal )
|
134
|
+
value.should == T_BIGDECIMAL
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
Copyright 2012 Saverio Miroddi saverio.pub2 <a-hat!> gmail.com
|
5
|
+
|
6
|
+
This file is part of SpreadBase.
|
7
|
+
|
8
|
+
SpreadBase is free software: you can redistribute it and/or modify it under the
|
9
|
+
terms of the GNU Lesser General Public License as published by the Free Software
|
10
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
11
|
+
version.
|
12
|
+
|
13
|
+
SpreadBase is distributed in the hope that it will be useful, but WITHOUT ANY
|
14
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
15
|
+
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License along
|
18
|
+
with SpreadBase. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
=end
|
20
|
+
|
21
|
+
require File.expand_path( '../../../lib/spreadbase', __FILE__ )
|
22
|
+
require File.expand_path( '../../spec_helpers', __FILE__ )
|
23
|
+
|
24
|
+
include SpecHelpers
|
25
|
+
|
26
|
+
describe SpreadBase::Document do
|
27
|
+
|
28
|
+
before :each do
|
29
|
+
@sample_document = SpreadBase::Document.new
|
30
|
+
@sample_document.tables = [
|
31
|
+
SpreadBase::Table.new(
|
32
|
+
'abc', [
|
33
|
+
[ 1, 1.1, T_BIGDECIMAL ],
|
34
|
+
[ T_DATE, T_DATETIME, T_TIME ],
|
35
|
+
[ true, 'a', nil ]
|
36
|
+
]
|
37
|
+
)
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
# :-D
|
42
|
+
#
|
43
|
+
it "should initialize out of thin air" do
|
44
|
+
document = SpreadBase::Document.new
|
45
|
+
|
46
|
+
document.document_path.should == nil
|
47
|
+
|
48
|
+
document.tables.should be_empty
|
49
|
+
end
|
50
|
+
|
51
|
+
# A lazy use of stubs
|
52
|
+
#
|
53
|
+
it "should initialize from a file" do
|
54
|
+
codec = stub_initializer( SpreadBase::Codecs::OpenDocument12 )
|
55
|
+
|
56
|
+
File.should_receive( :'exists?' ).with( '/pizza/margerita.txt' ).and_return( true )
|
57
|
+
IO.should_receive( :read ).with( '/pizza/margerita.txt' ).and_return( 'abc' )
|
58
|
+
codec.should_receive( :decode_archive ).with( 'abc', {} ).and_return( @sample_document )
|
59
|
+
|
60
|
+
document = SpreadBase::Document.new( '/pizza/margerita.txt' )
|
61
|
+
|
62
|
+
assert_size( document.tables, 1 ) do | table |
|
63
|
+
table.name.should == 'abc'
|
64
|
+
table.data.size.should == 3
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should initialize with a non-existing file" do
|
69
|
+
codec = stub_initializer( SpreadBase::Codecs::OpenDocument12 )
|
70
|
+
|
71
|
+
document = SpreadBase::Document.new( '/pizza/margerita.txt' )
|
72
|
+
|
73
|
+
assert_size( document.tables, 0 )
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should save to a file" do
|
77
|
+
codec = stub_initializer( SpreadBase::Codecs::OpenDocument12 )
|
78
|
+
|
79
|
+
document = SpreadBase::Document.new
|
80
|
+
document.tables << SpreadBase::Table.new( 'Ya-ha!' )
|
81
|
+
document.document_path = '/tmp/abc.ods'
|
82
|
+
|
83
|
+
codec.should_receive( :encode_to_archive ).with( document, :prettify => 'abc' ).and_return( 'sob!' )
|
84
|
+
File.should_receive( :open ).with( '/tmp/abc.ods', 'wb' )
|
85
|
+
|
86
|
+
document.save( :prettify => 'abc' )
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should raise an error when trying to save without a filename" do
|
90
|
+
document = SpreadBase::Document.new
|
91
|
+
document.tables << SpreadBase::Table.new( 'Ya-ha!' )
|
92
|
+
|
93
|
+
lambda { document.save }.should raise_error( RuntimeError, "Document path not specified" )
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should raise an error when trying to save without tables" do
|
97
|
+
document = SpreadBase::Document.new
|
98
|
+
document.document_path = 'abc.ods'
|
99
|
+
|
100
|
+
lambda { document.save }.should raise_error( RuntimeError, "At least one table must be present" )
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should return the data as string (:to_s)" do
|
104
|
+
expected_string = "\
|
105
|
+
abc:
|
106
|
+
|
107
|
+
+------------+---------------------------+---------------------------+
|
108
|
+
| 1 | 1.1 | 0.133E1 |
|
109
|
+
| 2012-04-10 | 2012-04-11T23:33:42+00:00 | 2012-04-11 23:33:42 +0200 |
|
110
|
+
| true | a | |
|
111
|
+
+------------+---------------------------+---------------------------+
|
112
|
+
|
113
|
+
"
|
114
|
+
|
115
|
+
@sample_document.to_s.should == expected_string
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should return the data as string, with headers (:to_s)" do
|
119
|
+
expected_string = "\
|
120
|
+
abc:
|
121
|
+
|
122
|
+
+------------+---------------------------+---------------------------+
|
123
|
+
| 1 | 1.1 | 0.133E1 |
|
124
|
+
+------------+---------------------------+---------------------------+
|
125
|
+
| 2012-04-10 | 2012-04-11T23:33:42+00:00 | 2012-04-11 23:33:42 +0200 |
|
126
|
+
| true | a | |
|
127
|
+
+------------+---------------------------+---------------------------+
|
128
|
+
|
129
|
+
"
|
130
|
+
|
131
|
+
@sample_document.to_s( :with_headers => true ).should == expected_string
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|