hypersonic-plus 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/hdatastructures/hfieldtable.rb +285 -0
- data/lib/hdatastructures/hhash.rb +9 -0
- data/lib/hdatastructures/hlist.rb +100 -0
- data/lib/hdatastructures/hrecord.rb +75 -0
- data/lib/hdatastructures/hspreadfieldtable.rb +129 -0
- data/lib/hdb/hdataloader.rb +75 -0
- data/lib/hdb/hdb.rb +357 -0
- data/lib/hdb/hdb_test.rb +248 -0
- data/lib/hdb/hdbgenerator.rb +211 -0
- data/lib/hdb/hdbi.rb +63 -0
- data/lib/hdb/hdbi_test.rb +133 -0
- data/lib/hdb/hfield.rb +180 -0
- data/lib/hdb/hmysql.rb +99 -0
- data/lib/hdb/hmysql2.rb +96 -0
- data/lib/hdb/hodb.rb +948 -0
- data/lib/hdb/hpgsql.rb +54 -0
- data/lib/hengine/application_controller.rb +204 -0
- data/lib/hengine/hconfiguration.rb +40 -0
- data/lib/hengine/hhotlogger.rb +13 -0
- data/lib/hengine/hlogger.rb +119 -0
- data/lib/hengine/hmalloc.rb +275 -0
- data/lib/hengine/hmoduleloader.rb +15 -0
- data/lib/hengine/hsessiondata.rb +79 -0
- data/lib/hengine/hshareddata.rb +60 -0
- data/lib/hengine/htranslate.rb +40 -0
- data/lib/hengine/hviewloader.rb +99 -0
- data/lib/hinit/hinit.rb +3 -0
- data/lib/hmisc/hcolorize.rb +100 -0
- data/lib/hmisc/hdecoratorfunctions.rb +15 -0
- data/lib/hmisc/hdir.rb +19 -0
- data/lib/hmisc/hhtmlnode.rb +27 -0
- data/lib/hmisc/hinputvalidator.rb +95 -0
- data/lib/hmisc/hio.rb +142 -0
- data/lib/hmisc/hjson.rb +16 -0
- data/lib/hsqlmanager/hpgsqldatabasemanager.rb +76 -0
- data/lib/hsqlmanager/hsqldatabasemanager.rb +349 -0
- data/lib/hsqlmanager/hsqltable.rb +16 -0
- data/lib/husermanager/husermanager.rb +122 -0
- data/lib/hwidgets/haccordionmenu.rb +117 -0
- data/lib/hwidgets/hcheckboxtag.rb +33 -0
- data/lib/hwidgets/hdbactionbuttons.rb +26 -0
- data/lib/hwidgets/hdbcombobox.rb +71 -0
- data/lib/hwidgets/hdbdialogview.rb +190 -0
- data/lib/hwidgets/hdbfilterview.rb +28 -0
- data/lib/hwidgets/hdbtableview.rb +213 -0
- data/lib/hwidgets/hdbview.rb +63 -0
- data/lib/hwidgets/hdivtag.rb +9 -0
- data/lib/hwidgets/hdropdown.rb +44 -0
- data/lib/hwidgets/hformfield.rb +91 -0
- data/lib/hwidgets/hgrouptag.rb +65 -0
- data/lib/hwidgets/hhiddeninputtag.rb +12 -0
- data/lib/hwidgets/hinputtag.rb +55 -0
- data/lib/hwidgets/hlabeltag.rb +30 -0
- data/lib/hwidgets/hmainview.rb +37 -0
- data/lib/hwidgets/hpagination.rb +65 -0
- data/lib/hwidgets/hradiobuttontag.rb +30 -0
- data/lib/hwidgets/hselecttag.rb +32 -0
- data/lib/hwidgets/htableview.rb +262 -0
- data/lib/hwidgets/htabview.rb +84 -0
- data/lib/hwidgets/htextareatag.rb +20 -0
- data/lib/hwidgets/htopnav.rb +85 -0
- data/lib/hwidgets/hwidget.rb +423 -0
- data/lib/hypersonic.rb +9 -0
- metadata +276 -0
data/lib/hdb/hmysql2.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mysql2'
|
4
|
+
require 'hdb/hdb'
|
5
|
+
|
6
|
+
class Hash
|
7
|
+
|
8
|
+
def join(separator)
|
9
|
+
|
10
|
+
arr = []
|
11
|
+
self.each do |key, value|
|
12
|
+
arr << "#{key} = #{value}"
|
13
|
+
end
|
14
|
+
return arr.join(separator)
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Array
|
20
|
+
|
21
|
+
def hjoin(separator, quoteChar = '"')
|
22
|
+
|
23
|
+
arr = []
|
24
|
+
self.each { |value| arr << "#{value}" }
|
25
|
+
return arr.join(separator)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class HMySql2 < HDB
|
31
|
+
|
32
|
+
def initialize(host, port, dbname, user, password, timezone)
|
33
|
+
|
34
|
+
super(host, port, dbname, user, password, timezone, "hmysql2")
|
35
|
+
@result = nil
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def connect()
|
40
|
+
|
41
|
+
@connection = Mysql2::Client.new(host: @host, username: @user, password: @password, database: @dbname, port: @port.to_i)
|
42
|
+
#hl << "Server version: #{self.execute("SHOW server_version").dataByFieldIndex(0,0).to_s}"
|
43
|
+
self.execute("SET time_zone = '#{@timezone}'") if @timezone
|
44
|
+
return @connection
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def disconnect()
|
49
|
+
|
50
|
+
@connection.close()
|
51
|
+
@connection = nil
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def _execute(queryStr = self.queryStr)
|
56
|
+
|
57
|
+
@result = @connection.query(queryStr)
|
58
|
+
|
59
|
+
return self unless @result
|
60
|
+
|
61
|
+
@resultTable = HFieldTable.new()
|
62
|
+
self.fieldNameList().each { |fieldName| @resultTable.addFieldName(fieldName) }
|
63
|
+
@resultTable.makeCaption()
|
64
|
+
@result.each_with_index do |row, i|
|
65
|
+
row.each do |fieldName, fieldValue|
|
66
|
+
@resultTable.setDataByFieldName(i, fieldName, fieldValue.to_s)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return self
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def fieldNameList()
|
75
|
+
|
76
|
+
fieldList = HList.new()
|
77
|
+
|
78
|
+
@result.fields.each { |fieldName| fieldList << fieldName }
|
79
|
+
|
80
|
+
return fieldList
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def rowsAffected
|
85
|
+
return @connection.affected_rows()
|
86
|
+
end
|
87
|
+
|
88
|
+
def insert(tableName, values)
|
89
|
+
|
90
|
+
self.execute("INSERT INTO #{tableName} #{self.insertValues(values)}")
|
91
|
+
return @connection.last_id
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
data/lib/hdb/hodb.rb
ADDED
@@ -0,0 +1,948 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'hdb/hfield'
|
4
|
+
|
5
|
+
class Array
|
6
|
+
|
7
|
+
# the follow function didn't use
|
8
|
+
# return a table that contains only fields
|
9
|
+
# table = [{a:1, b:2, c:3}, {a:4, b:5, c:6}]
|
10
|
+
# table.filter([:a, :c]) => [{a:1, c:3}, {a:4, c:6}]
|
11
|
+
def filter(fields)
|
12
|
+
|
13
|
+
result = []
|
14
|
+
self.each do |row|
|
15
|
+
result << row.select { |key, value| fields.include?(key) }
|
16
|
+
end
|
17
|
+
return result
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def sortByList(fieldName, list)
|
23
|
+
|
24
|
+
return self unless list
|
25
|
+
|
26
|
+
hash = {}
|
27
|
+
self.each { |row| hash[row[fieldName]] = row }
|
28
|
+
list.each_with_index { |id, i| self[i] = hash[id] }
|
29
|
+
return self
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# if list = [3,2,1,0] => it reverses the @table records
|
34
|
+
def sortByPositionList(list)
|
35
|
+
|
36
|
+
return self unless list
|
37
|
+
|
38
|
+
tableCopy = []
|
39
|
+
self.each_with_index { |row, i| tableCopy[i] = row }
|
40
|
+
list.each_with_index { |id, i| self[i] = tableCopy[list[i]] }
|
41
|
+
return self
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def column(fieldName, recordKey = nil)
|
46
|
+
|
47
|
+
result = []
|
48
|
+
self.each do |row|
|
49
|
+
data = row[fieldName.to_s]
|
50
|
+
data = data.value(recordKey) if data.class == HRecord and recordKey
|
51
|
+
result << data
|
52
|
+
end
|
53
|
+
return result
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class HRecordPtr
|
60
|
+
|
61
|
+
attr_reader :odb, :tableCursor, :type
|
62
|
+
|
63
|
+
def initialize(odb, type = nil)
|
64
|
+
@odb = odb
|
65
|
+
@tableCursor = @odb.tableCursor
|
66
|
+
@type = type
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(sym, *args, &block)
|
70
|
+
|
71
|
+
#puts "=======================================> #{sym.to_s}".red
|
72
|
+
@odb.tableCursor = @tableCursor
|
73
|
+
return @odb.send(sym, *args, &block)
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
class HODB # Object DB
|
81
|
+
|
82
|
+
attr_reader :generate, :modelName, :parentModel, :parent, :connectionName, :hfields, :table, :source, :tmp, :toWrite, :toChange, :tableCursor, :type, :sortField
|
83
|
+
attr_reader :domain # riga da cancellare
|
84
|
+
|
85
|
+
def initialize(modelName = nil, parents = [], connectionName: "default", domain: {}, generate: true)
|
86
|
+
p "modelName: #{modelName}, parents: #{parents}, connectionName = #{connectionName}"
|
87
|
+
@generate = generate # if true build the table into db
|
88
|
+
|
89
|
+
@visited = []
|
90
|
+
|
91
|
+
@toWrite = []
|
92
|
+
@toChange = []
|
93
|
+
@toDelete = []
|
94
|
+
|
95
|
+
@vid = 0 # virtual id
|
96
|
+
|
97
|
+
@tmp = {}
|
98
|
+
@type = nil
|
99
|
+
@source = nil
|
100
|
+
@domain = domain # it's required for example to group the result of oneToMany relation or manyToMany
|
101
|
+
@modelName = modelName
|
102
|
+
@connectionName = connectionName
|
103
|
+
@parents = [] # pairs of type {ptr: 0x..., referenceFieldName: 'modelname_id'}
|
104
|
+
@hfields = {} # hypersonic fields
|
105
|
+
@tableFields = nil # fields of table
|
106
|
+
@modelFields = nil # fields of table + fields of all parents
|
107
|
+
@table = []
|
108
|
+
@tableCursor = nil
|
109
|
+
@allParents = nil
|
110
|
+
|
111
|
+
self.setParents(parents)
|
112
|
+
self.setSystemFields()
|
113
|
+
|
114
|
+
self.init()
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
def recordPtr(type = nil)
|
119
|
+
return HRecordPtr.new(self, type)
|
120
|
+
end
|
121
|
+
|
122
|
+
def newHODB(modelName, type: nil, domain: {})
|
123
|
+
_modelName = modelName.to_s.hcapitalize
|
124
|
+
#puts "newHODB: #{modelName}"
|
125
|
+
p "#{_modelName}.new(connectionName: @connectionName, domain: domain)"
|
126
|
+
odb = (Object.const_defined?(_modelName)) ? eval("#{_modelName}.new(connectionName: @connectionName, domain: domain)") : HODB.new(modelName, connectionName: @connectionName, domain: domain)
|
127
|
+
odb.source = self
|
128
|
+
odb.type = type if type
|
129
|
+
return odb
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.newOdb(modelName, connectionName = "default", domain: {})
|
134
|
+
className = modelName.hcapitalize
|
135
|
+
return eval("#{className}.new(connectionName: connectionName, domain: domain)")
|
136
|
+
end
|
137
|
+
|
138
|
+
def ptrOfRecord(fieldName, fieldValue)
|
139
|
+
|
140
|
+
return fieldValue.tableCursor if fieldValue.class == HRecordPtr # Se si tratta gia' di un ptr a un record lo restituisce
|
141
|
+
@table.each do |record|
|
142
|
+
return record if record[fieldName.to_s] == fieldValue
|
143
|
+
end
|
144
|
+
return nil
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
def allParents()
|
149
|
+
return @allParents if @allParents
|
150
|
+
@allParents = [self]
|
151
|
+
@parents.each { |parent| @allParents += parent[:ptr].allParents() }
|
152
|
+
return @allParents
|
153
|
+
end
|
154
|
+
|
155
|
+
def tableFields # return only the fields of table
|
156
|
+
self.findBy(:false, []) unless @tableFields # poputate @tableFields
|
157
|
+
return @tableFields
|
158
|
+
end
|
159
|
+
|
160
|
+
def modelFields # return all fields
|
161
|
+
return @modelFields if @modelFields
|
162
|
+
@modelFields = Marshal.load(Marshal.dump(self.tableFields()))
|
163
|
+
@parents.each { |parent| @modelFields.merge!(parent[:ptr].modelFields()) }
|
164
|
+
return @modelFields
|
165
|
+
end
|
166
|
+
|
167
|
+
def systemFields(inheritance = false)
|
168
|
+
return self.hfields(inheritance).select { |fieldName, field| field[:system] }
|
169
|
+
end
|
170
|
+
|
171
|
+
def hfields(inheritance = true)
|
172
|
+
return @hfields unless inheritance
|
173
|
+
return @allHfields if @allHfields
|
174
|
+
@allHfields = {}
|
175
|
+
@hfields.each { |fieldName, fieldValue| @allHfields[fieldName] = fieldValue }
|
176
|
+
@parents.each { |parent| @allHfields.merge!( parent[:ptr].hfields(inheritance) ) }
|
177
|
+
return @allHfields
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
# false: return only fields of table
|
182
|
+
# true: return the fields of table + parents fields
|
183
|
+
# :false: return only hfields of table
|
184
|
+
# :true: return only hfields of table + parents hfields
|
185
|
+
def fields(inheritance = false)
|
186
|
+
|
187
|
+
return inheritance if inheritance.class == Array
|
188
|
+
|
189
|
+
case inheritance
|
190
|
+
when true
|
191
|
+
return self.modelFields()
|
192
|
+
when false
|
193
|
+
return self.tableFields()
|
194
|
+
when :true
|
195
|
+
return self.hfields(:true)
|
196
|
+
when :false
|
197
|
+
return self.hfields(:false)
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
def nodeOfField(fieldName)
|
203
|
+
result = self.fields().include?(fieldName) ? [self] : []
|
204
|
+
@parents.each { |parent| result += parent[:ptr].nodeOfField(fieldName) }
|
205
|
+
return @nodes = result
|
206
|
+
end
|
207
|
+
|
208
|
+
def valueOfField(fieldName)
|
209
|
+
nodes = self.nodeOfField(fieldName)
|
210
|
+
return (nodes.any?) ? nodes[0].tableCursor[fieldName] : nil
|
211
|
+
end
|
212
|
+
|
213
|
+
def setValueOfField(fieldName, fieldValue)
|
214
|
+
nodes = self.nodeOfField(fieldName)
|
215
|
+
nodes.each { |node| node.tableCursor[fieldName] = fieldValue }
|
216
|
+
end
|
217
|
+
|
218
|
+
def setParents(parents = [])
|
219
|
+
parents.each do |modelName|
|
220
|
+
referenceFieldName = "#{modelName}_id"
|
221
|
+
parent = {modelName: modelName, referenceFieldName: referenceFieldName}
|
222
|
+
self.addField(referenceFieldName, HField.oneToOne(modelName))
|
223
|
+
#parent[:ptr] = self.newHODB(modelName, domain: @domain)
|
224
|
+
parent[:ptr] = self.newHODB(modelName)
|
225
|
+
@parents << parent
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
def setSystemFields()
|
231
|
+
self.id = HField.primaryKey
|
232
|
+
self.created_date = HField.dateTime(default: '#CURRENT_TIMESTAMP', system: true)
|
233
|
+
self.updated_date = HField.dateTime(default: '#CURRENT_TIMESTAMP', system: true)
|
234
|
+
self.ordering = HField.integer(system: true)
|
235
|
+
end
|
236
|
+
|
237
|
+
def addField(fieldName, args)
|
238
|
+
|
239
|
+
field = HField.autoComplete(@modelName, fieldName, args) # For the magic field
|
240
|
+
@hfields[fieldName] = field
|
241
|
+
hl << "addField: #{fieldName} #{field}"
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
def oneToOne(modelName, referenceFieldName)
|
246
|
+
|
247
|
+
return self.manyToOne(modelName, referenceFieldName, 'oneToOne')
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
def manyToOne(modelName, referenceFieldName, type = 'manyToOne')
|
252
|
+
|
253
|
+
return @tableCursor[modelName] if @tableCursor[modelName]
|
254
|
+
id = self.valueOfField(referenceFieldName)
|
255
|
+
@tableCursor[modelName] = odb = self.newHODB(modelName, type: type)
|
256
|
+
@visited.addIfNotPresent(odb)
|
257
|
+
puts "modelName: #{referenceFieldName}".red
|
258
|
+
@tableCursor.hprint
|
259
|
+
unless id
|
260
|
+
self.setValueOfField(referenceFieldName, odb.recordPtr(type))
|
261
|
+
return odb
|
262
|
+
end
|
263
|
+
@toChange << @tableCursor unless @toChange.include?(@tableCursor)
|
264
|
+
return odb.findBy_id(id)
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
def oneToMany(fieldName, modelName, referenceFieldName)
|
269
|
+
|
270
|
+
return @tableCursor[fieldName] if @tableCursor[fieldName]
|
271
|
+
if(self.id[0] != "#")
|
272
|
+
domain = {"#{referenceFieldName}": self.id}
|
273
|
+
odb = self.newHODB(modelName, type: 'oneToMany', domain: domain).findBy()
|
274
|
+
return @visited.addIfNotPresent(odb)
|
275
|
+
end
|
276
|
+
domain = {"#{referenceFieldName}": nil}
|
277
|
+
odb = self.newHODB(modelName, type: 'oneToMany', domain: domain)
|
278
|
+
@tableCursor[fieldName] = odb
|
279
|
+
@visited.addIfNotPresent(odb)
|
280
|
+
return odb
|
281
|
+
end
|
282
|
+
|
283
|
+
def manyToMany(modelName, joinTable, referenceFieldName, referenceFieldName2)
|
284
|
+
|
285
|
+
odb = self.oneToMany(joinTable, joinTable, referenceFieldName)
|
286
|
+
odb.type = 'manyToMany'
|
287
|
+
odb.tmp[:referenceFieldName] = referenceFieldName2
|
288
|
+
odb.tmp[:rightModelName] = modelName
|
289
|
+
return odb
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
# a_table <--> manyToMany <--> b_table
|
294
|
+
# To access to b_table from a_table -> a_table.a_table_b_table_join.rightModel
|
295
|
+
# Moreover on right model is unsense call the create function
|
296
|
+
def rightModel
|
297
|
+
|
298
|
+
rightModelName = @tmp[:rightModelName]
|
299
|
+
return @tableCursor[rightModelName] if @tableCursor[rightModelName]
|
300
|
+
|
301
|
+
ids = @table.column(@tmp[:referenceFieldName])
|
302
|
+
where = "id IN (#{ids.join(',')})"
|
303
|
+
odb = self.newHODB(rightModelName, type: 'rightTable').findBy(where) if (@type == 'manyToMany')
|
304
|
+
@visited.addIfNotPresent(odb)
|
305
|
+
return @tableCursor[rightModelName] = odb
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
def virtualField(obj, functionName, &block)
|
310
|
+
|
311
|
+
return block.call(self) if block
|
312
|
+
#hl << "obj.#{functionName.to_s}(self)"
|
313
|
+
return eval("obj.#{functionName.to_s}(self)") if obj and functionName
|
314
|
+
|
315
|
+
end
|
316
|
+
|
317
|
+
def inspection(str)
|
318
|
+
puts "=============> #{str}"
|
319
|
+
return false
|
320
|
+
end
|
321
|
+
|
322
|
+
def fieldProperty(fieldName, property)
|
323
|
+
|
324
|
+
return nil unless fieldName
|
325
|
+
hfield = self.hfields()[fieldName.to_s] || self.hfields()[fieldName.to_sym]
|
326
|
+
return hfield[property.to_s] || hfield[property.to_sym] if hfield
|
327
|
+
return nil
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
|
332
|
+
# [[:a, :b, :c], [1, 2, 3]].transpose
|
333
|
+
# => [[:a, 1], [:b, 2], [:c, 3]]
|
334
|
+
def method_missing(sym, *args, &block)
|
335
|
+
if sym =~ /^(\w+)=$/
|
336
|
+
if args[0].class == HField
|
337
|
+
self.addField($1.to_s, args[0])
|
338
|
+
elsif self.nodeOfField($1.to_s).any?
|
339
|
+
@nodes.each { |node| node.tableCursor[$1.to_s] = args[0] if node.tableCursor }
|
340
|
+
@toChange << @tableCursor if (!@toChange.include?(@tableCursor) and @tableCursor)
|
341
|
+
elsif instance_variable_defined?("@#{$1.to_s}") # is required to use attr_reader to setting
|
342
|
+
instance_variable_set("@#{$1}", args[0])
|
343
|
+
else
|
344
|
+
hl.<<("hodb::method_missing: #{$1.to_s} not found", "ERROR")
|
345
|
+
end
|
346
|
+
return
|
347
|
+
elsif sym.to_s =~ /^findBy_(.+)$/
|
348
|
+
attrs = $1.split('_and_')
|
349
|
+
attrs_with_args = [attrs, args].transpose
|
350
|
+
where = Hash[attrs_with_args]
|
351
|
+
return self.findBy(where)
|
352
|
+
elsif @hfields[sym.to_s] and @hfields[sym.to_s][:modelNameReference]
|
353
|
+
modelName = @hfields[sym.to_s][:modelNameReference]
|
354
|
+
type = self.fieldProperty(sym, :type)
|
355
|
+
return self.oneToOne(modelName, sym.to_s) if (type == 'oneToOne')
|
356
|
+
return self.manyToOne(modelName, sym.to_s) if (type == 'manyToOne')
|
357
|
+
referenceFieldName = @hfields[sym.to_s][:referenceFieldName]
|
358
|
+
return self.oneToMany(sym.to_s, modelName, referenceFieldName) if (type == 'oneToMany')
|
359
|
+
joinTable = @hfields[sym.to_s][:joinTable]
|
360
|
+
referenceFieldName2 = @hfields[sym.to_s][:referenceFieldName2]
|
361
|
+
return self.manyToMany(modelName, joinTable, referenceFieldName, referenceFieldName2) if (type == 'manyToMany')
|
362
|
+
elsif @hfields[sym.to_s] and @hfields[sym.to_s][:type] == 'virtual'
|
363
|
+
return self.virtualField(@hfields[sym.to_s][:object] || self, @hfields[sym.to_s][:functionName], &@hfields[sym.to_s][:block])
|
364
|
+
elsif sym =~ /^(\w+)_id$/
|
365
|
+
return self.manyToOne($1.to_s, sym.to_s)
|
366
|
+
elsif sym =~ /^(\w+)_table$/
|
367
|
+
return self.oneToMany(sym.to_s, $1.to_s, "#{@modelName}_id")
|
368
|
+
elsif sym =~ /^(\w+)_join$/
|
369
|
+
return self.manyToMany($1.to_s, "#{@modelName}_#{$1.to_s}_join", "#{@modelName}_id", "#{$1.to_s}_id")
|
370
|
+
elsif @tableCursor and @tableCursor.include?(sym.to_s)
|
371
|
+
return @tableCursor[sym.to_s]
|
372
|
+
#elsif sym =~ /^(\w+)_virtual$/
|
373
|
+
# return self.virtualField($1.to_s, self, &block)
|
374
|
+
else
|
375
|
+
@parents.each do |parent|
|
376
|
+
result = parent[:ptr].method_missing(sym, *args, &block)
|
377
|
+
return result if result
|
378
|
+
end
|
379
|
+
end
|
380
|
+
hl.<<("hodb::method_missing: #{sym.to_s} not found", "ERROR")
|
381
|
+
return nil
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
def reset
|
386
|
+
@parents.each { |parent| parent[:ptr].reset }
|
387
|
+
@tableCursor = nil
|
388
|
+
end
|
389
|
+
|
390
|
+
def first
|
391
|
+
self.reset
|
392
|
+
return self.next
|
393
|
+
end
|
394
|
+
|
395
|
+
def last
|
396
|
+
@tableCursor = @table.count > 0 ? @table[@table.count - 1] : nil
|
397
|
+
return self
|
398
|
+
end
|
399
|
+
|
400
|
+
def setTableCursor(tableCursor = @tableCursor)
|
401
|
+
@tableCursor = tableCursor
|
402
|
+
@id = @tableCursor["id"]
|
403
|
+
@parents.each do |parent|
|
404
|
+
parentTableCursor = @tableCursor[parent[:referenceFieldName]]
|
405
|
+
parentTableCursor = parent[:ptr].ptrOfRecord("id", parentTableCursor)
|
406
|
+
parent[:ptr].setTableCursor(parentTableCursor)
|
407
|
+
end
|
408
|
+
return self
|
409
|
+
end
|
410
|
+
|
411
|
+
def next()
|
412
|
+
|
413
|
+
index = @tableCursor ? @table.index(@tableCursor) + 1 : 0
|
414
|
+
|
415
|
+
if (index < @table.count)
|
416
|
+
@tableCursor = @table[index]
|
417
|
+
self.setTableCursor
|
418
|
+
return self
|
419
|
+
end
|
420
|
+
return nil
|
421
|
+
|
422
|
+
end
|
423
|
+
|
424
|
+
def each
|
425
|
+
|
426
|
+
self.execute unless @executed
|
427
|
+
|
428
|
+
self.reset()
|
429
|
+
while(self.next) do
|
430
|
+
yield(self)
|
431
|
+
end
|
432
|
+
|
433
|
+
@tableCursor = nil
|
434
|
+
self.init()
|
435
|
+
|
436
|
+
end
|
437
|
+
|
438
|
+
def each_with_index
|
439
|
+
i = -1
|
440
|
+
self.each do |record|
|
441
|
+
yield(self, i += 1)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
|
446
|
+
def eachField(inheritance = true)
|
447
|
+
self.fields(inheritance).each do |fieldName, fieldValue|
|
448
|
+
fieldValue = self.data(fieldName)
|
449
|
+
fieldValue = eval("self.#{fieldName}") unless fieldValue # si tratta di campi virtual runtime
|
450
|
+
yield(fieldName, fieldValue)
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
|
455
|
+
def toFieldTable(inheritance = true)
|
456
|
+
|
457
|
+
fieldTable = HSpreadFieldTable.new
|
458
|
+
fieldTable.tableName = @modelName
|
459
|
+
|
460
|
+
self.fields(inheritance).each do |fieldName, fieldValue|
|
461
|
+
fieldTable.addFieldName(fieldName)
|
462
|
+
fieldTable.setFieldCaption(fieldName, fieldName.to_s.hcapitalize)
|
463
|
+
fieldType = self.fieldProperty(fieldName.to_s, :type)
|
464
|
+
fieldTable.setFieldType(fieldName, fieldType) if fieldType
|
465
|
+
end
|
466
|
+
|
467
|
+
self.each_with_index do |row, i|
|
468
|
+
row.eachField(inheritance) do |fieldName, fieldValue|
|
469
|
+
fieldTable.setIntoRecordByFieldName(i, fieldName, fieldValue)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
return fieldTable
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
def allRelations
|
478
|
+
result = []
|
479
|
+
result << hdb(@connectionName).normalizeWhereFormat(@domain) if @domain.class == String or @domain.any?
|
480
|
+
@parents.each do |parent|
|
481
|
+
result += ["#{@modelName}.#{parent[:referenceFieldName]} = #{parent[:ptr].modelName}.id"] + parent[:ptr].allRelations
|
482
|
+
end
|
483
|
+
return result
|
484
|
+
end
|
485
|
+
|
486
|
+
def allModels
|
487
|
+
result = []
|
488
|
+
self.allParents().each { |parent| result << parent.modelName unless result.include?(parent.modelName) }
|
489
|
+
return result
|
490
|
+
end
|
491
|
+
|
492
|
+
def modelNameOfField(fieldName)
|
493
|
+
|
494
|
+
fieldName = fieldName.to_s
|
495
|
+
node = self.nodeOfField(fieldName)
|
496
|
+
return (node.any?) ? node[0].modelName : nil
|
497
|
+
|
498
|
+
end
|
499
|
+
|
500
|
+
def modelNameAndFieldName(fieldName)
|
501
|
+
|
502
|
+
modelName = self.modelNameOfField(fieldName)
|
503
|
+
return (modelName) ? "#{modelName}.#{fieldName}" : fieldName
|
504
|
+
|
505
|
+
end
|
506
|
+
|
507
|
+
def data(fieldName)
|
508
|
+
|
509
|
+
fieldName = fieldName.to_s
|
510
|
+
node = self.nodeOfField(fieldName)
|
511
|
+
return (node.any?) ? node[0].tableCursor[fieldName] : nil
|
512
|
+
|
513
|
+
end
|
514
|
+
|
515
|
+
|
516
|
+
def normalizeWhereFormat(where)
|
517
|
+
|
518
|
+
if where.class == Hash # findBy {'c_tables.id': 1}
|
519
|
+
newWhere = {}
|
520
|
+
where.each { |fieldName, fieldValue| newWhere[self.modelNameAndFieldName(fieldName)] = fieldValue }
|
521
|
+
where = newWhere
|
522
|
+
end
|
523
|
+
|
524
|
+
return hdb(@connectionName).normalizeWhereFormat(where)
|
525
|
+
|
526
|
+
end
|
527
|
+
|
528
|
+
def init()
|
529
|
+
@where = "true"
|
530
|
+
@orderBy = "id"
|
531
|
+
@pageSize = "all"
|
532
|
+
@page = 0
|
533
|
+
end
|
534
|
+
|
535
|
+
def where(where)
|
536
|
+
@executed = false
|
537
|
+
@where = where
|
538
|
+
return self
|
539
|
+
end
|
540
|
+
def orderBy(orderBy)
|
541
|
+
@executed = false
|
542
|
+
orderBy = orderBy.hjoin(', ') if(orderBy.class == Array)
|
543
|
+
@orderBy = orderBy
|
544
|
+
return self
|
545
|
+
end
|
546
|
+
def direction(direction)
|
547
|
+
@executed = false
|
548
|
+
@direction = direction
|
549
|
+
return self
|
550
|
+
end
|
551
|
+
def pageSize(pageSize)
|
552
|
+
@executed = false
|
553
|
+
@pageSize = pageSize
|
554
|
+
return self
|
555
|
+
end
|
556
|
+
def page(page)
|
557
|
+
@executed = false
|
558
|
+
@page = page
|
559
|
+
return self
|
560
|
+
end
|
561
|
+
|
562
|
+
def sortOffLine(fieldName = "id", sortDirection = 'desc', sortMap = [])
|
563
|
+
|
564
|
+
# table = [{id:7, name:'valerio', surname:'bianchi'},
|
565
|
+
# {id:8, name:'mario', surname:'rossi'},
|
566
|
+
# {id:6, name:'laura', surname:'neri'}]
|
567
|
+
#
|
568
|
+
# table.sort_by { |row| row["name"] } =>
|
569
|
+
# {id:6, name:'laura', surname:'neri'},
|
570
|
+
# {id:8, name:'mario', surname:'rossi'},
|
571
|
+
# {id:7, name:'valerio', surname:'bianchi'}
|
572
|
+
# columnSorted = tableSorted.column("id") => [1, 3, 2]
|
573
|
+
# idColumn = @table.column("id") => [2, 3, 1]
|
574
|
+
# sortMap => [2, 1, 0]
|
575
|
+
# A this time to print the records it is enough to scan sortMap
|
576
|
+
# The first element to print is @table[2] => @table[1] => @table[0]
|
577
|
+
|
578
|
+
puts "========================================================".red
|
579
|
+
puts "======= sortOffLine =======".red
|
580
|
+
puts "========================================================".red
|
581
|
+
puts "currentModelName: #{@modelName}".red
|
582
|
+
if sortMap.empty?
|
583
|
+
node = self.nodeOfField(fieldName)[0]
|
584
|
+
return unless node
|
585
|
+
puts "modelName of #{fieldName}: #{node.modelName}".red
|
586
|
+
|
587
|
+
p node.hfields()
|
588
|
+
fieldType = node.hfields()[fieldName] ? node.hfields()[fieldName][:type] : nil
|
589
|
+
puts "type of #{fieldName}: #{fieldType}"
|
590
|
+
tableSorted = nil
|
591
|
+
if fieldType == "integer"
|
592
|
+
tableSorted = node.table.sort_by { |row| row[fieldName].to_i }
|
593
|
+
elsif fieldType == "float"
|
594
|
+
tableSorted = node.table.sort_by { |row| row[fieldName].to_f }
|
595
|
+
elsif fieldType == "time"
|
596
|
+
tableSorted = node.table.sort_by { |row| row[fieldName].to_time }
|
597
|
+
elsif fieldType == "date_time"
|
598
|
+
tableSorted = node.table.sort_by { |row| row[fieldName].to_datetime }
|
599
|
+
else
|
600
|
+
tableSorted = node.table.sort_by { |row| row[fieldName] }
|
601
|
+
end
|
602
|
+
|
603
|
+
tableSorted.reverse! if sortDirection == 'asc'
|
604
|
+
|
605
|
+
columnSorted = tableSorted.column("id")
|
606
|
+
idColumn = node.table.column("id")
|
607
|
+
columnSorted.each_with_index { |value, i| sortMap[i] = idColumn.index(value) }
|
608
|
+
p sortMap
|
609
|
+
end
|
610
|
+
|
611
|
+
@table.sortByPositionList(sortMap)
|
612
|
+
|
613
|
+
@parents.each do |parent|
|
614
|
+
parent[:ptr].sortOffLine(nil, sortDirection, sortMap)
|
615
|
+
end
|
616
|
+
|
617
|
+
end
|
618
|
+
|
619
|
+
# findByOffLine({id: 1, name: 'margherita'})
|
620
|
+
def findByOffLine(where)
|
621
|
+
|
622
|
+
tableCursor = @tableCursor
|
623
|
+
self.each do |record|
|
624
|
+
return self if where.each do |fieldName, fieldValue|
|
625
|
+
#puts "#{record.valueOfField(fieldName.to_s)} - #{fieldValue}"
|
626
|
+
break if record.valueOfField(fieldName.to_s) != fieldValue
|
627
|
+
end
|
628
|
+
end
|
629
|
+
self.setTableCursor(tableCursor) # if not found restore the tableCursor value
|
630
|
+
return self
|
631
|
+
|
632
|
+
end
|
633
|
+
|
634
|
+
# example: findBy({id: 1})
|
635
|
+
# findBy({'c_tables.id': 1}) - I can specify the field of the another table
|
636
|
+
# findBy({id: 1, name: 'ciao'}) -> c_tables.id = '1' AND c_tables.name = 'ciao'
|
637
|
+
# The follow statement isn't safe. You can use it, only if the values don't come from forms but they are statics
|
638
|
+
# findBy(["c_tables.id > 0", "c_tables.name = 'ciao'"])
|
639
|
+
# The follow statement is safe as the ? syntax and you can use the values from forms
|
640
|
+
# findBy(["c_tables.id > 0", "c_tables.name = #{q(form_field)}"])
|
641
|
+
|
642
|
+
def findBy(where = 'true', ids = nil, orderBy: nil, direction: nil, pageSize: "all", page: 0)
|
643
|
+
|
644
|
+
return self unless where
|
645
|
+
where = self.normalizeWhereFormat(where)
|
646
|
+
|
647
|
+
model = (ids == nil) ? self.allModels.join(', ') : @modelName
|
648
|
+
where = (self.allRelations << where).join(' and ') if !ids and where
|
649
|
+
|
650
|
+
hdb = hdb(@connectionName).
|
651
|
+
select("#{modelName}.*").
|
652
|
+
from(model).
|
653
|
+
where(where).
|
654
|
+
orderBy(orderBy).
|
655
|
+
direction(direction).
|
656
|
+
execute(pageSize: pageSize, page: page)
|
657
|
+
|
658
|
+
@tableFields = Hash[hdb.fieldNameList()]
|
659
|
+
@table = hdb.table.sortByList("id", ids)
|
660
|
+
@tableCursor = nil
|
661
|
+
|
662
|
+
return self if @table.count == 0
|
663
|
+
|
664
|
+
@parents.each do |parent|
|
665
|
+
ids = @table.column(parent[:referenceFieldName])
|
666
|
+
parent[:ptr].findBy("id IN (#{ids.join(',')})", ids)
|
667
|
+
end
|
668
|
+
return self.next().recordPtr('manyToOne')
|
669
|
+
|
670
|
+
end
|
671
|
+
|
672
|
+
def execute
|
673
|
+
# @executed serve per evitare di chiamare execute nelle istruzioni del tipo:
|
674
|
+
# odb.where(filter).orderBy(sortField).direction(sortDirection).pageSize(pageSize).page(page)
|
675
|
+
@executed = true
|
676
|
+
return self.findBy(@where, nil, orderBy: @orderBy, direction: @direction, pageSize: @pageSize, page: @page)
|
677
|
+
end
|
678
|
+
|
679
|
+
def all
|
680
|
+
return self.findBy()
|
681
|
+
end
|
682
|
+
|
683
|
+
def defaultValue(fieldName)
|
684
|
+
field = @hfields[fieldName.to_s]
|
685
|
+
return nil unless field
|
686
|
+
return (field[:default]) ? field[:default] : field.defaultValue()
|
687
|
+
end
|
688
|
+
|
689
|
+
def defaultRecord(record)
|
690
|
+
defaultRecord = Marshal.load(Marshal.dump(self.fields()))
|
691
|
+
defaultRecord.each { |fieldName, fieldValue| defaultRecord[fieldName.to_s] = self.defaultValue(fieldName) }
|
692
|
+
defaultRecord["id"] = "##{@vid+=1}"
|
693
|
+
record.each {|fieldName,fieldValue| defaultRecord[fieldName.to_s] = fieldValue if defaultRecord.include?(fieldName.to_s)}
|
694
|
+
@domain.each {|fieldName,fieldValue| defaultRecord[fieldName.to_s] = fieldValue if defaultRecord.include?(fieldName.to_s)} if @domain.class == Hash
|
695
|
+
puts "#{defaultRecord}".red
|
696
|
+
return defaultRecord
|
697
|
+
end
|
698
|
+
|
699
|
+
def create(record = {})
|
700
|
+
defaultRecord = self.defaultRecord(record)
|
701
|
+
@parents.each { |parent| defaultRecord[parent[:referenceFieldName]] = parent[:ptr].create(record) }
|
702
|
+
@toWrite << defaultRecord
|
703
|
+
@table << defaultRecord
|
704
|
+
self.last
|
705
|
+
return self.recordPtr("parent")
|
706
|
+
end
|
707
|
+
|
708
|
+
def setRecord(record, tableCursor = @tableCursor)
|
709
|
+
@toChange << tableCursor unless @toChange.include?(tableCursor)
|
710
|
+
record.each do |fieldName, fieldValue|
|
711
|
+
unless self.fields(true).include?(fieldName.to_s)
|
712
|
+
hl.<<("hodb::setRecord: #{fieldName.to_s} not found", "ERROR")
|
713
|
+
next
|
714
|
+
end
|
715
|
+
setValueOfField(fieldName.to_s, fieldValue)
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
|
720
|
+
def write(values = {})
|
721
|
+
hl << "********************************* write(#{@type}) *********************************"
|
722
|
+
return self unless @toWrite.include?(@tableCursor)
|
723
|
+
return self unless values
|
724
|
+
puts "#{values}".red
|
725
|
+
@tableCursor.merge!(values)
|
726
|
+
@tableCursor["id"] = "#default" if @tableCursor["id"][0] == "#"
|
727
|
+
@tableCursor.each do |fieldName, fieldValue|
|
728
|
+
if fieldValue.class == HRecordPtr
|
729
|
+
if fieldValue.type == "parent"
|
730
|
+
@tableCursor[fieldName] = fieldValue.write(values).id
|
731
|
+
elsif fieldValue.type == "manyToOne" or fieldValue.type == "oneToOne"
|
732
|
+
@tableCursor[fieldName] = fieldValue.write().id
|
733
|
+
elsif fieldValue.type == nil # questo caso non deve verificarsi
|
734
|
+
hl.<<("hodb::write: ", "ERROR")
|
735
|
+
fieldValue.tableCursor.hprint
|
736
|
+
end
|
737
|
+
end
|
738
|
+
end
|
739
|
+
# intersect rimuove ad es. i campy oneToMany e i campi inseriti dalla merge! sopra se non fanno parte del @tableCursor
|
740
|
+
@tableCursor["id"] = hdb(@connectionName).insert(@modelName, @tableCursor.intersect(self.fields))
|
741
|
+
@tableCursor.each do |fieldName, fieldValue|
|
742
|
+
if fieldValue.class <= HODB and (fieldValue.type == 'oneToMany' or fieldValue.type == 'manyToMany' or fieldValue.type == 'rightTable')
|
743
|
+
referenceFieldName = fieldValue.domain.keys[0].to_s
|
744
|
+
fieldValue.writeAll({"#{referenceFieldName}" => @tableCursor["id"]})
|
745
|
+
end
|
746
|
+
end
|
747
|
+
@toWrite.delete(@tableCursor)
|
748
|
+
return self
|
749
|
+
end
|
750
|
+
|
751
|
+
def writeAll(values = {})
|
752
|
+
|
753
|
+
puts "********************* writeAll ********************".pink
|
754
|
+
|
755
|
+
@toDelete.each { |record| self.delete({id: record["id"]}) }
|
756
|
+
@toDelete.clear
|
757
|
+
|
758
|
+
toWrite = @toWrite.dup
|
759
|
+
toWrite.each do |record|
|
760
|
+
@tableCursor = record
|
761
|
+
self.write(values)
|
762
|
+
end
|
763
|
+
return self
|
764
|
+
end
|
765
|
+
|
766
|
+
def save(values = {})
|
767
|
+
hl << "********************************* save(#{@type} - #{@modelName}) *********************************"
|
768
|
+
#return self unless @toChange.include?(@tableCursor)
|
769
|
+
puts "#{values}".red
|
770
|
+
@tableCursor.hprint
|
771
|
+
@tableCursor.merge!(values)
|
772
|
+
@tableCursor["id"] = "#default" if @tableCursor["id"][0] == "#"
|
773
|
+
self.setTableCursor(@tableCursor)
|
774
|
+
@tableCursor.each do |fieldName, fieldValue|
|
775
|
+
if fieldValue.class <= HODB and (fieldValue.type == 'manyToOne' or fieldValue.type == 'oneToOne')
|
776
|
+
puts "call: #{fieldName} - #{fieldValue.domain}".red
|
777
|
+
@tableCursor[fieldName] = fieldValue.saveAll().id
|
778
|
+
end
|
779
|
+
end
|
780
|
+
@parents.each { |parent| parent[:ptr].save(values) }
|
781
|
+
# intersect rimuove ad es. i campy oneToMany e i campi inseriti dalla merge! sopra se non fanno parte del @tableCursor
|
782
|
+
hdb(@connectionName).update(@modelName, @tableCursor.intersect(self.fields), {id: @tableCursor["id"]})
|
783
|
+
@tableCursor.each do |fieldName, fieldValue|
|
784
|
+
if fieldValue.class <= HODB and (fieldValue.type == 'oneToMany' or fieldValue.type == 'manyToMany' or fieldValue.type == 'rightTable')
|
785
|
+
p "saveAll".red
|
786
|
+
fieldValue.saveAll()
|
787
|
+
end
|
788
|
+
end
|
789
|
+
@toChange.delete(@tableCursor)
|
790
|
+
return self
|
791
|
+
end
|
792
|
+
|
793
|
+
def saveAll(values = {})
|
794
|
+
toChange = @toChange.dup
|
795
|
+
toChange.each do |record|
|
796
|
+
@tableCursor = record
|
797
|
+
self.save(values)
|
798
|
+
end
|
799
|
+
return self
|
800
|
+
end
|
801
|
+
|
802
|
+
def delete(where = "TRUE", ids = nil)
|
803
|
+
|
804
|
+
where = self.normalizeWhereFormat(where)
|
805
|
+
|
806
|
+
model = (ids == nil) ? self.allModels.join(', ') : @modelName
|
807
|
+
where = (self.allRelations << where).join(' and ') unless ids
|
808
|
+
|
809
|
+
@tableCursor = nil
|
810
|
+
table = hdb(@connectionName).select("#{modelName}.*").from(model).where(where).execute.table
|
811
|
+
return self if table.count == 0
|
812
|
+
|
813
|
+
ids = table.column(:id)
|
814
|
+
hdb(@connectionName).delete(@modelName, "id IN (#{ids.join(',')})")
|
815
|
+
|
816
|
+
ids.each { |id| @table.delete(self.ptrOfRecord("id", id)) }
|
817
|
+
|
818
|
+
@parents.each do |parent|
|
819
|
+
ids = table.column(parent[:referenceFieldName])
|
820
|
+
parent[:ptr].delete("id IN (#{ids.join(',')})", ids)
|
821
|
+
end
|
822
|
+
return self
|
823
|
+
|
824
|
+
end
|
825
|
+
|
826
|
+
|
827
|
+
def _remove(record = @tableCursor)
|
828
|
+
|
829
|
+
record = record.tableCursor if record.class == HRecordPtr
|
830
|
+
puts "_remove: #{record}".pink
|
831
|
+
puts "============================".red
|
832
|
+
if (record["id"][0] == "#")
|
833
|
+
@parents.each { |parent| record[parent[:referenceFieldName]]._remove }
|
834
|
+
@toWrite.delete(record)
|
835
|
+
@toChange.delete(record)
|
836
|
+
else
|
837
|
+
@parents.each do |parent|
|
838
|
+
referenceFieldName = parent[:referenceFieldName]
|
839
|
+
id = record[referenceFieldName]
|
840
|
+
parent[:ptr].remove(id)
|
841
|
+
end
|
842
|
+
@toDelete << record
|
843
|
+
end
|
844
|
+
@table.delete(record)
|
845
|
+
|
846
|
+
end
|
847
|
+
|
848
|
+
# virtual remove => the real removal happens with apply
|
849
|
+
def remove(recordId = @tableCursor["id"])
|
850
|
+
|
851
|
+
puts "remove: #{@modelName} - #{recordId}".yellow
|
852
|
+
self.findByOffLine({id: recordId})
|
853
|
+
self._remove(@tableCursor)
|
854
|
+
|
855
|
+
end
|
856
|
+
|
857
|
+
|
858
|
+
def apply
|
859
|
+
puts "************************* apply **********************".pink
|
860
|
+
self.writeAll
|
861
|
+
self.saveAll
|
862
|
+
@parents.each { |parent| parent[:ptr].apply }
|
863
|
+
@visited.each do |odb|
|
864
|
+
puts "####################################=> #{odb.modelName}".pink
|
865
|
+
odb.apply
|
866
|
+
end
|
867
|
+
@visited.clear
|
868
|
+
end
|
869
|
+
|
870
|
+
def columnWidth(fieldName, inheritance = true)
|
871
|
+
|
872
|
+
return @colsWidth[fieldName] if @colsWidth.include?(fieldName)
|
873
|
+
|
874
|
+
maxLength = fieldName.length
|
875
|
+
self.each do |row|
|
876
|
+
row.eachField(inheritance) do |fieldName, fieldValue|
|
877
|
+
len = fieldValue.to_s.length
|
878
|
+
maxLength = len if maxLength < len and fieldValue.class != HRecordPtr and fieldValue.class > HODB
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
return @colsWidth[fieldName] = maxLength
|
883
|
+
|
884
|
+
end
|
885
|
+
|
886
|
+
def showValue(fieldName, fieldValue, color = nil, separator = '|')
|
887
|
+
|
888
|
+
fieldValue = fieldValue.object_id if fieldValue.class == HRecordPtr or fieldValue.class <= HODB
|
889
|
+
value = " #{fieldValue.to_s.center(self.columnWidth(fieldName))} #{separator}"
|
890
|
+
unless color
|
891
|
+
print value
|
892
|
+
else
|
893
|
+
print eval "'#{value}'.#{color}"
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
def showHeader(color, inheritance = true)
|
898
|
+
|
899
|
+
puts
|
900
|
+
print eval "' >> #{@modelName.to_s} <<'.#{color}"
|
901
|
+
puts
|
902
|
+
self.fields(inheritance).each do |fieldName, fieldValue|
|
903
|
+
self.showValue(fieldName, "-" * self.columnWidth(fieldName, inheritance), color, '+' )
|
904
|
+
end
|
905
|
+
puts
|
906
|
+
self.fields(inheritance).each do |fieldName, fieldValue|
|
907
|
+
self.showValue(fieldName, fieldName, color, '|')
|
908
|
+
end
|
909
|
+
puts
|
910
|
+
self.fields(inheritance).each do |fieldName, fieldValue|
|
911
|
+
self.showValue(fieldName, "-" * self.columnWidth(fieldName, inheritance), color, '+' )
|
912
|
+
end
|
913
|
+
puts
|
914
|
+
end
|
915
|
+
|
916
|
+
def show(color = 'hight_cyan', inheritance = true)
|
917
|
+
@colsWidth = {}
|
918
|
+
@parents.each do |parent|
|
919
|
+
parent[:ptr].show(color, inheritance) unless (inheritance)
|
920
|
+
end
|
921
|
+
self.showHeader(color, inheritance)
|
922
|
+
self.each do |row|
|
923
|
+
row.eachField(inheritance) do |fieldName, fieldValue|
|
924
|
+
self.showValue(fieldName, fieldValue, 'white')
|
925
|
+
end
|
926
|
+
puts
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
930
|
+
def self.test1
|
931
|
+
a = HODB.new({a: 1, b: 2, c: 3})
|
932
|
+
a.a = 0
|
933
|
+
p a.a
|
934
|
+
p a.b
|
935
|
+
a.d = 40 # make a variable automatically
|
936
|
+
p a.d
|
937
|
+
end
|
938
|
+
|
939
|
+
def self.test2
|
940
|
+
odb = HODB.new
|
941
|
+
odb.name = HField.text(caption: 'Name', mandatory: true, readonly: false)
|
942
|
+
odb.name = "hypersonic"
|
943
|
+
p odb.hfields(:name), odb.name
|
944
|
+
end
|
945
|
+
|
946
|
+
end
|
947
|
+
|
948
|
+
#HODB.test2
|