og 0.27.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/ProjectInfo +2 -2
  2. data/README +8 -4
  3. data/Rakefile +1 -1
  4. data/doc/AUTHORS +1 -1
  5. data/doc/RELEASES +81 -0
  6. data/examples/README +7 -0
  7. data/lib/glue/cacheable.rb +152 -0
  8. data/lib/glue/hierarchical.rb +5 -4
  9. data/lib/glue/optimistic_locking.rb +0 -1
  10. data/lib/glue/orderable.rb +46 -44
  11. data/lib/glue/taggable.rb +7 -4
  12. data/lib/glue/timestamped.rb +1 -1
  13. data/lib/og.rb +13 -6
  14. data/lib/og/entity.rb +226 -9
  15. data/lib/og/evolution.rb +2 -2
  16. data/lib/og/ez/clause.rb +147 -0
  17. data/lib/og/ez/condition.rb +181 -0
  18. data/lib/og/manager.rb +31 -30
  19. data/lib/og/relation.rb +5 -5
  20. data/lib/og/relation/has_many.rb +3 -1
  21. data/lib/og/relation/joins_many.rb +1 -1
  22. data/lib/og/store.rb +6 -3
  23. data/lib/og/store/kirby.rb +3 -5
  24. data/lib/og/store/mysql.rb +0 -1
  25. data/lib/og/store/sql.rb +43 -7
  26. data/lib/og/store/sqlite.rb +97 -11
  27. data/lib/og/store/sqlite2.rb +231 -0
  28. data/lib/og/test/testcase.rb +1 -1
  29. data/lib/og/vendor/mysql.rb +103 -25
  30. data/test/glue/tc_revisable.rb +11 -11
  31. data/test/og/CONFIG.rb +20 -8
  32. data/test/og/mixin/tc_hierarchical.rb +5 -3
  33. data/test/og/mixin/tc_optimistic_locking.rb +6 -4
  34. data/test/og/mixin/tc_orderable.rb +22 -22
  35. data/test/og/mixin/tc_taggable.rb +15 -11
  36. data/test/og/mixin/tc_timestamped.rb +4 -2
  37. data/test/og/multi_validations_model.rb +8 -0
  38. data/test/og/store/tc_filesys.rb +15 -12
  39. data/test/og/store/tc_kirby.rb +14 -11
  40. data/test/og/tc_accumulator.rb +1 -3
  41. data/test/og/tc_cacheable.rb +58 -0
  42. data/test/og/tc_delete_all.rb +13 -16
  43. data/test/og/tc_ez.rb +33 -0
  44. data/test/og/tc_finder.rb +2 -4
  45. data/test/og/tc_inheritance.rb +3 -3
  46. data/test/og/tc_inheritance2.rb +2 -3
  47. data/test/og/tc_join.rb +3 -2
  48. data/test/og/tc_multi_validations.rb +3 -3
  49. data/test/og/tc_multiple.rb +3 -6
  50. data/test/og/tc_override.rb +19 -13
  51. data/test/og/tc_polymorphic.rb +1 -3
  52. data/test/og/tc_resolve.rb +32 -0
  53. data/test/og/tc_reverse.rb +27 -28
  54. data/test/og/tc_scoped.rb +2 -4
  55. data/test/og/tc_select.rb +1 -3
  56. data/test/og/tc_store.rb +3 -8
  57. data/test/og/tc_validation.rb +2 -2
  58. data/test/og/tc_validation2.rb +56 -58
  59. data/test/og/tc_validation_loop.rb +2 -5
  60. metadata +15 -7
  61. data/lib/og/vendor/mysql411.rb +0 -306
@@ -2,7 +2,7 @@
2
2
 
3
3
  TITLE : &title Og
4
4
  NAME : &pkg og
5
- VERSION : '0.27.0'
5
+ VERSION : '0.28.0'
6
6
  STATUS : beta
7
7
 
8
8
  AUTHOR : George Moschovitis
@@ -17,7 +17,7 @@ DESCRIPTION: >
17
17
  KirbyBase, Filesystem and more.
18
18
 
19
19
  DEPENDENCIES:
20
- - [ glue, '= 0.27.0' ]
20
+ - [ glue, '= 0.28.0' ]
21
21
 
