Rubernate 0.1.5 → 0.1.6

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.
@@ -48,7 +48,13 @@ module Queries
48
48
  end
49
49
  end
50
50
 
51
- # Factory method, creates queries based on Generic factory.
51
+ # Factory method, creates queries using stardart factory.
52
+ #
53
+ # :call-seq:
54
+ #
55
+ # q = Rubernate::Queries.query "Select :o; Where o.prop.str == :value"
56
+ # puts q.to_sql
57
+ #
52
58
  def self.query q_text=nil, &q_block
53
59
  if block_given?
54
60
  @@generic_factory.query(&q_block)
@@ -68,7 +74,7 @@ module Queries
68
74
  #
69
75
  # New implementations of elements MUST accept factory as it's first parameter.
70
76
  class Factory
71
- attr_reader :cache # Queries cache. TODO: limit size!
77
+ attr_reader :cache # Queries cache. TODO: limit cache size!
72
78
  # Initalizes default implementations
73
79
  def initialize
74
80
  @expr = Expr
@@ -102,7 +108,6 @@ module Queries
102
108
  end
103
109
  end
104
110
 
105
- # Contains classes for standart ANSY SQL.
106
111
  # Represent abstract expression
107
112
  class Expr
108
113
  include Operations
@@ -145,7 +150,7 @@ module Queries
145
150
  end
146
151
  end
147
152
 
148
- # Represents constraint for one columns.
153
+ # Represents constraint for one column.
149
154
  class UnOpConstr < Expr
150
155
  def initialize factory, expr, op, braces = false
151
156
  @factory, @op, @braces = factory, op, braces
@@ -169,7 +174,7 @@ module Queries
169
174
  end
170
175
  end
171
176
 
172
- # Represent constraint that applied on two columns.
177
+ # Represent constraint applied on two columns.
173
178
  class BinOpConstr < Expr
174
179
  def initialize factory, expr1, expr2, sign, braces = false
175
180
  @factory, @sign, @braces = factory, sign, braces
@@ -196,7 +201,8 @@ module Queries
196
201
  end
197
202
  end
198
203
 
199
- # Represent expression with table's field
204
+ # Represent expression with tabls field such as
205
+ # <tt>r_params.name</tt> or <tt>r_objects.object_class</tt>
200
206
  class FieldExpr < Expr
201
207
  def initialize factory, table, field
202
208
  @factory, @table, @field, @markers = factory, table, field, []
@@ -216,7 +222,7 @@ module Queries
216
222
  end
217
223
  end
218
224
 
219
- # Represent r_params for hashes and arrays constrained by key
225
+ # Represents r_params for hashes and arrays constrained by key
220
226
  class KeyRefExpr < BinOpConstr
221
227
  def initialize factory, r_param, key_field, key_value
222
228
  @factory, @r_param, @key_field, @key_value = factory, r_param, key_field, key_value
@@ -227,7 +233,7 @@ module Queries
227
233
  end
228
234
  end
229
235
 
230
- # Reresents List of expressions
236
+ # Reresents collection of expressions
231
237
  class ExprsList < Expr
232
238
  def initialize factory, list
233
239
  @factory, @exprs = factory, list.collect{|expr| Expr === expr ? expr : factory.expr(expr)}
@@ -243,7 +249,7 @@ module Queries
243
249
  end
244
250
  end
245
251
 
246
- # Represents r_params table
252
+ # Represents <tt>r_params</tt> table
247
253
  class RParam < Expr
248
254
  include Rubernate::DBI
249
255
 
@@ -260,15 +266,31 @@ module Queries
260
266
  @r_object.to_sql + @p_name
261
267
  end
262
268
 
263
- # Fields accessors.
269
+ # Creates accessor to +r_params.primary_key+.
264
270
  def pk () f_expr 'object_pk'; end
271
+
272
+ # Creates accessor to +r_params.int_value+.
265
273
  def int () f_expr 'int_value'; end
274
+
275
+ # Creates accessor to +r_parms.flt_value+.
266
276
  def float() f_expr 'flt_value'; end
277
+
278
+ # Creates accessor to +r_parms.str_value+.
267
279
  def str () f_expr 'str_value'; end
280
+
281
+ # Creates accessor to +r_parms.dat_value+ with appropriate converison to time if needed.
268
282
  def time () f_expr 'dat_value'; end
283
+
284
+ # Creates accessor to +r_parms.dat_value+ with appropriate converison if needed.
269
285
  def date () f_expr 'dat_value'; end
286
+
287
+ # Creates accessor to +r_parms.ref_value+.
270
288
  def ref () f_expr 'ref_value'; end
289
+
290
+ # Creates accessor to +r_parms.flags+.
271
291
  def flags() f_expr 'flags'; end
