Rubernate 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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