22
22
  DISTRIBUTE: [ gem, tgz, zip ]
23
23
 
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = Og 0.27.0 README
1
+ = Og 0.28.0 README
2
2
 
3
3
  Og (ObjectGraph) is a powerful and elegant object-relational mapping
4
4
  library. Og manages the lifecycle of Ruby objects and provides
@@ -16,8 +16,8 @@ automatically generates join tables for many_to_many relations
16
16
  and provides a collection of usefull Mixins to synthesize
17
17
  common Entities.
18
18
 
19
- Adapters for PostgreSQL, MySQL, SQLite3, KirbyBase, Memory, Filesystem,
20
- Oracle and SQL Server are included.
19
+ Adapters for PostgreSQL, MySQL, SQLite3, KirbyBase, Memory,
20
+ Filesystem, Oracle and SQL Server are included.
21
21
 
22
22
  Og is part of the Nitro project, released as a stand-alone library
23
23
  due to popular demand. You can find the ChangeLog in the Nitro
@@ -44,6 +44,8 @@ The library provides the following features:
44
44
  stores in the same application.
45
45
  * Deserialize to Ruby Objects.
46
46
  * Deserialize sql join queries to Ruby Objects.
47
+ * Can optionally use Ruby as a query language.
48
+ * Supports model caching (even on distribbuted environments)
47
49
  * Eager associations.
48
50
  * Serialize arbitrary ruby object graphs through YAML.
49
51
  * Connection pooling.
@@ -81,7 +83,9 @@ Documentation for Og can be found at
81
83
 
82
84
  Don't forget to read the file doc/RELEASES for usefull
83
85
  documentation bits. Also, have a look at the test cases in