292
+
293
+ # Creates accessor to +r_parms.name+.
272
294
  def name () f_expr 'name'; end
273
295
 
274
296
  # The following methods checks r_param.flags value. (r_param.flags)
@@ -304,7 +326,7 @@ module Queries
304
326
  end
305
327
  end
306
328
 
307
- # Represent r_objects table
329
+ # Represent <tt>r_objects</tt> table
308
330
  class RObject < Expr
309
331
  # Init Table accepts query and name of table
310
332
  def initialize factory, name
@@ -1,4 +1,6 @@
1
- module Rubernate
1
+ require 'rubernate/lazyload'
2
+
3
+ module Rubernate
2
4
  # Base class for all Runtime implementations.
3
5
  class Runtime
4
6
  include Callbacks::Runtime
@@ -6,13 +8,18 @@ module Rubernate
6
8
  # Log for Runtime events
7
9
  Log = Rubernate::Log
8
10
 
11
+ # Runtime scope settings
12
+ attr_reader :settings
13
+
9
14
  def initialize
10
15
  @pool = {} # Contains objects loaded during the session
11
- @factory = Queries::Factory.new
12
- end
16
+ @@factory = Queries::Factory.new unless @@factory
17
+ @factory = @@factory
18
+ @settings = Hash.new {|hash, key| hash[key] = Rubernate.settings[key]}
19
+ end
20
+ @@factory = nil
13
21
 
14
- # Finds object by primary key,
15
- # raises ObjectNotFoundException if object is not found
22
+ # Finds object by primary key. Raises ObjectNotFoundException if object is not found
16
23
  def find_by_pk pk, load = false
17
24
  result = @pool[pk]
18
25
  unless result
@@ -28,13 +35,14 @@ module Rubernate
28
35
  result
29
36
  end
30
37
 
31
- # Finds objects by query. Returns ordered list of objects.
32
- # If +params+ if Array the query will be treated as native sql
33
- # and won't be processed.
38
+ # Finds objects by query. Returns ordered list of objects or empty one if no objects was found.
39
+ # The query can be one of two types.
40
+ # * native sql - in this case +params+ should be of type Array.
41
+ # * query language - +params+ shoud be of type Hash.
34
42
  def find_by_query query, params={} #TODO: improve working with paramters
35
43
  flush_modified
36
44
  params = case params
37
- when Hash: params
45
+ when Hash : params
38
46
  when Array: params
39
47
  else [params]
40
48
  end
@@ -54,7 +62,7 @@ module Rubernate
54
62
  # primary key already loaded in session.
55
63
  def attach object
56
64
  raise "Can't attach object: #{object.primary_key}" if @pool.has_key? object.primary_key
57
- object.peer = Peer.new unless object.peer
65
+ object.__peer = Peer.new unless object.__peer
58
66
  create object
59
67
  @pool[object.primary_key] = object
60
68
  Log.debug {"Attach #{object.class.name}: #{object.primary_key} to session"}
@@ -75,13 +83,13 @@ module Rubernate
75
83
  raise
76
84
  end
77
85
 
78
- # Begins session
86
+ # Begins session and transaction.
79
87
  def begin
80
88
  Log.debug {"Begin session #{self}"}
81
89
  on_begin
82
90
  end
83
91
 
84
- # Persist all changes and Commit transction.
92
+ # Persist all changes and commit transction.
85
93
  def commit
86
94
  before_commit # callback
87
95
  flush_modified
@@ -93,7 +101,7 @@ module Rubernate
93
101
  raise
94
102
  end
95
103
 
96
- # Discard all changes and Rollback transaction.
104
+ # Discard all changes and rollback transaction.
97
105
  def rollback ex='not specified'
98
106
  on_rollback # callback
99
107
  Log.warn {"Rollback session #{self} due to error: #{ex}"}
@@ -103,7 +111,10 @@ module Rubernate
103
111
  raise
104
112
  end
105
113
 
106
- # Flushes modified objects. Invokes on_store callback before storing.
114
+ # Stores modified objects to database. This method is invoked before
115
+ # transaction commit and before each invokation of Runtime.find_by_query.
116
+ # You can invoke this method manually if you want to store all changes of your
117
+ # objects to database immediately.
107
118
  def flush_modified
108
119
  objects = modified
109
120
  before_flush modified # callback
@@ -116,8 +127,9 @@ module Rubernate
116
127
 
117
128
  private
118
129
  # Creates new object instance or returns insance from pool
119
- # Parameter klass can be Class or String (class name)
120
- def instantiate pk, klass, peer = nil
130
+ # * klass - can be Class or String (class name)
131
+ # * peer - can be Peer, LazyLoader or nill
132
+ def instantiate pk, klass, peer = nil
121
133
  object = @pool[pk]
122
134
  unless object
