intersys 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,10 +11,15 @@ module Intersys
11
11
  extend DL::Importable
12
12
  begin
13
13
  dlload("libcbind.dylib")
14
- rescue
14
+ rescue StandardError => e
15
+ puts e
15
16
  end
16
17
 
17
18
  require File.dirname(__FILE__) + '/intersys_cache'
19
+ require 'object'
20
+ require 'callable'
21
+ require 'reflection'
22
+
18
23
 
19
24
  class Method
20
25
  def description
@@ -30,264 +35,51 @@ module Intersys
30
35
  end
31
36
  end
32
37
 
33
- module Callable
34
- # Returns ClassDefinition object for current class
35
- def intersys_reflector
36
- @reflector ||= Intersys::Reflection::ClassDefinition.open(class_name)
37
- end
38
-
39
- # returns list of methods for this class
40
- def intersys_methods
41
- @methods ||= intersys_reflector._methods
42
- end
43
-
44
- # returns list of properties for current class
45
- def intersys_properties
46
- @properties ||= intersys_reflector.properties
47
- end
48
-
49
- #protected
50
- # Loads property definition with required name for required object
51
- # for internal use only
52
- def intersys_property(name)
53
- Property.new(database, class_name, name.to_s, self)
54
- end
55
-
56
- # Loads method definition with required name for required object
57
- # for internal use only
58
- def intersys_method(name)
59
- Method.new(database, class_name, name.to_s, self)
60
- end
61
-
62
- public
63
- # call class method
64
- def intersys_call(method_name, *args)
65
- intersys_method(method_name).call!(args)
66
- end
67
- alias :call :intersys_call
68
-
69
- def intersys_has_property?(property)
70
- self.intersys_reflector.properties.to_a.include?(property)
71
- end
72
-
73
- def intersys_has_method?(method)
74
- self.intersys_reflector._methods.to_a.include?(method)
75
- end
76
-
77
- # Get the specified property
78
- def intersys_get(property)
79
- intersys_property(property).get
80
- end
81
-
82
- # Set the specified property
83
- def intersys_set(property, value)
84
- intersys_property(property).set(value)
85
- end
86
-
87
- def method_missing(method, *args)
88
- method_name = method.to_s.camelize
89
- if match_data = method_name.match(/intersys_(.*)/)
90
- # Protection from errors in this method
91
- return super(method, *args)
92
- end
93
- if match_data = method_name.match(/(\w+)=/)
94
- return intersys_set(match_data.captures.first, args.first)
95
- end
96
- return intersys_get(method_name) if intersys_has_property?(method_name) && args.empty?
97
- begin
98
- return intersys_call(method_name, *args)
99
- rescue NoMethodError => e
100
- end
101
- begin
102
- return intersys_call("%"+method_name, *args)
103
- rescue NoMethodError => e
104
- end
105
- super(method, *args)
38
+
39
+ module ActiveRecordEmulation
40
+ def append_features(base)
41
+ base.extend ClassMethods
106
42
  end
107
43
 
108
- end
109
-
110
- # Basic class for all classes, through which is performed access to Cache classes
111
- # For each Cache class must be created ruby class, inherited from Intersys::Object
112
- #
113
- # By default prefix "User" is selected. If Cache class has another prefix, it must
114
- # be provided explicitly via method "prefix":
115
- # class List < Intersys::Object
116
- # prefix "%Library"
117
- # end
118
- #
119
- # By default name of Cache class is taken the same as name of ruby class.
120
- # Thus in this example this class List will be marshalled to Cache class
121
- # %Library.List
122
- #
123
- class Object
124
-
125
- class << self
126
- protected
127
- def class_names
128
- common_get_or_set("@class_names", {})
129
- end
130
-
131
- def prefix=(name)
132
- @prefix = name
133
- @class_name = @prefix + "." + (@class_name ? @class_name.split(".").last : self.to_s)
134
- register_name!
135
- end
136
-
137
- def class_name=(name)
138
- if name.index(".")
139
- self.prefix = name.split(".").first
140
- @class_name = name
44
+ module ClassMethods
45
+ def create(attributes = nil)
46
+ if attributes.is_a?(Array)
47
+ attributes.collect { |attr| create(attr) }
141
48
  else
142
- @class_name = self.prefix + "." + name
143
- end
144
- register_name!
145
- end
146
-
147
- # Register class name of current class in global list
148
- def register_name!
149
- if i = class_names.index(self)
150
- class_names.delete(i)
49
+ object = intersys_call("%New")
50
+ attributes.each { |att,value| object.send("#{att}=", value) }
51
+ object.save
52
+ object
151
53
  end
152
- class_names[class_name] = self
153
- class_name
154
54
  end