84
- the test directory for examples of usage.
86
+ the test directory for examples of usage. Additional examples
87
+ of Og usage can be found at the example distribution of the
88
+ Nitro Web Framework (http://www.nitrohq.com)
85
89
 
86
90
  You can find a nice tutorial at www.rubygarden.com. Be warned
87
91
  that this tutorial describes an earlier version of Og. A *LOT*
data/Rakefile CHANGED
@@ -30,7 +30,7 @@ task :default => :package
30
30
  # Run the tests.
31
31
 
32
32
  Rake::TestTask.new do |t|
33
- cwd = File.expand_path(File.join(File.dirname(__FILE__) + '.'))
33
+ cwd = File.expand_path(File.join(File.dirname(__FILE__), '..'))
34
34
  t.libs << 'test'
35
35
  %w[glue nitro og].each do |dir|
36
36
  t.libs << File.join(cwd, dir, 'lib')
@@ -33,7 +33,7 @@ IDEAS, ADDITIONAL CODING, SUPPORT:
33
33
  * Matt Bowen <matt.bowen@farweststeel.com>
34
34
  Oracle driver, documentation.
35
35
 
36
- * Aidan Rogers <aidan@yoyo.org>
36
+ * Aidan Rogers <aidan@infurious.com>
37
37
  Bug reports, patches.
38
38
 
39
39
  * Thomas Quas <tquas@yahoo.com>
@@ -1,3 +1,84 @@
1
+ == Version 0.28.0
2
+
3
+ A snapshot of the latest developments. As always, cool new
4
+ features were added, the code is refactored, the security increased
5
+ and reported bugs fixed.
6
+
7
+ Most notable changes:
8
+
9
+ * New generalized caching system. The caching code is refactored
10
+ in a new Glue system. At the moment, caches in memory, DRb,
11
+ filesystem and Og are provided. A memcache version will be available
12
+ in the near future. The new caching system is used to implement
13
+ Session stores, Og caching, Fragment caching, and Application scoped
14
+ parameters. A useful DRb cache management script is provided to
15
+ manage multiple DRb caches.
16
+
17
+ * Introduced a new Og Cacheable mixin. By including this mixin
18
+ in your classes you make them eligible to Og caching. Here comes
19
+ an example:
20
+
21
+ class User
22
+ is Cachable
23
+ property :name, String
24
+ property :age, Fixnum
25
+ end
26
+
27
+ Cacheable reuses the new generalized caching system to provide
28
+ various options for distributed caching. At the moment entities
29
+ (instances of managed classes) are cached by their primary key.
30
+
31
+ * Og now advanced quering using Ruby as the data query language
32
+ to complement the usage of Ruby as a data definition language
33
+ and provide an end-to-end Ruby solution. At the moment only
34
+ supported for the SQL based adapters. Here comes an example:
35
+
36
+ users = User.find do |user|
37
+ user.age > 10
38
+ user.any {
39
+ name == 'George'
40
+ name == 'Stella'
41
+ }
42
+ end
43
+
44
+ # => SELECT * FROM oguser WHERE (oguser.age > 10 AND (oguser.name = 'George' OR oguser.name = 'Stella'))
45
+
46
+ This feature uses the Caboose/EZ code by Ezra. Pure magic!
47
+
48
+ * Og find now supports prepared statement like syntax:
49
+
50
+ User.find :condition => ['name LIKE ? and create_time > ?', 'g%', Time.now]
51
+
52
+ The interpolated values are automatically escaped to avoid
53
+ SQL injection attacks.
54
+
55
+ Some additional forms of find are supported:
56
+
57
+ User.find [['name = ? and create_time > ?', 'gmosx', Time.now]
58
+ User.find "name = 'gmosx'"
59
+
60
+ and more.
61
+
62
+ * Added experimental support for deep copying (cloning) of Og
63
+ managed objects. This mechanism handles properties (annotated
64
+ attributes) and some relation types.
65
+
66
+ * Integration of Facets 1.0.1. The new library features a better
67
+ API and better implementation of various features.
68
+
69
+ * Added schema evolution support to the SQLite adapter. All major
70
+ Og adapter support automatic schema evolution, ie Og detects common
71
+ types of changes in your Ruby code to automatically alter the
72
+ underlying schema for you.
73
+
74
+ * Introduced Og SQLite2 (legacy SQLite) adapter.
75
+
76
+ * Added more test cases, and improved RDoc comments throughout
77
+ the code.
78
+
79
+ * Many, many bug fixes.
80
+
81
+
1
82
  == Version 0.27.0
2
83
 
3
84
  Once again we have a great mix of cool new features, along
@@ -1,15 +1,22 @@
1
1
  = Og Examples
2
2
 
3
+ Here you can find some simple Og examples. For more examples
4
+ please download the Nitro examples tarball. Nitro is a Ruby
5
+ Web Framework that uses Og.
6
+
7
+
3
8
  == run.rb
4
9
 
5
10
  A simple example that demonstrates some Og features. The example
6
11
  automatically creates a 'test' database.
7
12
 
13
+
8
14
  == mock_example.rb
9
15
 
10
16
  Demonstrates how easily the Og infrastructure can be mocked,
11
17
  for easy test unit writing.
12
18
 
19
+
13
20
  == mysql_to_psql.rb
14
21
 
15
22
  Demonstrates how easy it is to migrate a mysql database
@@ -0,0 +1,152 @@
1
+ require 'facet/classinherit'
2
+
3
+ module Glue
4
+
5
+ # Include this module in your Og managed classes to make
6
+ # them cacheable. Only queries by id are cached.
7
+ #
8
+ # If you use a distributed cache (drb, memcache, etc) , you may
9
+ # have to start a separate server.
10
+ #
11
+ #--
12
+ # gmosx, WARNING: If the file lib/og/entity.rb is changed
13
+ # this file should be updated to reflect the changes!
14
+ #++
15
+
16
+ module Cacheable
17
+
18
+ ClassInherit do
19
+
20
+ def after_enchant(base)
21
+ base.module_eval do
22
+
23
+ alias_method :save_without_cache, :save
24
+ def save(options = nil)
25
+ Cacheable.cache_delete(self.class, pk)
26
+ val = save_without_cache(options)
27
+ Cacheable.cache_set(self)
28
+ return val
29
+ end
30
+ alias_method :save!, :save
31
+ alias_method :validate_and_save, :save
32
+
33
+ alias_method :force_save_without_cache!, :force_save!
34
+ def force_save!(options = nil)
35
+ Cacheable.cache_delete(self.class, pk)
36
+ val = force_save_without_cache!(options)
37
+ Cacheable.cache_set(self)
38
+ return val
39
+ end
40
+
41
+ alias_method :insert_without_cache, :insert
42
+ def insert
43
+ insert_without_cache()
44
+ Cacheable.cache_set(self)
45
+ return self
46
+ end
47
+
48
+ alias_method :update_without_cache, :update
49
+ def update(options = nil)
50
+ Cacheable.cache_delete(self.class, pk)
51
+ val = update_without_cache(options)
52
+ Cacheable.cache_set(self)
53
+ return val
54
+ end
55
+
56
+ alias_method :update_properties_without_cache, :update_properties
57
+ def update_properties(*properties)
58
+ Cacheable.cache_delete(self.class, pk)
59
+ val = update_properties_without_cache(*properties)
60
+ Cacheable.cache_set(self)
61
+ return val
62
+ end
63
+ alias_method :update_property, :update_properties
64
+ alias_method :pupdate, :update_properties
65
+
66
+ alias_method :update_by_sql_without_cache, :update_by_sql
67
+ def update_by_sql(set)
68
+ Cacheable.cache_delete(self.class, pk)
69
+ val = update_by_sql_without_cache(sql)
70
+ Cacheable.cache_set(self)
71
+ return val
72
+ end
73
+ alias_method :update_sql, :update_by_sql
74
+ alias_method :supdate, :update_by_sql
75
+
76
+ alias_method :reload_without_cache, :reload
77
+ def reload
78
+ Cacheable.cache_delete(self.class, pk)
79
+ reload_without_cache()
80
+ Cacheable.cache_set(self)
81
+ end
82
+ alias_method :reload!, :reload
83
+
84
+ alias_method :delete_without_cache, :delete
85
+ def delete(cascade = true)
86
+ delete_without_cache(cascade)
87
+ Cacheable.cache_delete(self.class, pk)
88
+ end
89
+
90
+ def og_cache_key
91
+ "#{self.class}:#{pk}"
92
+ end
93
+
94
+ class << self
95
+ alias_method :load_without_cache, :load
96
+ def load(pk)
97
+ key = og_cache_key(pk)
98
+ unless obj = ogmanager.cache.get(key)
99
+ obj = load_without_cache(pk)
100
+ ogmanager.cache.set(key, obj)
101
+ end
102
+
103
+ return obj
104
+ end
105
+ alias_method :[], :load
106
+ alias_method :exist?, :load
107
+
108
+ alias_method :delete_without_cache, :delete
109
+ def delete(obj_or_pk, cascade = true)
110
+ delete_without_cache(obj_or_pk, cascade)
111
+ Cacheable.cache_delete(self, obj_or_pk)
112
+ end
113
+
114
+ def og_cache_key(pk)
115
+ "#{self}:#{pk}"
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+ end
122
+
123
+ end
124
+
125
+ # ...
126
+
127
+ def self.cache_get(klass, pk)
128
+ end
129
+
130
+ # ...
131
+
132
+ def self.cache_set(obj)
133
+ obj.class.ogmanager.cache.set(obj.og_cache_key, obj)
134
+ end
135
+
136
+ # Invalidate the cache entry for an object. Og high level
137
+ # methods (for example the entity methods) automatically
138
+ # call this method where needed. However if you manually alter
139
+ # the store using Og low level methods (for example a native
140
+ # SQL query) you should call this method explicitly.
141
+
142
+ def self.cache_delete(klass, pk)
143
+ key = "og#{klass}:#{pk}"
144
+ # self.og_local_cache.delete(key)
145
+ klass.ogmanager.cache.delete(key)
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ # * George Moschovitis <gm@navel.gr>
@@ -1,5 +1,6 @@
1
- require 'mega/dynamod'
2
- require 'mega/orm_support'
1
+ require 'facet/ormsupport'
2
+
3
+ require 'glue/paramix'
3
4
 
4
5
  module Glue
5
6
 
@@ -11,7 +12,7 @@ module Glue
11
12
 
12
13
  module NestedSets
13
14
 
14
- def self.append_dynamic_features(base, options)
15
+ def self.included_with_params(base, options)
15
16
  c = {
16
17
  :left => 'lft',
17
18
  :right => 'rgt',
@@ -128,7 +129,7 @@ end
128
129
 
129
130
  module Hierarchical
130
131
 
131
- def self.append_dynamic_features(base, options)
132
+ def self.included_with_params(base, options)
132
133
  o = {
133
134
  :method => :nested_sets,
134
135
  }
@@ -1,4 +1,3 @@
1
- require 'mega/dynamod'
2
1
  require 'glue/on_included'
3
2
 
4
3
  module Glue
@@ -1,4 +1,4 @@
1
- require 'mega/dynamod'
1
+ require 'glue/paramix'
2
2
  require 'glue/aspects'
3
3
 
4
4
  module Glue
@@ -8,63 +8,65 @@ module Glue
8
8
  module Orderable
9
9
  include Glue::Aspects
10
10
 
11
- dynamic_feature do |opt|
11
+ def self.included_with_parameters(base, opt)
12
+ base.module_eval do
12
13
 
13
- opt_position = opt[:position] || 'position'
14
+ opt_position = opt[:position] || 'position'
14
15
 
15
- opt_type = opt[:type] || Fixnum
16
+ opt_type = opt[:type] || Fixnum
16
17
 
17
- # provide a user defined condition.
18
-
19
- opt_condition = opt[:condition]
18
+ # provide a user defined condition.
19
+
20
+ opt_condition = opt[:condition]
20
21
 
21
- # provide a condition based on a key field (?)
22
-
23
- opt_scope = opt[:scope]
22
+ # provide a condition based on a key field (?)
23
+
24
+ opt_scope = opt[:scope]
24
25
 
25
- # clean scope field.
26
-
27
- if opt_scope
28
- if opt_scope.to_s !~ /_oid$/
29
- opt_scope = "#{opt_scope}_oid".to_sym
30
- else
31
- opt_scope = opt_scope.to_sym
26
+ # clean scope field.
27
+
28
+ if opt_scope
29
+ if opt_scope.to_s !~ /_oid$/
30
+ opt_scope = "#{opt_scope}_oid".to_sym
31
+ else
32
+ opt_scope = opt_scope.to_sym
33
+ end
32
34
  end
33
- end
34
35
 
35
- define_method :orderable_position do
36
- opt_position
37
- end
36
+ define_method :orderable_position do
37
+ opt_position
38
+ end
38
39
 
39
- define_method :orderable_type do
40
- opt_type
41
- end
40
+ define_method :orderable_type do
41
+ opt_type
42
+ end
42
43
 
43
- define_method :orderable_scope do
44
- opt_scope
45
- end
44
+ define_method :orderable_scope do
45
+ opt_scope
46
+ end
46
47
 
47
- define_method :orderable_condition do
48
- scope = orderable_scope
49
- if scope
50
- scope_value = send(scope)
51
- scope = scope_value ? "#{scope} = #{scope_value}" : "#{scope} IS NULL"
48
+ define_method :orderable_condition do
49
+ scope = orderable_scope
50
+ if scope
51
+ scope_value = send(scope)
52
+ scope = scope_value ? "#{scope} = #{scope_value}" : "#{scope} IS NULL"
53
+ end
54
+ return [ opt_condition, scope ].compact
52
55
  end
53
- return [ opt_condition, scope ].compact
54
- end
55
56
 
56
- # How to check if property is already defined?
57
-
58
- unless method_defined?( opt_position )
59
- define_method( opt_position ) do @position ; end
60
- define_method( "#{opt_position}=" ) do |x| @position = x ; end
61
- property opt_position, opt_type
62
- end
57
+ # How to check if property is already defined?
58
+
59
+ unless method_defined?( opt_position )
60
+ define_method( opt_position ) do @position ; end
61
+ define_method( "#{opt_position}=" ) do |x| @position = x ; end
62
+ property opt_position, opt_type
63
+ end
63
64
 
64
- # Use position for general reference.
65
-
66
- attr_accessor :position
65
+ # Use position for general reference.
66
+
67
+ attr_accessor :position
67
68
 
69
+ end
68
70
  end #dynamic_feature
69
71
 
70
72
  before "add_to_bottom", :on => :og_insert