intersys 0.1 → 0.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.
@@ -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