rhodes-framework 1.2.0 → 1.2.1
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/Manifest.txt +0 -1
- data/lib/rhodes.rb +2 -2
- data/lib/rhom/rhom.rb +71 -71
- data/lib/rhom/rhom_db_adapter.rb +252 -249
- data/lib/rhom/rhom_object_factory.rb +339 -339
- data/lib/version.rb +2 -2
- metadata +2 -3
- data/rhodes-framework.gemspec +0 -18
@@ -1,340 +1,340 @@
|
|
1
|
-
#
|
2
|
-
# rhom_object_factory.rb
|
3
|
-
# rhodes
|
4
|
-
# Returns an array of RhomObjects
|
5
|
-
#
|
6
|
-
# Copyright (C) 2008 Rhomobile, Inc. All rights reserved.
|
7
|
-
#
|
8
|
-
# This program is free software: you can redistribute it and/or modify
|
9
|
-
# it under the terms of the GNU General Public License as published by
|
10
|
-
# the Free Software Foundation, either version 3 of the License, or
|
11
|
-
# (at your option) any later version.
|
12
|
-
#
|
13
|
-
# This program is distributed in the hope that it will be useful,
|
14
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
-
# GNU General Public License for more details.
|
17
|
-
#
|
18
|
-
# You should have received a copy of the GNU General Public License
|
19
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
-
#
|
21
|
-
require 'rhom'
|
22
|
-
require 'rho'
|
23
|
-
require 'rho/rhosupport'
|
24
|
-
|
25
|
-
module Rhom
|
26
|
-
class RhomObjectFactory
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
unless not defined? Rho::RhoConfig.sources
|
30
|
-
init_objects
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Initialize new object with dynamic attributes
|
35
|
-
def init_objects
|
36
|
-
Rho::RhoConfig.sources.each do |classname,source|
|
37
|
-
unless Object.const_defined?(classname.intern)
|
38
|
-
Object.const_set(classname.intern,
|
39
|
-
Class.new do
|
40
|
-
include ::Rhom::RhomObject
|
41
|
-
extend ::Rhom::RhomObject
|
42
|
-
|
43
|
-
# This holds the attributes for an instance of
|
44
|
-
# the rhom object
|
45
|
-
attr_accessor :vars
|
46
|
-
|
47
|
-
def initialize(obj=nil)
|
48
|
-
@vars = {}
|
49
|
-
self.vars['object'] = "#{((Time.now.to_f - Time.mktime(2009,"jan",1,0,0,0,0).to_f) * 10**6).to_i}"
|
50
|
-
if obj
|
51
|
-
obj.each do |key,value|
|
52
|
-
self.vars[key] = value
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def method_missing(name, *args)
|
58
|
-
unless name == Fixnum
|
59
|
-
varname = name.to_s.gsub(/\=/,"")
|
60
|
-
setting = (name.to_s =~ /=/)
|
61
|
-
if setting
|
62
|
-
@vars[varname] = args[0]
|
63
|
-
else
|
64
|
-
@vars[varname]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class << self
|
70
|
-
|
71
|
-
def count
|
72
|
-
SyncEngine.lock_sync_mutex
|
73
|
-
res = ::Rhom::RhomDbAdapter.select_from_table('object_values','object', {"source_id"=>get_source_id}, {"distinct"=>true}).length
|
74
|
-
SyncEngine.unlock_sync_mutex
|
75
|
-
res
|
76
|
-
end
|
77
|
-
|
78
|
-
def get_source_id
|
79
|
-
Rho::RhoConfig.sources[self.name.to_s]['source_id'].to_s
|
80
|
-
end
|
81
|
-
|
82
|
-
# retrieve a single record if object id provided, otherwise return
|
83
|
-
# full list corresponding to factory's source id
|
84
|
-
def find(*args)
|
85
|
-
raise ::Rhom::RecordNotFound if args[0].nil? or args.length == 0
|
86
|
-
puts "Inside find: args - #{args.inspect}"
|
87
|
-
ret_list = []
|
88
|
-
conditions = {}
|
89
|
-
where_cond = nil
|
90
|
-
# first find all query objects
|
91
|
-
if args.first == :all
|
92
|
-
where_cond = {"source_id"=>get_source_id}
|
93
|
-
elsif args.first.is_a?(String)
|
94
|
-
where_cond = {"object"=>strip_braces(args.first.to_s)}
|
95
|
-
end
|
96
|
-
|
97
|
-
# do we have conditions?
|
98
|
-
# if so, add them to the query
|
99
|
-
condition_hash = nil
|
100
|
-
select_arr = nil
|
101
|
-
condition_str = nil
|
102
|
-
limit = nil
|
103
|
-
offset = nil
|
104
|
-
if args[1]
|
105
|
-
if args[1][:conditions]
|
106
|
-
condition_hash = args[1][:conditions] if args[1][:conditions].is_a?(Hash)
|
107
|
-
# conditions are a string
|
108
|
-
condition_str = args[1][:conditions] if args[1][:conditions].is_a?(String)
|
109
|
-
# conditions are an array
|
110
|
-
if args[1][:conditions].is_a? (Array)
|
111
|
-
condition_str = args[1][:conditions][0].split(/\?/).each_with_index { |param,i|
|
112
|
-
param << args[1][:conditions][i+1].to_s
|
113
|
-
}.join(' ').to_s
|
114
|
-
end
|
115
|
-
end
|
116
|
-
if args[1][:per_page] and args[1][:offset]
|
117
|
-
limit = args[1][:per_page].to_s
|
118
|
-
offset = args[1][:offset].to_s
|
119
|
-
end
|
120
|
-
select_arr = args[1][:select] if args[1][:select]
|
121
|
-
end
|
122
|
-
|
123
|
-
start = Time.new
|
124
|
-
# return horizontal resultset from database
|
125
|
-
# for example, an object that has attributes name,industry:
|
126
|
-
# | object | name | industry |
|
127
|
-
# ---------------------------------------------------------------------------
|
128
|
-
# | 3560c0a0-ef58-2f40-68a5-48f39f63741b |A.G. Parr PLC 37862 |Entertainment|
|
129
|
-
attribs = get_attribs
|
130
|
-
if attribs and attribs.length > 0
|
131
|
-
sql = ""
|
132
|
-
sql << "SELECT * FROM (\n" if condition_hash or condition_str
|
133
|
-
sql << "SELECT object,\n"
|
134
|
-
attribs.reject! {|attrib| select_arr.index(attrib).nil?} if select_arr
|
135
|
-
start = Time.new
|
136
|
-
attribs.each do |attrib|
|
137
|
-
unless attrib.nil? or attrib.length == 0 or method_name_reserved?(attrib)
|
138
|
-
sql << "MAX(CASE WHEN attrib = '#{attrib}' AND update_type IN (#{::Rhom::UPDATE_TYPES.join(',')}) THEN value ELSE NULL END) AS \"#{attrib}\",\n"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
sql.chomp!
|
142
|
-
sql.chop!
|
143
|
-
sql << " FROM object_values ov where update_type not in ('delete','update')\n"
|
144
|
-
sql << "AND " + ::Rhom::RhomDbAdapter.where_str(where_cond) + "\n" if where_cond and where_cond.length > 0
|
145
|
-
sql << "group by object\n"
|
146
|
-
sql << "order by \"#{args[1][:order]}\"" if args[1] and args[1][:order]
|
147
|
-
sql << ") WHERE " + ::Rhom::RhomDbAdapter.where_str(condition_hash) if condition_hash
|
148
|
-
sql << ") WHERE " + condition_str if condition_str
|
149
|
-
sql << " LIMIT " + limit + " OFFSET " + offset if limit and offset
|
150
|
-
|
151
|
-
list = ::Rhom::RhomDbAdapter.execute_sql(sql)
|
152
|
-
puts "Database query took #{Time.new - start} sec, #{list.length} rows"
|
153
|
-
start = Time.new
|
154
|
-
list.each do |rowhash|
|
155
|
-
# always return object field with surrounding '{}'
|
156
|
-
rowhash['object'] = "{#{rowhash['object']}}"
|
157
|
-
new_obj = self.new
|
158
|
-
new_obj.vars.merge!(rowhash)
|
159
|
-
ret_list << new_obj
|
160
|
-
end
|
161
|
-
end
|
162
|
-
puts "Processing rhom objects took #{Time.new - start} sec, #{ret_list.length} objects"
|
163
|
-
args.first == :first || args.first.is_a?(String) ? ret_list[0] : ret_list
|
164
|
-
end
|
165
|
-
|
166
|
-
# Alias for find
|
167
|
-
def find_all(args=nil)
|
168
|
-
find(:all, args)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Returns a set of rhom objects, limiting the set to length :per_page
|
172
|
-
# If no :per_page is specified, the default size is 10
|
173
|
-
def paginate(args=nil)
|
174
|
-
# Default to 10 items per page
|
175
|
-
args[:page] ||= 0
|
176
|
-
args[:per_page] ||= 10
|
177
|
-
args[:offset] = args[:page] * args[:per_page]
|
178
|
-
find(:all, args)
|
179
|
-
end
|
180
|
-
|
181
|
-
def set_notification(url,params)
|
182
|
-
SyncEngine.set_notification(get_source_id.to_i,url,params)
|
183
|
-
end
|
184
|
-
|
185
|
-
def clear_notification
|
186
|
-
SyncEngine.clear_notification(get_source_id.to_i)
|
187
|
-
end
|
188
|
-
|
189
|
-
def ask(question)
|
190
|
-
tmp_obj = self.new(:object =>djb_hash("#{question}#{rand.to_s}", 10).to_s)
|
191
|
-
if question
|
192
|
-
# We only support one ask at a time!
|
193
|
-
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>get_source_id, "update_type"=>'ask'})
|
194
|
-
::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>get_source_id, "object"=>tmp_obj.object, "attrib"=>'question', "value"=>Rho::RhoSupport.url_encode(question), "update_type"=>'ask'})
|
195
|
-
SyncEngine.dosync
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
# deletes all records matching conditions (optionally nil)
|
200
|
-
def delete_all(conditions=nil)
|
201
|
-
if conditions
|
202
|
-
del_conditions = get_conditions_hash(conditions[:conditions])
|
203
|
-
# find all relevant objects, then delete them
|
204
|
-
del_objects = ::Rhom::RhomDbAdapter.select_from_table('object_values', 'object', del_conditions.merge!({"source_id"=>get_source_id}), {"distinct"=>true})
|
205
|
-
del_objects.each do |obj|
|
206
|
-
::Rhom::RhomDbAdapter.delete_from_table('object_values', {'object'=>obj['object']})
|
207
|
-
end
|
208
|
-
else
|
209
|
-
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>get_source_id})
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
private
|
214
|
-
|
215
|
-
# returns attributes for the source
|
216
|
-
def get_attribs
|
217
|
-
attribs = ::Rhom::RhomDbAdapter.select_from_table('object_values','attrib', {"source_id"=>get_source_id}, {"distinct"=>true})
|
218
|
-
attribs.collect! do |attrib|
|
219
|
-
attrib['attrib']
|
220
|
-
end
|
221
|
-
attribs
|
222
|
-
end
|
223
|
-
|
224
|
-
# get hash of conditions in sql form
|
225
|
-
def get_conditions_hash(conditions=nil)
|
226
|
-
if conditions
|
227
|
-
condition_hash = {}
|
228
|
-
conditions.each do |key,value|
|
229
|
-
condition_hash.merge!('attrib' => key.to_s, 'value' => value.to_s)
|
230
|
-
end
|
231
|
-
condition_hash
|
232
|
-
else
|
233
|
-
nil
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end #class methods
|
237
|
-
|
238
|
-
# deletes the record from the viewable list as well as
|
239
|
-
# adding a delete record to the list of sync operations
|
240
|
-
def destroy
|
241
|
-
result = nil
|
242
|
-
obj = self.inst_strip_braces(self.object)
|
243
|
-
update_type=self.get_update_type_by_source('delete')
|
244
|
-
if obj
|
245
|
-
# first delete the record from viewable list
|
246
|
-
result = ::Rhom::RhomDbAdapter.delete_from_table('object_values', {"object"=>obj})
|
247
|
-
if update_type
|
248
|
-
# now add delete operation
|
249
|
-
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "update_type"=>update_type})
|
250
|
-
end
|
251
|
-
end
|
252
|
-
result
|
253
|
-
end
|
254
|
-
|
255
|
-
# saves the current object to the database as a create type
|
256
|
-
def save
|
257
|
-
result = nil
|
258
|
-
# iterate over each instance variable and insert create row to table
|
259
|
-
obj = self.inst_strip_braces(self.object)
|
260
|
-
update_type=self.get_update_type_by_source('create')
|
261
|
-
begin
|
262
|
-
::Rhom::RhomDbAdapter.start_transaction
|
263
|
-
|
264
|
-
self.vars.each do |key,value|
|
265
|
-
val = self.inst_strip_braces(value)
|
266
|
-
# add rows excluding object, source_id and update_type
|
267
|
-
unless self.method_name_reserved?(key)
|
268
|
-
fields = {"source_id"=>self.get_inst_source_id,
|
269
|
-
"object"=>obj,
|
270
|
-
"attrib"=>key,
|
271
|
-
"value"=>val,
|
272
|
-
"update_type"=>update_type}
|
273
|
-
fields = key == "image_uri" ? fields.merge!({"attrib_type" => "blob.file"}) : fields
|
274
|
-
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', fields)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
::Rhom::RhomDbAdapter.commit
|
279
|
-
|
280
|
-
rescue Exception => e
|
281
|
-
::Rhom::RhomDbAdapter.rollback
|
282
|
-
end
|
283
|
-
|
284
|
-
result
|
285
|
-
end
|
286
|
-
|
287
|
-
# updates the current record in the viewable list and adds
|
288
|
-
# a sync operation to update
|
289
|
-
def update_attributes(attrs)
|
290
|
-
result = nil
|
291
|
-
obj = self.inst_strip_braces(self.object)
|
292
|
-
update_type=self.get_update_type_by_source('update')
|
293
|
-
attrs.each do |attrib,val|
|
294
|
-
attrib = attrib.to_s.gsub(/@/,"")
|
295
|
-
old_val = self.send attrib.to_sym unless self.method_name_reserved?(attrib)
|
296
|
-
|
297
|
-
# Don't save objects with braces to database
|
298
|
-
new_val = self.inst_strip_braces(val)
|
299
|
-
|
300
|
-
# if the object's value doesn't match the database record
|
301
|
-
# then we procede with update
|
302
|
-
if old_val != new_val
|
303
|
-
unless self.method_name_reserved?(attrib)
|
304
|
-
# only one update at a time
|
305
|
-
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "update_type"=>update_type})
|
306
|
-
# add to syncengine queue
|
307
|
-
::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "value"=>new_val, "update_type"=>update_type})
|
308
|
-
# update viewable ('query') list
|
309
|
-
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "update_type"=>'query'})
|
310
|
-
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "value"=>new_val, "update_type"=>'query'})
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
result
|
315
|
-
end
|
316
|
-
|
317
|
-
def get_inst_source_id
|
318
|
-
Rho::RhoConfig.sources[self.class.name.to_s]['source_id'].to_s
|
319
|
-
end
|
320
|
-
|
321
|
-
def get_update_type_by_source(update_type)
|
322
|
-
source_type = Rho::RhoConfig.sources[self.class.name.to_s]['type']
|
323
|
-
if source_type and source_type == "ask" and update_type == 'delete'
|
324
|
-
nil
|
325
|
-
elsif source_type and source_type == "ask"
|
326
|
-
"query"
|
327
|
-
else
|
328
|
-
update_type
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
def inst_strip_braces(str=nil)
|
333
|
-
str ? str.gsub(/\{/,"").gsub(/\}/,"") : nil
|
334
|
-
end
|
335
|
-
end)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end # RhomObjectFactory
|
1
|
+
#
|
2
|
+
# rhom_object_factory.rb
|
3
|
+
# rhodes
|
4
|
+
# Returns an array of RhomObjects
|
5
|
+
#
|
6
|
+
# Copyright (C) 2008 Rhomobile, Inc. All rights reserved.
|
7
|
+
#
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#
|
21
|
+
require 'rhom'
|
22
|
+
require 'rho'
|
23
|
+
require 'rho/rhosupport'
|
24
|
+
|
25
|
+
module Rhom
|
26
|
+
class RhomObjectFactory
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
unless not defined? Rho::RhoConfig.sources
|
30
|
+
init_objects
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Initialize new object with dynamic attributes
|
35
|
+
def init_objects
|
36
|
+
Rho::RhoConfig.sources.each do |classname,source|
|
37
|
+
unless Object.const_defined?(classname.intern)
|
38
|
+
Object.const_set(classname.intern,
|
39
|
+
Class.new do
|
40
|
+
include ::Rhom::RhomObject
|
41
|
+
extend ::Rhom::RhomObject
|
42
|
+
|
43
|
+
# This holds the attributes for an instance of
|
44
|
+
# the rhom object
|
45
|
+
attr_accessor :vars
|
46
|
+
|
47
|
+
def initialize(obj=nil)
|
48
|
+
@vars = {}
|
49
|
+
self.vars['object'] = "#{((Time.now.to_f - Time.mktime(2009,"jan",1,0,0,0,0).to_f) * 10**6).to_i}"
|
50
|
+
if obj
|
51
|
+
obj.each do |key,value|
|
52
|
+
self.vars[key] = value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(name, *args)
|
58
|
+
unless name == Fixnum
|
59
|
+
varname = name.to_s.gsub(/\=/,"")
|
60
|
+
setting = (name.to_s =~ /=/)
|
61
|
+
if setting
|
62
|
+
@vars[varname] = args[0]
|
63
|
+
else
|
64
|
+
@vars[varname]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
|
71
|
+
def count
|
72
|
+
SyncEngine.lock_sync_mutex
|
73
|
+
res = ::Rhom::RhomDbAdapter.select_from_table('object_values','object', {"source_id"=>get_source_id}, {"distinct"=>true}).length
|
74
|
+
SyncEngine.unlock_sync_mutex
|
75
|
+
res
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_source_id
|
79
|
+
Rho::RhoConfig.sources[self.name.to_s]['source_id'].to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
# retrieve a single record if object id provided, otherwise return
|
83
|
+
# full list corresponding to factory's source id
|
84
|
+
def find(*args)
|
85
|
+
raise ::Rhom::RecordNotFound if args[0].nil? or args.length == 0
|
86
|
+
puts "Inside find: args - #{args.inspect}"
|
87
|
+
ret_list = []
|
88
|
+
conditions = {}
|
89
|
+
where_cond = nil
|
90
|
+
# first find all query objects
|
91
|
+
if args.first == :all || args.first == :first
|
92
|
+
where_cond = {"source_id"=>get_source_id}
|
93
|
+
elsif args.first.is_a?(String)
|
94
|
+
where_cond = {"object"=>strip_braces(args.first.to_s),"source_id"=>get_source_id}
|
95
|
+
end
|
96
|
+
|
97
|
+
# do we have conditions?
|
98
|
+
# if so, add them to the query
|
99
|
+
condition_hash = nil
|
100
|
+
select_arr = nil
|
101
|
+
condition_str = nil
|
102
|
+
limit = nil
|
103
|
+
offset = nil
|
104
|
+
if args[1]
|
105
|
+
if args[1][:conditions]
|
106
|
+
condition_hash = args[1][:conditions] if args[1][:conditions].is_a?(Hash)
|
107
|
+
# conditions are a string
|
108
|
+
condition_str = args[1][:conditions] if args[1][:conditions].is_a?(String)
|
109
|
+
# conditions are an array
|
110
|
+
if args[1][:conditions].is_a? (Array)
|
111
|
+
condition_str = args[1][:conditions][0].split(/\?/).each_with_index { |param,i|
|
112
|
+
param << args[1][:conditions][i+1].to_s
|
113
|
+
}.join(' ').to_s
|
114
|
+
end
|
115
|
+
end
|
116
|
+
if args[1][:per_page] and args[1][:offset]
|
117
|
+
limit = args[1][:per_page].to_s
|
118
|
+
offset = args[1][:offset].to_s
|
119
|
+
end
|
120
|
+
select_arr = args[1][:select] if args[1][:select]
|
121
|
+
end
|
122
|
+
|
123
|
+
start = Time.new
|
124
|
+
# return horizontal resultset from database
|
125
|
+
# for example, an object that has attributes name,industry:
|
126
|
+
# | object | name | industry |
|
127
|
+
# ---------------------------------------------------------------------------
|
128
|
+
# | 3560c0a0-ef58-2f40-68a5-48f39f63741b |A.G. Parr PLC 37862 |Entertainment|
|
129
|
+
attribs = get_attribs
|
130
|
+
if attribs and attribs.length > 0
|
131
|
+
sql = ""
|
132
|
+
sql << "SELECT * FROM (\n" if condition_hash or condition_str
|
133
|
+
sql << "SELECT object,\n"
|
134
|
+
attribs.reject! {|attrib| select_arr.index(attrib).nil?} if select_arr
|
135
|
+
start = Time.new
|
136
|
+
attribs.each do |attrib|
|
137
|
+
unless attrib.nil? or attrib.length == 0 or method_name_reserved?(attrib)
|
138
|
+
sql << "MAX(CASE WHEN attrib = '#{attrib}' AND update_type IN (#{::Rhom::UPDATE_TYPES.join(',')}) THEN value ELSE NULL END) AS \"#{attrib}\",\n"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
sql.chomp!
|
142
|
+
sql.chop!
|
143
|
+
sql << " FROM object_values ov where update_type not in ('delete','update')\n"
|
144
|
+
sql << "AND " + ::Rhom::RhomDbAdapter.where_str(where_cond) + "\n" if where_cond and where_cond.length > 0
|
145
|
+
sql << "group by object\n"
|
146
|
+
sql << "order by \"#{args[1][:order]}\"" if args[1] and args[1][:order]
|
147
|
+
sql << ") WHERE " + ::Rhom::RhomDbAdapter.where_str(condition_hash) if condition_hash
|
148
|
+
sql << ") WHERE " + condition_str if condition_str
|
149
|
+
sql << " LIMIT " + limit + " OFFSET " + offset if limit and offset
|
150
|
+
|
151
|
+
list = ::Rhom::RhomDbAdapter.execute_sql(sql)
|
152
|
+
puts "Database query took #{Time.new - start} sec, #{list.length} rows"
|
153
|
+
start = Time.new
|
154
|
+
list.each do |rowhash|
|
155
|
+
# always return object field with surrounding '{}'
|
156
|
+
rowhash['object'] = "{#{rowhash['object']}}"
|
157
|
+
new_obj = self.new
|
158
|
+
new_obj.vars.merge!(rowhash)
|
159
|
+
ret_list << new_obj
|
160
|
+
end
|
161
|
+
end
|
162
|
+
puts "Processing rhom objects took #{Time.new - start} sec, #{ret_list.length} objects"
|
163
|
+
args.first == :first || args.first.is_a?(String) ? ret_list[0] : ret_list
|
164
|
+
end
|
165
|
+
|
166
|
+
# Alias for find
|
167
|
+
def find_all(args=nil)
|
168
|
+
find(:all, args)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns a set of rhom objects, limiting the set to length :per_page
|
172
|
+
# If no :per_page is specified, the default size is 10
|
173
|
+
def paginate(args=nil)
|
174
|
+
# Default to 10 items per page
|
175
|
+
args[:page] ||= 0
|
176
|
+
args[:per_page] ||= 10
|
177
|
+
args[:offset] = args[:page] * args[:per_page]
|
178
|
+
find(:all, args)
|
179
|
+
end
|
180
|
+
|
181
|
+
def set_notification(url,params)
|
182
|
+
SyncEngine.set_notification(get_source_id.to_i,url,params)
|
183
|
+
end
|
184
|
+
|
185
|
+
def clear_notification
|
186
|
+
SyncEngine.clear_notification(get_source_id.to_i)
|
187
|
+
end
|
188
|
+
|
189
|
+
def ask(question)
|
190
|
+
tmp_obj = self.new(:object =>djb_hash("#{question}#{rand.to_s}", 10).to_s)
|
191
|
+
if question
|
192
|
+
# We only support one ask at a time!
|
193
|
+
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>get_source_id, "update_type"=>'ask'})
|
194
|
+
::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>get_source_id, "object"=>tmp_obj.object, "attrib"=>'question', "value"=>Rho::RhoSupport.url_encode(question), "update_type"=>'ask'})
|
195
|
+
SyncEngine.dosync
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# deletes all records matching conditions (optionally nil)
|
200
|
+
def delete_all(conditions=nil)
|
201
|
+
if conditions
|
202
|
+
del_conditions = get_conditions_hash(conditions[:conditions])
|
203
|
+
# find all relevant objects, then delete them
|
204
|
+
del_objects = ::Rhom::RhomDbAdapter.select_from_table('object_values', 'object', del_conditions.merge!({"source_id"=>get_source_id}), {"distinct"=>true})
|
205
|
+
del_objects.each do |obj|
|
206
|
+
::Rhom::RhomDbAdapter.delete_from_table('object_values', {'object'=>obj['object']})
|
207
|
+
end
|
208
|
+
else
|
209
|
+
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>get_source_id})
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
|
215
|
+
# returns attributes for the source
|
216
|
+
def get_attribs
|
217
|
+
attribs = ::Rhom::RhomDbAdapter.select_from_table('object_values','attrib', {"source_id"=>get_source_id}, {"distinct"=>true})
|
218
|
+
attribs.collect! do |attrib|
|
219
|
+
attrib['attrib']
|
220
|
+
end
|
221
|
+
attribs
|
222
|
+
end
|
223
|
+
|
224
|
+
# get hash of conditions in sql form
|
225
|
+
def get_conditions_hash(conditions=nil)
|
226
|
+
if conditions
|
227
|
+
condition_hash = {}
|
228
|
+
conditions.each do |key,value|
|
229
|
+
condition_hash.merge!('attrib' => key.to_s, 'value' => value.to_s)
|
230
|
+
end
|
231
|
+
condition_hash
|
232
|
+
else
|
233
|
+
nil
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end #class methods
|
237
|
+
|
238
|
+
# deletes the record from the viewable list as well as
|
239
|
+
# adding a delete record to the list of sync operations
|
240
|
+
def destroy
|
241
|
+
result = nil
|
242
|
+
obj = self.inst_strip_braces(self.object)
|
243
|
+
update_type=self.get_update_type_by_source('delete')
|
244
|
+
if obj
|
245
|
+
# first delete the record from viewable list
|
246
|
+
result = ::Rhom::RhomDbAdapter.delete_from_table('object_values', {"object"=>obj})
|
247
|
+
if update_type
|
248
|
+
# now add delete operation
|
249
|
+
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "update_type"=>update_type})
|
250
|
+
end
|
251
|
+
end
|
252
|
+
result
|
253
|
+
end
|
254
|
+
|
255
|
+
# saves the current object to the database as a create type
|
256
|
+
def save
|
257
|
+
result = nil
|
258
|
+
# iterate over each instance variable and insert create row to table
|
259
|
+
obj = self.inst_strip_braces(self.object)
|
260
|
+
update_type=self.get_update_type_by_source('create')
|
261
|
+
begin
|
262
|
+
::Rhom::RhomDbAdapter.start_transaction
|
263
|
+
|
264
|
+
self.vars.each do |key,value|
|
265
|
+
val = self.inst_strip_braces(value)
|
266
|
+
# add rows excluding object, source_id and update_type
|
267
|
+
unless self.method_name_reserved?(key)
|
268
|
+
fields = {"source_id"=>self.get_inst_source_id,
|
269
|
+
"object"=>obj,
|
270
|
+
"attrib"=>key,
|
271
|
+
"value"=>val,
|
272
|
+
"update_type"=>update_type}
|
273
|
+
fields = key == "image_uri" ? fields.merge!({"attrib_type" => "blob.file"}) : fields
|
274
|
+
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', fields)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
::Rhom::RhomDbAdapter.commit
|
279
|
+
|
280
|
+
rescue Exception => e
|
281
|
+
::Rhom::RhomDbAdapter.rollback
|
282
|
+
end
|
283
|
+
|
284
|
+
result
|
285
|
+
end
|
286
|
+
|
287
|
+
# updates the current record in the viewable list and adds
|
288
|
+
# a sync operation to update
|
289
|
+
def update_attributes(attrs)
|
290
|
+
result = nil
|
291
|
+
obj = self.inst_strip_braces(self.object)
|
292
|
+
update_type=self.get_update_type_by_source('update')
|
293
|
+
attrs.each do |attrib,val|
|
294
|
+
attrib = attrib.to_s.gsub(/@/,"")
|
295
|
+
old_val = self.send attrib.to_sym unless self.method_name_reserved?(attrib)
|
296
|
+
|
297
|
+
# Don't save objects with braces to database
|
298
|
+
new_val = self.inst_strip_braces(val)
|
299
|
+
|
300
|
+
# if the object's value doesn't match the database record
|
301
|
+
# then we procede with update
|
302
|
+
if old_val != new_val
|
303
|
+
unless self.method_name_reserved?(attrib)
|
304
|
+
# only one update at a time
|
305
|
+
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "update_type"=>update_type})
|
306
|
+
# add to syncengine queue
|
307
|
+
::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "value"=>new_val, "update_type"=>update_type})
|
308
|
+
# update viewable ('query') list
|
309
|
+
::Rhom::RhomDbAdapter.delete_from_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "update_type"=>'query'})
|
310
|
+
result = ::Rhom::RhomDbAdapter.insert_into_table('object_values', {"source_id"=>self.get_inst_source_id, "object"=>obj, "attrib"=>attrib, "value"=>new_val, "update_type"=>'query'})
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
result
|
315
|
+
end
|
316
|
+
|
317
|
+
def get_inst_source_id
|
318
|
+
Rho::RhoConfig.sources[self.class.name.to_s]['source_id'].to_s
|
319
|
+
end
|
320
|
+
|
321
|
+
def get_update_type_by_source(update_type)
|
322
|
+
source_type = Rho::RhoConfig.sources[self.class.name.to_s]['type']
|
323
|
+
if source_type and source_type == "ask" and update_type == 'delete'
|
324
|
+
nil
|
325
|
+
elsif source_type and source_type == "ask"
|
326
|
+
"query"
|
327
|
+
else
|
328
|
+
update_type
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def inst_strip_braces(str=nil)
|
333
|
+
str ? str.gsub(/\{/,"").gsub(/\}/,"") : nil
|
334
|
+
end
|
335
|
+
end)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end # RhomObjectFactory
|
340
340
|
end # Rhom
|