123
135
  clazz = klass.is_a?(Class) ? klass : get_class(klass)
@@ -125,10 +137,10 @@ module Rubernate
125
137
  object.primary_key = pk
126
138
  @pool[pk] = object
127
139
  end
128
- object.peer = peer # TODO: TEST!!! and write description
140
+ object.__peer = peer if peer
129
141
  object
130
- end
131
-
142
+ end
143
+
132
144
  #Classes cache.
133
145
  @@classes = {}
134
146
 
@@ -141,17 +153,27 @@ module Rubernate
141
153
  @@classes[name] = klass
142
154
  end
143
155
 
156
+ # Returns LazyLoaderFactory instance.
157
+ def lazy_factory
158
+ case settings[:lazy_load]
159
+ when :holder: HolderLazyLoaderFactory.new
160
+ when :collection: ParamLazyLoaderFactory.new
161
+ when :separately, nil: LazyLoaderFactory.new
162
+ else "wrong value for setting :lazy_load - #{settings[:lazy_load]}"
163
+ end
164
+ end
165
+
144
166
  # Returns modified objects.
145
167
  def modified
146
- @pool.values.find_all {|object| object.peer and object.dirty?}
168
+ @pool.values.find_all {|object| object.__peer and object.dirty?}
147
169
  end
148
170
 
149
- # Callback functions invoked when session successfully closed
171
+ # Callback functions it's invoked when session successfully closed
150
172
  # Should be overriden by subclasses to perform implement closing logic
151
173
  def close
152
174
  end
153
175
 
154
- # Callback functions invoked when session fails
176
+ # Callback functions it's invoked when session fails.
155
177
  # Should be overriden by subclasses to cleanup resources
156
178
  def failed
157
179
  end
@@ -203,10 +225,10 @@ module Rubernate
203
225
  end
204
226
 
205
227
  def post_load object
206
- for value in object.peer.values
228
+ for value in object.__peer.values
207
229
  value.compact! if value.is_a? Array
208
230
  end
209
- object.peer.dirty = false
231
+ object.__peer.dirty = false
210
232
  object.on_load
211
233
  end
212
234
 
@@ -221,10 +243,10 @@ module Rubernate
221
243
  when Class: p.name
222
244
  else p
223
245
  end
224
- end
246
+ end
225
247
  end
226
-
227
- # Represetns Dummy Persistent. - objects whose class wasn't found during loading.
248
+
249
+ # Represetns object whose class wasn't found during loading.
228
250
  class DummyPersistent
229
251
  persistent
230
252
  def initialize class_name
data/lib/rubernate.rb CHANGED
@@ -41,8 +41,8 @@ module Rubernate
41
41
  # Rubernate core singelton methods.
42
42
  class << self
43
43
  # Allows you setup Rubernate by yours implementaion of Configuration.
44
- # See also method config
45
- def configuration= config
44
+ # See also method config
45
+ def configuration= config # :nodoc:
46
46
  Log.info "Rubernate configured by #{config}"
47
47
  @factory = config
48
48
  end
@@ -63,37 +63,14 @@ module Rubernate
63
63
  self.configuration = DBI::Configuration.new impl, init, url, user, password
64
64
  end
65
65
 
66
- # Loads MySQL module
67
- def require_mysql
68
- require 'rubernate/impl/dbi_mysql'
69
- require 'rubernate/init/init_mysql'
70
- [DBI::MySqlRuntime, DBI::MySqlInit.new]
71
- end
72
-
73
- # Loads Oracle module
74
- def require_oracle
75
- require 'rubernate/impl/dbi_oracle'
76
- require 'rubernate/init/init_oracle'
77
- [DBI::OracleRuntime, DBI::OracleInit.new]
78
- end
79
-
80
- # Loads Postgres module
81
- def require_pg
82
- require 'rubernate/impl/dbi_pg'
83
- require 'rubernate/init/init_pg'
84
- [DBI::PgRuntime, DBI::PgInit.new]
85
- end
86
-
87
- # Loads Memory module used only for testing
88
- def require_memory
89
- require 'rubernate/impl/memory'
90
- Memory::Runtime
91
- end
92
66
 
93
67
  # Intializes database - creates necessary tables, sequences and indices.
94
68
  def init_db
95
69
  @factory.init_db
96
70
  end
71
+
72
+ # Global scope settings
73
+ attr_reader :settings
97
74
 
98
75
  # Returns Runtime object associated with current session
99
76
  # or nil if session does not excists
@@ -108,8 +85,9 @@ module Rubernate
108
85
  Thread.current[:Rubernate] != nil
109
86
  end
110
87
 
111
- # Begins new Rubernate session
88
+ # Begins new session and transaction in database. Returns Runtime object or supply it to block if one is given.
112
89
  def session