155
55
 
156
- public
157
- # Nice function, that generates description of Cache class, looking just as C++ one
158
- # Maybe, later, it will be possible even to generate IDL, using this code
159
- def intersys_description
160
- "class #{class_name} { \n" + intersys_reflector.all_methods.map do |mtd|
161
- begin
162
- "\t"+intersys_method(mtd).description+";\n"
163
- rescue
164
- "\tundefined #{mtd}\n"
165
- end
166
- end.join("") + "};"
167
- end
168
-
169
- # Help to work with instance variables of Intersys::Object class
170
- # required, because list of registered descendants of Intersys::Object,
171
- # database connection etc. should be in one place
172
- def common_get_or_set(name, default_value = nil)
173
- unless var = Intersys::Object.instance_variable_get(name)
174
- default = block_given? ? yield : default_value
175
- var = Intersys::Object.instance_variable_set(name, default)
176
- end
177
- var
178
- end
179
-
180
- # Takes Cache class name and try to resolve it to Ruby class
181
- def lookup(class_name)
182
- class_names[class_name] || raise(UnMarshallError, "Couldn't find registered class with Cache name '#{class_name}'")
183
- end
184
-
185
- # Each Cache class has prefix before it's name: namespace.
186
- # this method set's prefix for current class is provided,
187
- # or just returns current prefix
188
- def prefix(name = nil)
189
- self.prefix = name if name
190
- @prefix ||= "User"
56
+ def exists?(id)
57
+ exists_id(id)
191
58
  end
192
-
193
- # Returns Cache class name, if called without parameters, or sets one, if passed
194
- def class_name(name = nil)
195
- self.class_name = name if name
196
- self.class_name = (prefix + "." + to_s) unless @class_name
197
- @class_name
198
- end
199
-
200
- # Returns database, if called without parameters, or sets one, if passed
201
- # Once established, it is not possible now to connect to another database
202
- def database(db_options = {})
203
- common_get_or_set("@database") do
204
- Intersys::Database.new({:user => "_SYSTEM", :password => "SYS", :namespace => "User"}.merge(db_options))
205
- end
59
+
60
+ def find_by_sql(sql)
61
+ warn "Nop, no find_by_sql in Object interface"
62
+ nil
206
63
  end
207
-
208
- # This method takes block and executes it between
209
- # START TRANSACTION and COMMIT TRANSACTION
210
- #
211
- # In case of exception ROLLBACK TRANSACTION is called
212
- def transaction
213
- return unless block_given?
214
- database.start
215
- begin
216
- yield
217
- database.commit
218
- rescue StandardError => e
219
- database.rollback
220
- raise e
64
+
65
+ def find(*args)
66
+ if args.size == 1
67
+ return open(args.first)
221
68
  end
69
+ warn "No idea, how to implement method find"
70
+ nil
222
71
  end
223
-
224
- # :nodoc
225
- def inherited(klass)
226
- class_names[klass.class_name] = klass
227
- end
228
-
229
- # Look into Cache documentation for what is concurrency. I don't know
230
- def concurrency
231
- 1
232
- end
233
-
234
- # timeout for connection
235
- def timeout
236
- 5
237
- end
238
-
239
- # Nice method, that deletes all instances of class.
240
- # You can just Person.delete_extent, but Person.delete_all looks more like ActiveRecord
241
- def delete_all
242
- intersys_call("%DeleteExtent")
243
- end
244
-
245
- end
246
-
247
- # You can ask for database from instance
248
- def database
249
- self.class.database
250
- end
251
-
252
- # You can ask from instance it's Cache class name
253
- def class_name
254
- self.class.class_name
255
- end
256
-
257
- # Returns id of current object.
258
- # You can remove this method and You will get string ID, so leave it here
259
- # However, if You ask reflector for id, it will give incorrect answer,
260
- # because Cache allows id to be string
261
- def id
262
- intersys_call("%Id").to_i
263
- end
264
-
265
- # Destroys current object
266
- def destroy
267
- self.class.intersys_call("%DeleteId", id)
72
+
73
+
268
74
  end
269
-
270
- include Callable
271
75
  end
272
- Intersys::Object.extend(Callable)
76
+
273
77
 
274
78
  # Class representing one query
275
79
  # You shouldn't create it yourself
276
80
  class Query
277
81
  attr_reader :database
278
82
 
279
- def initialize(database, query)
280
- @database = database
281
- native_initialize(database, query.to_wchar)
282
- end
283
-
284
- def each
285
- while (row = self.fetch) && row.size > 0
286
- #puts "Loaded row #{row}"
287
- yield row
288
- end
289
- end
290
-
291
83
  def to_a
