pulo 0.1.1 → 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.
- checksums.yaml +4 -4
- data/lib/pulo.rb +28 -0
- data/lib/pulo/exceptions.rb +6 -0
- data/lib/pulo/figure/figure2d.rb +248 -0
- data/lib/pulo/figure/figure3d.rb +166 -0
- data/lib/pulo/formatting.rb +140 -0
- data/lib/pulo/frames/frame.rb +289 -0
- data/lib/pulo/frames/frame_cell.rb +83 -0
- data/lib/pulo/frames/frame_column.rb +149 -0
- data/lib/pulo/frames/frame_row.rb +87 -0
- data/lib/pulo/helpers.rb +1 -0
- data/lib/pulo/machine/hydraulics/pipe.rb +71 -0
- data/lib/pulo/machine/machines.rb +10 -0
- data/lib/pulo/machine/mechanics/moments_of_inertia.rb +64 -0
- data/lib/pulo/machine/steam/boiler.rb +61 -0
- data/lib/pulo/machine/steam/boiler_deaerator.rb +64 -0
- data/lib/pulo/machine/steam/deaerator.rb +37 -0
- data/lib/pulo/machine/steam/desuperheater.rb +29 -0
- data/lib/pulo/machine/steam/header.rb +20 -0
- data/lib/pulo/machine/steam/if97.rb +378 -0
- data/lib/pulo/machine/steam/steam_process.rb +27 -0
- data/lib/pulo/machine/steam/steam_turbine.rb +42 -0
- data/lib/pulo/machine/steam/water_steam.rb +229 -0
- data/lib/pulo/material/water.rb +34 -0
- data/lib/pulo/quantity/dimension.rb +63 -0
- data/lib/pulo/quantity/numeric_overloads.rb +217 -0
- data/lib/pulo/quantity/quantity.rb +285 -0
- data/lib/pulo/quantity/quantity_builder.rb +185 -0
- data/lib/pulo/quantity/quantity_definitions.rb +8 -0
- data/lib/pulo/quantity/quantity_definitions/area_volume.rb +73 -0
- data/lib/pulo/quantity/quantity_definitions/basic.rb +157 -0
- data/lib/pulo/quantity/quantity_definitions/electric.rb +22 -0
- data/lib/pulo/quantity/quantity_definitions/energy.rb +50 -0
- data/lib/pulo/quantity/quantity_definitions/fluids.rb +23 -0
- data/lib/pulo/quantity/quantity_definitions/force_power.rb +82 -0
- data/lib/pulo/quantity/quantity_definitions/rotation.rb +49 -0
- data/lib/pulo/quantity/quantity_definitions/value.rb +65 -0
- data/lib/pulo/quantity/quantity_definitions/velocity_acc_flow.rb +66 -0
- data/lib/pulo/quantity/quantity_groups/quantity_groups.rb +36 -0
- data/lib/pulo/quantity/unit.rb +45 -0
- data/lib/pulo/quantity_checker.rb +13 -0
- data/lib/pulo/tables/density.rb +10 -0
- data/lib/pulo/tables/melting_temperature.rb +9 -0
- data/lib/pulo/tables/specific_energy.rb +10 -0
- data/lib/pulo/tables/speed_of_sound.rb +9 -0
- data/lib/pulo/tables/tables.rb +104 -0
- data/lib/pulo/tables/tensile_strength.rb +10 -0
- data/lib/pulo/tables/yield_strength.rb +10 -0
- data/lib/pulo/version.rb +3 -0
- metadata +51 -3
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Pulo
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def stats_format stats
|
7
|
+
ret=''
|
8
|
+
stats.each do |stat|
|
9
|
+
if stat[0]==:number
|
10
|
+
ret+='Count: ' + stat[1].to_s + "\n"
|
11
|
+
else
|
12
|
+
ret+=stat[0].to_s.capitalize + ': ' + stat[1].to_s + "\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ret
|
16
|
+
end
|
17
|
+
|
18
|
+
def super_digit(val)
|
19
|
+
val.to_s.chars.inject('') do |res, chr|
|
20
|
+
res+= case chr
|
21
|
+
when '.'
|
22
|
+
"\u207B".encode('utf-8')
|
23
|
+
when '-'
|
24
|
+
"\u207B".encode('utf-8')
|
25
|
+
when '1'
|
26
|
+
"\u00B9".encode('utf-8')
|
27
|
+
when '2'
|
28
|
+
"\u00B2".encode('utf-8')
|
29
|
+
when '3'
|
30
|
+
"\u00B3".encode('utf-8')
|
31
|
+
when '0'
|
32
|
+
"\u2070".encode('utf-8')
|
33
|
+
when '4'
|
34
|
+
"\u2074".encode('utf-8')
|
35
|
+
when '5'
|
36
|
+
"\u2075".encode('utf-8')
|
37
|
+
when '6'
|
38
|
+
"\u2076".encode('utf-8')
|
39
|
+
when '7'
|
40
|
+
"\u2077".encode('utf-8')
|
41
|
+
when '8'
|
42
|
+
"\u2078".encode('utf-8')
|
43
|
+
when '9'
|
44
|
+
"\u2079".encode('utf-8')
|
45
|
+
else
|
46
|
+
''
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class NumberToRoundedConverter
|
53
|
+
def self.convert(number, precision)
|
54
|
+
|
55
|
+
precision ||= Pulo.precision
|
56
|
+
|
57
|
+
if Pulo.significant_figures && precision > 0
|
58
|
+
digits, rounded_number = digits_and_rounded_number(number, precision)
|
59
|
+
precision -= digits
|
60
|
+
precision = 0 if precision < 0 # don't let it be negative
|
61
|
+
else
|
62
|
+
rounded_number = number.round(precision)
|
63
|
+
rounded_number = rounded_number.to_i if precision == 0
|
64
|
+
rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
|
65
|
+
end
|
66
|
+
formatted_string = "%00.#{precision}f" % rounded_number
|
67
|
+
|
68
|
+
delimited_number = NumberToDelimitedConverter.convert(formatted_string)
|
69
|
+
format_number(delimited_number)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def self.digits_and_rounded_number(number,precision)
|
75
|
+
if zero?(number)
|
76
|
+
[1, 0]
|
77
|
+
else
|
78
|
+
digits = digit_count(number)
|
79
|
+
multiplier = 10 ** (digits - precision)
|
80
|
+
rounded_number = calculate_rounded_number(number,multiplier)
|
81
|
+
digits = digit_count(rounded_number) # After rounding, the number of digits may have changed
|
82
|
+
[digits, rounded_number]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.calculate_rounded_number(number,multiplier)
|
87
|
+
(number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.digit_count(number)
|
91
|
+
number.zero? ? 1 : (Math.log10(absolute_number(number)) + 1).floor
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.format_number(number)
|
95
|
+
escaped_separator = Regexp.escape('.')
|
96
|
+
number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.absolute_number(number)
|
100
|
+
number.respond_to?(:abs) ? number.abs : number.to_d.abs
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.zero?(number)
|
104
|
+
number.respond_to?(:zero?) ? number.zero? : number.to_d.zero?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class NumberToDelimitedConverter
|
109
|
+
DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
110
|
+
|
111
|
+
def self.convert(number)
|
112
|
+
parts(number).join('.')
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def self.parts(number)
|
118
|
+
left, right = number.to_s.split('.')
|
119
|
+
left.gsub!(DELIMITED_REGEX) do |digit_to_delimit|
|
120
|
+
"#{digit_to_delimit},"
|
121
|
+
end
|
122
|
+
[left, right].compact
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
#class BigDecimal
|
129
|
+
# DEFAULT_STRING_FORMAT = 'F'
|
130
|
+
# def to_formatted_s(*args)
|
131
|
+
# if args[0].is_a?(Symbol)
|
132
|
+
# super
|
133
|
+
# else
|
134
|
+
# format = args[0] || DEFAULT_STRING_FORMAT
|
135
|
+
# _original_to_s(format)
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
# alias_method :_original_to_s, :to_s
|
139
|
+
# alias_method :to_s, :to_formatted_s
|
140
|
+
#end
|
@@ -0,0 +1,289 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'descriptive_statistics'
|
3
|
+
require_relative 'frame_cell'
|
4
|
+
require_relative 'frame_row'
|
5
|
+
require_relative 'frame_column'
|
6
|
+
|
7
|
+
module Pulo
|
8
|
+
|
9
|
+
class Frame
|
10
|
+
|
11
|
+
attr_reader :column_count,:row_count,:rows, :columns, :column_names
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@rows=[]
|
15
|
+
@columns=[]
|
16
|
+
@column_names={}
|
17
|
+
@column_count=0
|
18
|
+
@row_count=0
|
19
|
+
end
|
20
|
+
|
21
|
+
def export_csv(path)
|
22
|
+
|
23
|
+
CSV.open(path, 'wb') do |csv|
|
24
|
+
csv << @columns.map {|col| col.name}
|
25
|
+
csv << @columns.map {|col|
|
26
|
+
if col.column_class.respond_to?(:quantity_name)
|
27
|
+
col.column_class.quantity_name
|
28
|
+
else
|
29
|
+
col.column_class.name
|
30
|
+
end
|
31
|
+
}
|
32
|
+
csv << @columns.map {|col|
|
33
|
+
if col.column_class.respond_to?(:quantity_name)
|
34
|
+
col.column_unit.abbreviation
|
35
|
+
else
|
36
|
+
''
|
37
|
+
end
|
38
|
+
}
|
39
|
+
@rows.each do |row|
|
40
|
+
csv<<row.to_a.map{|cell|
|
41
|
+
if cell.class.respond_to?(:quantity_name)
|
42
|
+
cell.value
|
43
|
+
else
|
44
|
+
cell
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#applies the given function to each row
|
52
|
+
#returns a hash where each element (keyed by the group) is a frame containing the group
|
53
|
+
def group(group_function)
|
54
|
+
#t=Time.now
|
55
|
+
groups={}
|
56
|
+
@rows.each do |row|
|
57
|
+
res=group_function.call(row)
|
58
|
+
if groups[res]
|
59
|
+
groups[res].append_row(row.to_a)
|
60
|
+
else
|
61
|
+
frm=self.copy_definition
|
62
|
+
frm.append_row(row.to_a)
|
63
|
+
groups.merge!({res=>frm})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
#puts "Groups in #{((Time.now-t)*1000).to_i} ms."
|
67
|
+
groups
|
68
|
+
end
|
69
|
+
|
70
|
+
def group_reduce(group_function,column_defns)
|
71
|
+
#get groups
|
72
|
+
groups=group(group_function)
|
73
|
+
|
74
|
+
#t=Time.now
|
75
|
+
output=Frame.new
|
76
|
+
output.append_column 'Group'
|
77
|
+
|
78
|
+
#setup the columns
|
79
|
+
column_defns.keys.each do |col|
|
80
|
+
output.append_column(col)
|
81
|
+
end
|
82
|
+
|
83
|
+
#add a row to the output for each group produced in the earlier stage
|
84
|
+
groups.each do |group|
|
85
|
+
row=column_defns.map do |defn|
|
86
|
+
if defn[1].class==Proc
|
87
|
+
defn[1].call group[1]
|
88
|
+
else
|
89
|
+
#assume an array with method for descriptive statistics and a column name
|
90
|
+
c=group[1][defn[1][1]]
|
91
|
+
v=case defn[1][0]
|
92
|
+
when :min
|
93
|
+
c.to_a.min
|
94
|
+
when :max
|
95
|
+
c.to_a.max
|
96
|
+
else
|
97
|
+
DescriptiveStatistics.send(defn[1][0],c.to_a)
|
98
|
+
end
|
99
|
+
if c.column_class.respond_to?(:quantity_name) && defn[1][0]!=:number
|
100
|
+
c.column_class.send(c.column_unit.name,v)
|
101
|
+
else
|
102
|
+
v
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
row.insert 0,group[0]
|
107
|
+
output.append_row row
|
108
|
+
end
|
109
|
+
#puts "Reduce in #{((Time.now-t)*1000).to_i} ms."
|
110
|
+
output
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
def sort(&sort_function)
|
115
|
+
int=@rows.map do |row|
|
116
|
+
[row.row_number,sort_function.call(row)]
|
117
|
+
end.sort_by {|elm| elm[1]}.map{|elm| elm[0]}
|
118
|
+
frm=self.copy_definition
|
119
|
+
int.each do |row_no|
|
120
|
+
frm.append_row self.rows[row_no].to_a_values
|
121
|
+
end
|
122
|
+
frm
|
123
|
+
end
|
124
|
+
|
125
|
+
def clone
|
126
|
+
frame=copy_definition
|
127
|
+
@rows.each do |row|
|
128
|
+
frame.append_row row.to_a
|
129
|
+
end
|
130
|
+
frame
|
131
|
+
end
|
132
|
+
|
133
|
+
def copy_definition
|
134
|
+
frame=Frame.new
|
135
|
+
@columns.each do |col|
|
136
|
+
frame.append_column(col.name,col.hidden?,&col.formula)
|
137
|
+
end
|
138
|
+
frame
|
139
|
+
end
|
140
|
+
|
141
|
+
def delete_column(name_or_index)
|
142
|
+
if name_or_index.is_a?(Integer)
|
143
|
+
raise IndexError,"No column number #{name_or_index} defined." unless @columns[name_or_index]
|
144
|
+
index=name_or_index
|
145
|
+
name=@columns[index].name
|
146
|
+
else
|
147
|
+
index=@column_names[name_or_index]
|
148
|
+
raise IndexError,"Column with name '#{name_or_index}' not found." unless index
|
149
|
+
name=name_or_index
|
150
|
+
end
|
151
|
+
@rows.each {|row| row.delete_column(index)}
|
152
|
+
@column_names.delete(name)
|
153
|
+
@column_names.each do |item|
|
154
|
+
@column_names[item[0]]-=1 if @column_names[item[0]]>=index
|
155
|
+
end
|
156
|
+
@columns.delete_at(index)
|
157
|
+
@column_count-=1
|
158
|
+
end
|
159
|
+
|
160
|
+
def rename_column(old_name,new_name)
|
161
|
+
col=self[old_name]
|
162
|
+
col_no=@column_names[old_name]
|
163
|
+
@column_names.delete(old_name)
|
164
|
+
@column_names.merge!({new_name=>col_no})
|
165
|
+
col.name=new_name
|
166
|
+
end
|
167
|
+
|
168
|
+
def append_column(name,hidden=false,&formula)
|
169
|
+
col=FrameColumn.new(name,self, hidden, &formula)
|
170
|
+
|
171
|
+
@columns << col
|
172
|
+
@column_names.merge!({name=>@column_count})
|
173
|
+
|
174
|
+
@rows.each do |rw|
|
175
|
+
cell=FrameCell.new(col,rw)
|
176
|
+
col.append_row(cell)
|
177
|
+
rw.append_column(cell)
|
178
|
+
end
|
179
|
+
@column_count+=1
|
180
|
+
col
|
181
|
+
end
|
182
|
+
|
183
|
+
def append_row(values)
|
184
|
+
if values.is_a?(Array)
|
185
|
+
vals=values.each
|
186
|
+
row=FrameRow.new(self,@row_count)
|
187
|
+
@columns.each do |col|
|
188
|
+
if values.length==column_count
|
189
|
+
v = vals.next
|
190
|
+
else
|
191
|
+
v = col.value_column? ? vals.next : nil
|
192
|
+
end
|
193
|
+
cell=FrameCell.new(col,row,v)
|
194
|
+
col.append_row(cell)
|
195
|
+
row.append_column(cell)
|
196
|
+
end
|
197
|
+
@rows<<row
|
198
|
+
@row_count+=1
|
199
|
+
row
|
200
|
+
else
|
201
|
+
raise 'Expecting an array of values as the append row.'
|
202
|
+
end
|
203
|
+
end
|
204
|
+
def insert_row(previous_row,values)
|
205
|
+
if values.is_a?(Array)
|
206
|
+
row_no=previous_row.row_number+1
|
207
|
+
vals=values.each
|
208
|
+
row=FrameRow.new(self,row_no)
|
209
|
+
@columns.each do |col|
|
210
|
+
if values.length==column_count
|
211
|
+
v = vals.next
|
212
|
+
else
|
213
|
+
v = col.value_column? ? vals.next : nil
|
214
|
+
end
|
215
|
+
cell=FrameCell.new(col,row,v)
|
216
|
+
col.insert_row(row_no,cell)
|
217
|
+
row.append_column(cell)
|
218
|
+
end
|
219
|
+
@rows.insert(row_no,row)
|
220
|
+
@row_count+=1
|
221
|
+
@rows.drop(row_no+1).each {|r| r.row_number+=1}
|
222
|
+
else
|
223
|
+
raise 'Expecting an array of values as the append row.'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def recalc_all(with_timing=false)
|
228
|
+
formula_columns.each { |col| col.recalc with_timing }
|
229
|
+
end
|
230
|
+
|
231
|
+
def [](column)
|
232
|
+
if column.is_a?(Integer)
|
233
|
+
raise IndexError,"No column number #{column} defined." unless @columns[column]
|
234
|
+
@columns[column]
|
235
|
+
else
|
236
|
+
column_no=@column_names[column]
|
237
|
+
raise IndexError,"Column with name '#{column}' not found." unless column_no
|
238
|
+
@columns[column_no]
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def first_row
|
243
|
+
@rows.first
|
244
|
+
end
|
245
|
+
def last_row
|
246
|
+
@rows.last
|
247
|
+
end
|
248
|
+
|
249
|
+
def lookup(value,column)
|
250
|
+
self[column].lookup(value)
|
251
|
+
end
|
252
|
+
|
253
|
+
def to_s(&filter)
|
254
|
+
@columns.each {|c| c.recalc_width}
|
255
|
+
ret="\n "
|
256
|
+
ret+=@columns.select {|c| !c.hidden?}.map{|s| s.name.ljust(s.width,' ')}.join(' ') + "\n"
|
257
|
+
ret+='========= '
|
258
|
+
ret+=@columns.select {|c| !c.hidden?}.map{|s| ''.ljust(s.width,'=')}.join('= ') + "\n"
|
259
|
+
ret+=' '
|
260
|
+
ret+=@columns.select {|c| !c.hidden?}.map{|s|
|
261
|
+
if s.column_class.respond_to?(:quantity_name)
|
262
|
+
(s.column_class.quantity_name + (s.value_column? ? '' : '*')).ljust(s.width,' ')
|
263
|
+
else
|
264
|
+
(s.column_class.to_s + (s.value_column? ? '' : '*')).ljust(s.width,' ')
|
265
|
+
end
|
266
|
+
}.join(' ') + "\n"
|
267
|
+
ret+='--------- '
|
268
|
+
ret+=@columns.select {|c| !c.hidden?}.map{|s| ''.ljust(s.width,'-')}.join('- ') + "\n"
|
269
|
+
|
270
|
+
ret+=(@rows.select{|row| !block_given? || filter.call(row)}.map { |row| row.to_s}).join("\n")
|
271
|
+
|
272
|
+
ret+="\n" + @rows.length.to_s + " rows\n"
|
273
|
+
ret
|
274
|
+
end
|
275
|
+
|
276
|
+
def inspect
|
277
|
+
"Frame Object"
|
278
|
+
end
|
279
|
+
|
280
|
+
def value_columns
|
281
|
+
@columns.find_all { |col| col.value_column?}
|
282
|
+
end
|
283
|
+
|
284
|
+
def formula_columns
|
285
|
+
@columns.find_all { |col| !col.value_column?}
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Pulo
|
2
|
+
class FrameCell
|
3
|
+
|
4
|
+
def initialize(parent_column,parent_row,value=nil)
|
5
|
+
@parent_column=parent_column
|
6
|
+
@parent_row=parent_row
|
7
|
+
@error=false
|
8
|
+
self.value=value
|
9
|
+
end
|
10
|
+
|
11
|
+
def column
|
12
|
+
@parent_column
|
13
|
+
end
|
14
|
+
|
15
|
+
def row
|
16
|
+
@parent_row
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?
|
20
|
+
@value.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def value_column?
|
24
|
+
@parent_column.value_column?
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_error
|
28
|
+
@error=true
|
29
|
+
end
|
30
|
+
def unset_error
|
31
|
+
@error=false
|
32
|
+
end
|
33
|
+
def error?
|
34
|
+
@error
|
35
|
+
end
|
36
|
+
|
37
|
+
def value
|
38
|
+
#raise "Column (#{@parent_column.name}) requires re-calc, value not available." if @parent_column.recalc_required
|
39
|
+
return "ERR" if error?
|
40
|
+
#return "UNK" if @parent_column.recalc_required
|
41
|
+
#return "NIL" if empty?
|
42
|
+
@value
|
43
|
+
end
|
44
|
+
|
45
|
+
def value=(val)
|
46
|
+
|
47
|
+
if @parent_column.column_class==NilClass
|
48
|
+
@parent_column.column_class=val.class
|
49
|
+
if val.class.respond_to?(:quantity_name)
|
50
|
+
@parent_column.column_unit=val.unit
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if val.class.respond_to?(:quantity_name)
|
55
|
+
if val.unit.name!=@parent_column.column_unit.name
|
56
|
+
val=val.send(@parent_column.column_unit.name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
if @parent_column.column_class!=NilClass && val.class!=NilClass
|
61
|
+
if val.class.respond_to?(:quantity_name)
|
62
|
+
unless val.class.dimensions==@parent_column.column_class.dimensions
|
63
|
+
raise "Tried to set a value (#{val.to_s}) of class #{val.class} with dimensions #{val.class.dimensions} on column #{@parent_column.name} which already has a defined class of #{@parent_column.column_class}."
|
64
|
+
end
|
65
|
+
else
|
66
|
+
unless val.class==@parent_column.column_class
|
67
|
+
raise "Tried to set a value (#{val.to_s}) of class #{val.class} on column #{@parent_column.name} which already has a defined class of #{@parent_column.column_class}."
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
@value=val
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
begin
|
76
|
+
@parent_column.formatter.call(value).ljust(@parent_column.width,' ')
|
77
|
+
rescue Exception => e
|
78
|
+
value.to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|