90
+ raise 'No config found. Call Rubernate.config first.' unless @factory
113
91
  runtime = @factory.create
114
92
  Thread.current[:Rubernate] = runtime
115
93
  runtime.begin
@@ -125,19 +103,59 @@ module Rubernate
125
103
  end
126
104
  result
127
105
  end
128
- end
106
+ private
107
+ # Loads MySQL module
108
+ def require_mysql # :nodoc:
109
+ require 'rubernate/impl/dbi_mysql'
110
+ require 'rubernate/init/init_mysql'
111
+ [DBI::MySqlRuntime, DBI::MySqlInit.new]
112
+ end
129
113
 
130
- # Shortcut method can be used instead of Rubernate.runtime.find_by_pk
114
+ # Loads Oracle module
115
+ def require_oracle # :nodoc:
116
+ require 'rubernate/impl/dbi_oracle'
117
+ require 'rubernate/init/init_oracle'
118
+ [DBI::OracleRuntime, DBI::OracleInit.new]
119
+ end
120
+
121
+ # Loads Postgres module
122
+ def require_pg # :nodoc:
123
+ require 'rubernate/impl/dbi_pg'
124
+ require 'rubernate/init/init_pg'
125
+ [DBI::PgRuntime, DBI::PgInit.new]
126
+ end
127
+
128
+ # Loads Memory module used only for testing :nodoc:
129
+ def require_memory # :nodoc:
130
+ require 'rubernate/impl/memory'
131
+ Memory::Runtime
132
+ end
133
+ end
134
+ @settings = {}
135
+
136
+ # Finds object by primary key. This method is actually shortcut to Runtime.find_by_pk
131
137
  def find_by_pk pk
132
138
  Rubernate.runtime.find_by_pk pk
133
139
  end
134
140
 
135
- # Shortcut method can be used instead of Rubernate.runtime.find_by_query
141
+ # Finds object by query. This method is actually shortcut to Runtime.find_by_query
142
+ # Retruns array of objects, accepts native sql or query language expressions.
143
+ # If query is sql then +params+ should be array as in DBI. Else it should be Hash of <tt>{:maker=>value}</tt>.
144
+ #
145
+ # :call-seq: find_by_query(query, params={})
146
+ #
147
+ # Rubernate.find_by_query 'Select :p; Where p.name.str == :name', :name => 'Andy'
148
+ #
149
+ # #Or the same using native sql.
150
+ # Rubernate.find_by_query "select p_.* from r_objects p_ left outer join r_params p_name
151
+ # on (p_.object_pk = p_name.object_pk)
152
+ # where p_name.name = 'name' and p_name.str_value = ?", ['Andy']
153
+ #
136
154
  def find_by_query query, params={}
137
155
  Rubernate.runtime.find_by_query query, params
138
156
  end
139
157
 
140
- # Shortcut method can be used instead of Rubernate.runtime
158
+ # Returns current runtime object.
141
159
  def runtime
142
160
  Rubernate.runtime
143
161
  end
data/tests/config.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  # Set to true to run tests on Oracle
2
2
  $run_oracle_tests = false
3
3
 
4
- ORA_RUNTIME_CLASS = Rubernate.require_oracle[0]
5
- ORA_DB_URL = 'dbi:OCI8:dbg91'
4
+ module Rubernate
5
+
6
+ ORA_RUNTIME_CLASS = require_oracle[0]
7
+ ORA_DB_URL = 'dbi:OCI8:nc65db'
6
8
  ORA_DB_USER = 'netcracker65'
7
9
  ORA_DB_PWD = 'netcracker65'
8
10
 
9
11
  # Set to true to run tests on MySQL
10
12
  $run_mysql_tests = false
11
13
 
12
- MYSQL_RUNTIME_CLASS = Rubernate.require_mysql[0]
14
+ MYSQL_RUNTIME_CLASS = require_mysql[0]
13
15
  MYSQL_DB_URL = 'dbi:Mysql:rubernate_db:localhost'
14
16
  MYSQL_DB_USER = nil
15
17
  MYSQL_DB_PWD = nil
@@ -17,12 +19,13 @@ MYSQL_DB_PWD = nil
17
19
  # Set to true to run tests on PostgreSQL
18
20
  $run_pg_tests = false
19
21
 
20
- PG_RUNTIME_CLASS = Rubernate.require_pg[0]
22
+ PG_RUNTIME_CLASS = require_pg[0]
21
23
  PG_DB_URL = 'dbi:Pg:rubernate_db'
22
24
  PG_DB_USER = 'rn_test'
23
25
  PG_DB_PWD = 'rn_password'
24
26
 
25
- Rubernate.require_memory
27
+ require_memory
28
+ end
26
29
 
27
30
  # Log4r configuration
28
31
  Rubernate::Log.level = Log4r::DEBUG