292
84
  data = []
293
85
  self.each {|row| data << row}
@@ -302,131 +94,48 @@ module Intersys
302
94
 
303
95
  # Class representing Cache database connection
304
96
  class Database
97
+ protected
98
+ def strip_param(query, name)
99
+ if match_data = query.match(/#{name}(\s*)(\d+)/i)
100
+ query[match_data.to_s] = ""
101
+ match_data.captures.last
102
+ end
103
+ end
104
+
105
+ public
305
106
  def create_query(query)
306
- Query.new(self, query)
107
+ @limit = strip_param(query, "LIMIT")
108
+ @offset = strip_param(query, "OFFSET")
109
+ q = Query.new(self, query)
110
+ q.limit = @limit if @limit
111
+ q.offset = @offset if @offset
112
+ q
307
113
  end
308
114
 
309
115
  # This method creates SQL query, runs it, restores data
310
116
  # and closes query
311
- def query(query)
117
+ def query(query, params = [])
312
118
  data = []
313
- q = create_query(query).execute.fill(data).close
119
+ q = create_query(query).bind_params(params).execute.fill(data).close
314
120
  #1.upto(data.first.size) do |i|
315
121
  # puts q.column_name(i)
316
122
  #end
317
123
  data
318
124
  end
319
- end
320
-
321
- # Module reflection keeps classes required to get information
322
- # about methods and properties of Cache classes
323
- module Reflection
324
125
 
325
- # This class is basic reflection class
326
- # If has class method Open(class_name), that creates instance of
327
- # this class, representing its internals
328
- #
329
- # Usually creates via Intersys::Object.reflector
330
- #
331
- # Then it is possible to call such methods as _methods, properties
332
- # to get access to methods and properties of Cache class
333
- class ClassDefinition < Intersys::Object
334
- class_name "%Dictionary.ClassDefinition"
335
-
336
- # After all changes to class definition required to call save
337
- def save
338
- intersys_call("%Save")
339
- end
340
-
341
- # short alias to intersys_get("Methods")
342
- def _methods
343
- @methods ||= intersys_get("Methods")
344
- end
345
-
346
- def properties
347
- @properties ||= intersys_get("Properties")
348
- end
349
-
350
- def all_methods
351
- _methods.to_a + self.super.split(",").map do |klass|
352
- klass = klass.strip
353
- if match_data = klass.match(/^%([^\.]+)$/)
354
- klass = "%Library.#{match_data.captures.first}"
355
- end
356
- self.class.open(klass).all_methods
357
- end.flatten
358
- end
359
- end
360
-
361
- class PropertyDefinition < Intersys::Object
362
- class_name "%Dictionary.PropertyDefinition"
126
+ def execute(query, params = [])
127
+ create_query(query).bind_params(params).execute.close
363
128
  end
364
129
 
365
- class MethodDefinition < Intersys::Object
366
- class_name "%Dictionary.MethodDefinition"
130
+ # TODO: /csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_variables
131
+ # Somehow, I should extract from Cache %ROWCOUNT and %ROWID
132
+ def affected_rows
133
+ query("select %ROWCOUNT")
367
134
  end
368
135
 
369
- # This is a proxy object to Cache RelationshipObject, which is just like Rails Association object
370
- #
371
- class RelationshipObject < Intersys::Object
372
- class_name "%Library.RelationshipObject"
373
-
374
- def empty?
375
- @empty ||= intersys_call("IsEmpty")
376
- end
377
-
378
- def count
379
- @count ||= intersys_call("Count")
380
- end
381
- alias :size :count
382
-
383
- def [](index)
384
- return @list[index] if @loaded
385
- intersys_call("GetAt", index.to_s)
386
- end
387
-
388
- def each
389
- 1.upto(count) do |i|
390
- yield self[i]
391
- end
392
- end
393
-
394
- include Enumerable
395
-
396
- def to_a
397
- load_list
398
- end
399
-
400
- def include?(obj)
401
- load_list.include?(obj)
402
- end
403
-
404
- def inspect
405
- load_list.inspect
406
- end
407
- alias :to_s :inspect
408
-
409
- def <<(object)
410
- intersys_call("Insert", object)
411
- end
412
- alias :insert :<<
413
-
414
- def reload
415
- @list = nil
416
- @loaded = nil
417
- @empty = nil
418
- @count = nil
419
- end
420
-
421
- protected
422
- def load_list
423
- @list ||= []
424
- self.each do |prop|
425
- @list << prop.intersys_get("Name")
426
- end unless @loaded
427
- @loaded = true
428
- @list
429
- end
136
+ def insert_id
137
+ 0
430
138
  end
431
139
  end
140
+
432
141
  end