og 0.22.0 → 0.23.0

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.
data/INSTALL CHANGED
@@ -47,7 +47,8 @@ that you possibly have allready installed. Use with caution.
47
47
 
48
48
  You also have to manualy install the following libraries:
49
49
 
50
- * Facets
50
+ * Nano
51
+ * Mega
51
52
  * RedCloth
52
53
 
53
54
  = Manual installation.
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = Og 0.22.0 README
1
+ = Og 0.23.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
@@ -160,8 +160,8 @@ http://rubyforge.org/mailman/listinfo/nitro-general
160
160
 
161
161
  == Licence
162
162
 
163
- Copyright (c) 2004-2005, George 'tml' Moschovitis.
164
163
  Copyright (c) 2004-2005, Navel Ltd (http://www.navel.gr)
164
+ Copyright (c) 2004-2005, George 'gmosx' Moschovitis (http://www.gmosx.com).
165
165
 
166
166
  Og (http://www.nitrohq.com) is copyrighted free
167
167
  software created and maintained by George Moschovitis (mailto:gm@navel.gr)
data/Rakefile CHANGED
@@ -66,7 +66,7 @@ spec = Gem::Specification.new do |s|
66
66
 
67
67
  s.files = FileList[
68
68
  '[A-Z]*', 'install.rb', '{bin,benchmark,examples,doc,lib,test,vendor}/**/*'
69
- ].exclude('.svn/**/*').exclude('**/*.log').to_a
69
+ ].exclude("_darcs").exclude("_darcs/**/*").exclude('**/*.log').to_a
70
70
 
71
71
  s.require_path = 'lib'
72
72
  s.autorequire = 'og'
@@ -1,3 +1,7 @@
1
+ 11-08-2005 Aleksi Niemela <Aleksi.Niemela@cs.helsinki.fi>
2
+
3
+ * lib/og/store/*: log creation of join tables.
4
+
1
5
  07-08-2005 George Moschovitis <gm@navel.gr>
2
6
 
3
7
  * lib/og/entity.rb: fixed schema_inheritance alias.
data/doc/RELEASES CHANGED
@@ -1,3 +1,56 @@
1
+ == Version 0.23.0
2
+
3
+ The summer vacations are over and there is a brand new Nitro
4
+ release. There is a preview of the new Scaffolder (also handles
5
+ Og relations), lots of small features and improvements and many bug
6
+ fixes. Moreover the code has been restructured to utilize the
7
+ excellent Nano/Mega project as the support library.
8
+
9
+ Most notable additions:
10
+
11
+ * Scaffolding reloaded. The scaffolding infrastrucure is
12
+ reimplemented to generate more flexible code. The automatically
13
+ generated forms allow for visualisation and editing of
14
+ Og relations suchs as HasMany and BelongsTo.
15
+
16
+ Morover, an experimental admin component is provided. Just add the
17
+ line
18
+
19
+ require 'part/admin'
20
+
21
+ and surf
22
+
23
+ http://www.mysite.com/admin
24
+
25
+ To enter a simple administration screen. This feature is
26
+ considered a preview and will be improved in a future version.
27
+
28
+ * Introduced Og Taggable mixin. It was never easier to add
29
+ tagging to your appplication.
30
+
31
+ class Article
32
+ include Og::Taggable
33
+ ..
34
+ end
35
+
36
+ article.tag('navel', 'gmosx', 'nitro')
37
+ article.tags
38
+ article.tag_names
39
+ Article.find_with_tags('navel', 'gmosx')
40
+ Article.find_with_any_tag('name', 'gmosx')
41
+
42
+ t = Article::Tag.find_by_name('ruby')
43
+ t.articles
44
+ t.articles.count
45
+
46
+ For an example usage of this Mixin, consult the Spark sources.
47
+
48
+ * Added support for 'evolving' a single Og managed class. Useful
49
+ when you are in development mode and change your schema.
50
+
51
+ * Many many small bug fixes.
52
+
53
+
1
54
  == Version 0.22.0
2
55
 
3
56
  A snapshot of the latest developments. Many requested features
data/examples/run.rb CHANGED
@@ -23,7 +23,7 @@ end
23
23
  # = A Parent class.
24
24
 
25
25
  class User
26
- property :name, String, :unique => true
26
+ property :name, String, :uniq => true
27
27
  has_many :comments, UserComment
28
28
 
29
29
  def initialize(name = nil)
data/lib/og.rb CHANGED
@@ -1,20 +1,20 @@
1
1
  # = Og
2
2
  #
3
- # Copyright (c) 2004-2005, George Moschovitis (http://www.gmosx.com)
4
3
  # Copyright (c) 2004-2005, Navel Ltd (http://www.navel.gr)
4
+ # Copyright (c) 2004-2005, George Moschovitis (http://www.gmosx.com)
5
5
  #
6
- # Og is copyrighted free software created and maintained by
7
- # George Moschovitis (mailto:gm@navel.gr) and released under the
8
- # standard BSD Licence. For details consult the file doc/LICENCE.
6
+ # Og (http://www.nitrohq.com) is copyrighted free software
7
+ # created and maintained by George Moschovitis (mailto:gm@navel.gr)
8
+ # and released under the standard BSD Licence. For details
9
+ # consult the file doc/LICENCE.
10
+
11
+ require 'mega/synchash'
12
+ require 'mega/syncarray'
9
13
 
10
14
  require 'glue'
11
15
  require 'glue/logger'
12
16
  require 'glue/attribute'
13
17
  require 'glue/property'
14
- require 'glue/array'
15
- require 'glue/hash'
16
- require 'glue/time'
17
- require 'glue/pool'
18
18
  require 'glue/validation'
19
19
  require 'glue/aspects'
20
20
  require 'glue/configuration'
@@ -23,37 +23,6 @@ require 'glue/configuration'
23
23
  # provides transparent and efficient object-relational mapping
24
24
  # and querying mechanisms.
25
25
  #
26
- # === Features
27
- #
28
- # The library provides the following features:
29
- #
30
- # * Object-Relational mapping, automatically maps standard
31
- # Ruby objects to sql schemas
32
- # * Absolutely no configuration files.
33
- # * Multiple stores (PostgreSQL, MySQL, SQLite, Oraclei, SqlServer, ..).
34
- # * Supports non SQL stores (in-memory, filesystem, ..).
35
- # * Can 'reverse engineer' legacy database schemase.
36
- # * Fine-grained or High-level customization of the generated
37
- # schema.
38
- # * ActiveRecord-style domain specific language and db synchronized
39
- # collections.
40
- # * Transforms resultsets from arbitrary sql queries to Ruby objects.
41
- # * Independent store for each object class, can support multiple
42
- # stores in the same application.
43
- # * Deserialize to Ruby Objects.
44
- # * Deserialize sql join queries to Ruby Objects.
45
- # * Eager associations.
46
- # * Serialize arbitrary ruby object graphs through YAML.
47
- # * Connection pooling.
48
- # * Thread safety.
49
- # * SQL transactions.
50
- # * Aspect oriented constructs allow interception of lifecycle callbacks.
51
- # * Transparent support for cascading deletes for all backends.
52
- # * Hierarchical structures (nested sets)
53
- # * Works safely as part of distributed application.
54
- # * Optimistic locking.
55
- # * Simple implementation.
56
- #
57
26
  # === Property Metadata
58
27
  #
59
28
  # Og defines, reserves and uses the following property
@@ -71,19 +40,12 @@ require 'glue/configuration'
71
40
  # mark them as Object (or Array or Hash) in the prop_accessor
72
41
  # and the engine will serialize a YAML dump of the object.
73
42
  # Arbitrary object graphs are supported too.
74
- #
75
- # === Lifecycle Callbacks
76
- #
77
- # * og_read
78
- # * og_insert
79
- # * og_update
80
- # * og_delete
81
43
 
82
44
  module Og
83
45
 
84
46
  # The version.
85
47
 
86
- Version = '0.22.0'
48
+ Version = '0.23.0'
87
49
 
88
50
  # Library path.
89
51
 
@@ -170,11 +132,11 @@ module Og
170
132
 
171
133
  end
172
134
 
135
+ #--
173
136
  # gmosx: leave this here.
137
+ #++
174
138
 
175
139
  require 'og/manager'
176
140
  require 'og/errors'
177
141
  require 'og/types'
178
142
  require 'og/validation'
179
-
180
- # * George Moschovitis <gm@navel.gr>
data/lib/og/entity.rb CHANGED
@@ -56,6 +56,11 @@ module EntityMixin
56
56
  def transaction(&block)
57
57
  self.class.ogmanager.store.transaction(&block)
58
58
  end
59
+
60
+ def saved?
61
+ not @oid.nil?
62
+ end
63
+ alias_method :serialized?, :saved?
59
64
 
60
65
  def og_quote(obj)
61
66
  self.class.ogmanager.store.quote(obj)
data/lib/og/errors.rb CHANGED
@@ -1,5 +1,3 @@
1
- # $Id$
2
-
3
1
  module Og
4
2
 
5
3
  # This exception is thrown when a low level error happens
@@ -14,3 +12,5 @@ class StoreException < Exception
14
12
  end
15
13
 
16
14
  end
15
+
16
+ # * George Moschovitis <gm@navel.gr>
data/lib/og/manager.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'mega/pool'
2
+
1
3
  require 'og/entity'
2
4
  require 'og/store'
3
5
 
@@ -38,7 +40,7 @@ class Manager
38
40
  def initialize(options)
39
41
  @options = options
40
42
  @entities = {}
41
- @pool = Glue::Pool.new
43
+ @pool = Pool.new
42
44
 
43
45
  @store_class = Store.for_name(options[:store])
44
46
  @store_class.destroy(options) if options[:destroy]
@@ -108,11 +110,6 @@ class Manager
108
110
 
109
111
  info = EntityInfo.new(klass)
110
112
 
111
- # ensure that the superclass is managed before the
112
- # subclass.
113
-
114
- manage(klass.superclass) if has_super?(klass)
115
-
116
113
  klass.module_eval %{
117
114
  def ==(other)
118
115
  other ? @#{klass.primary_key.first} == other.#{klass.primary_key.first} : false
@@ -123,6 +120,11 @@ class Manager
123
120
  klass.class.send(:attr_accessor, :ogmanager)
124
121
 
125
122
  Relation.enchant(klass)
123
+
124
+ # ensure that the superclass is managed before the
125
+ # subclass.
126
+
127
+ manage(klass.superclass) if has_super?(klass)
126
128
 
127
129
  # FIXME: uggly!
128
130
  store.enchant(klass, self); put_store
@@ -167,8 +169,6 @@ class Manager
167
169
  end
168
170
  end
169
171
 
170
- Logger.debug "Og manageable classes: #{classes.inspect}" if $DBG
171
-
172
172
  return classes
173
173
  end
174
174
 
@@ -176,6 +176,9 @@ class Manager
176
176
 
177
177
  def manage_classes(*classes)
178
178
  classes = manageable_classes.flatten if classes.empty?
179
+
180
+ Logger.debug "Og manageable classes: #{classes.inspect}" if $DBG
181
+
179
182
  classes.each { |c| resolve_inheritance(c) }
180
183
  classes.each { |c| Relation.resolve(c, :resolve_target) }
181
184
  classes.each { |c| Relation.resolve(c, :resolve_polymorphic) }
@@ -187,3 +190,6 @@ class Manager
187
190
  end
188
191
 
189
192
  end
193
+
194
+ # * George Moschovitis <gm@navel.gr>
195
+ # * Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
@@ -1,8 +1,5 @@
1
- require 'facet/string/plural'
2
- require 'facet/string/singular'
3
- require 'facet/string/demodulize'
4
- require 'facet/string/underscore'
5
- require 'facet/macro'
1
+ require 'mega/macro'
2
+ require 'mega/orm_support'
6
3
 
7
4
  module Og
8
5
 
@@ -1,4 +1,4 @@
1
- require 'facet/macro'
1
+ require 'mega/macro'
2
2
 
3
3
  module Og
4
4
 
@@ -1,4 +1,4 @@
1
- require 'facet/macro'
1
+ require 'mega/macro'
2
2
 
3
3
  module Og
4
4
 
@@ -25,7 +25,7 @@ module Orderable
25
25
  scope = %{(#{scope} ? "#{scope} = \#{@#{scope}}" : "#{scope} IS NULL")}
26
26
  end
27
27
 
28
- cond = 'condition => ' + scope
28
+ cond = ':condition => ' + scope
29
29
  cond_and = ':condition => ' + scope + ' + " AND " +'
30
30
  else
31
31
  cond = ':condition => nil'
File without changes
@@ -0,0 +1,218 @@
1
+ require 'mega/macro'
2
+ require 'nano/object/assign_with'
3
+
4
+ #--
5
+ # gmosx: make polymorphic work with many_to_many.
6
+ #++
7
+
8
+ module Og
9
+
10
+ # The default Tag implementation. A tag attaches semantics to
11
+ # a given object.
12
+ #--
13
+ # FIXME: use index and char() instead of String.
14
+ #++
15
+
16
+ class Tag
17
+ property :name, String, :uniq => true
18
+
19
+ def initialize(name = nil)
20
+ @name = name
21
+ end
22
+ end
23
+
24
+ # Add tagging methods to the target class.
25
+ # For more information on the algorithms used surf:
26
+ # http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html
27
+ #
28
+ # === Example
29
+ #
30
+ # class Article
31
+ # include Taggable
32
+ # ..
33
+ # end
34
+ #
35
+ # article.tag('navel', 'gmosx', 'nitro')
36
+ # article.tags
37
+ # article.tag_names
38
+ # Article.find_with_tags('navel', 'gmosx')
39
+ # Article.find_with_any_tag('name', 'gmosx')
40
+ #
41
+ # Article::Tag.find_by_name('ruby').articles
42
+
43
+ module Taggable
44
+
45
+ # Helper.
46
+
47
+ def self.tags_to_names(the_tags, separator = ' ')
48
+ if the_tags.is_a? Array
49
+ names = the_tags
50
+ elsif the_tags.is_a? String
51
+ names = the_tags.split(separator)
52
+ end
53
+
54
+ names = names.flatten.uniq.compact
55
+
56
+ return names
57
+ end
58
+
59
+ def self.append_dynamic_features(base, options = nil)
60
+ o = {
61
+ :base_tag_class => Og::Tag,
62
+ :separator => ' '
63
+ }
64
+ o.update(options) if options
65
+
66
+ code = ''
67
+
68
+ unless o[:tag_class]
69
+ o[:tag_class] = 'Tag'
70
+ code << %{
71
+ class #{o[:tag_class]} < #{o[:base_tag_class]}
72
+ many_to_many #{base}, :foreign_name => :tags
73
+ end
74
+ }
75
+ end
76
+
77
+ tag_class = o[:tag_class]
78
+ separator = o[:separator].inspect
79
+
80
+ code << %{
81
+ many_to_many :tags, #{o[:tag_class]}
82
+ }
83
+
84
+ # Instance Methods:
85
+
86
+ # Apply a collection of tags to the object.
87
+ # +tags+ can be either an array or a String.
88
+ #
89
+ # === Options
90
+ #
91
+ # +clear+: clear the tags collection before adding the
92
+ # new tags.
93
+
94
+ code << %{
95
+ def tag(the_tags, options = {})
96
+ options = {
97
+ :clear => true
98
+ }.merge(options)
99
+
100
+ names = Taggable.tags_to_names(the_tags, #{separator})
101
+
102
+ tags.load_members
103
+
104
+ # clear the collection if needed.
105
+
106
+ self.tags.clear if options[:clear]
107
+
108
+ # append the tag names to the collection
109
+
110
+ names.each do |name|
111
+ name = name.strip
112
+ unless tagged_with?(name)
113
+ unless tag_obj = #{tag_class}.find_by_name(name)
114
+ tag_obj = #{tag_class}.create(name)
115
+ end
116
+ tags << tag_obj
117
+ end
118
+ end
119
+
120
+ self.save
121
+ end
122
+ }
123
+
124
+ # Clears all tags.
125
+
126
+ def delete_tags
127
+ end
128
+ alias_method :clear_tags, :delete_tags
129
+
130
+ # Returns an array of strings containing the tags applied to
131
+ # this object.
132
+
133
+ code << %{
134
+ def tag_names
135
+ tags.map { |t| t.name }
136
+ end
137
+ }
138
+
139
+ # Checks to see if this object has been tagged
140
+ # with +tag_name+.
141
+
142
+ code << %{
143
+ def tagged_with?(tag_name)
144
+ tag_names.include?(tag_name)
145
+ end
146
+ alias_method :tagged_by?, :tagged_with?
147
+ }
148
+
149
+ # Class Methods:
150
+
151
+ code << %{
152
+ class << self
153
+ }
154
+
155
+ # Find objects with all of the provided tags.
156
+ # INTERSECTION (AND)
157
+ #--
158
+ # TODO: move info out of compiled code.
159
+ #++
160
+
161
+ code << %{
162
+ def find_with_tags(*names)
163
+ info = ogmanager.store.join_table_info(#{base}, #{tag_class})
164
+ count = names.size
165
+ names = names.map { |n| "'\#{n}'" }.join(',')
166
+ sql = %{
167
+ SELECT o.*
168
+ FROM
169
+ \#{info[:first_table]} AS o,
170
+ \#{info[:second_table]} as t,
171
+ \#{info[:table]} as j
172
+ WHERE o.oid = j.\#{info[:first_key]}
173
+ AND t.oid = j.\#{info[:second_key]}
174
+ AND (t.name in (\#{names}))
175
+ GROUP BY o.oid
176
+ HAVING COUNT(o.oid) = \#{count};
177
+ }
178
+ return self.select(sql)
179
+ end
180
+ alias_method :find_with_tag, :find_with_tags
181
+ }
182
+
183
+ # Find objects with any of the provided tags.
184
+ # UNION (OR)
185
+
186
+ code << %{
187
+ def find_with_any_tag(*names)
188
+ info = ogmanager.store.join_table_info(#{base}, #{tag_class})
189
+ count = names.size
190
+ names = names.map { |n| "'\#{n}'" }.join(',')
191
+ sql = %{
192
+ SELECT o.*
193
+ FROM
194
+ \#{info[:first_table]} AS o,
195
+ \#{info[:second_table]} as t,
196
+ \#{info[:table]} as j
197
+ WHERE
198
+ o.oid = j.\#{info[:first_key]}
199
+ AND t.oid = j.\#{info[:second_key]}
200
+ AND (t.name in (\#{names}))
201
+ GROUP BY o.oid
202
+ }
203
+ return self.select(sql)
204
+ end
205
+ }
206
+
207
+ code << %{
208
+ end
209
+ }
210
+
211
+ base.module_eval(code)
212
+ end
213
+
214
+ end
215
+
216
+ end
217
+
218
+ # * George Moschovitis <gm@navel.gr>
data/lib/og/relation.rb CHANGED
@@ -1,16 +1,20 @@
1
- require 'facet/object/constant'
2
- require 'facet/string/plural'
3
- require 'facet/string/demodulize'
4
- require 'facet/string/underscore'
1
+ require 'nano/object/constant'
2
+ require 'nano/string/capitalized%3F'
3
+
4
+ require 'mega/orm_support'
5
5
 
6
6
  module Og
7
7
 
8
- # A relation between Entities.
8
+ # A relation between Entities.
9
9
 
10
10
  class Relation
11
11
 
12
+ # The parameters of this relation.
13
+
12
14
  attr_accessor :options
13
15
 
16
+ # Is this a polymorphic relation?
17
+
14
18
  attr_accessor :is_polymorphic
15
19
 
16
20
  # A generalized initialize method for all relations.
@@ -20,18 +24,34 @@ class Relation
20
24
  @options = options
21
25
  @options.update(args.pop) if args.last.is_a?(Hash)
22
26
 
23
- if args.empty? or (not (args.last.is_a?(Class) or args.last.is_a?(Symbol)))
24
- raise 'Class of target not defined'
25
- end
26
-
27
27
  target_name = if collection
28
28
  :target_plural_name
29
29
  else
30
30
  :target_singular_name
31
31
  end
32
32
 
33
- @options[:target_class] = args.pop
34
- @options[target_name] = args.first unless args.empty?
33
+ # Check that all needed options are provided.
34
+
35
+ if args.empty? or (not (args.last.is_a?(Class) or args.last.is_a?(Symbol)))
36
+ raise 'Class of target not defined'
37
+ end
38
+
39
+ # Try to set the target class. Checks for class and
40
+ # class symbol.
41
+
42
+ if args.last.to_s.capitalized?
43
+ @options[:target_class] = args.pop
44
+ end
45
+
46
+ # Try to set the target name.
47
+
48
+ if args.last.is_a? Symbol
49
+ @options[target_name] = args.pop
50
+ end
51
+
52
+ # Inflect target_class if not provided.
53
+
54
+ @options[:target_class] ||= @options[target_name].to_s.singular.camelize.intern
35
55
 
36
56
  setup()
37
57
  end
@@ -193,7 +213,8 @@ module RelationMacros
193
213
 
194
214
  # === Examples
195
215
  #
196
- # belongs_to Article
216
+ # belongs_to :article # inflects Article
217
+ # belongs_to Article # inflects :article
197
218
  # belongs_to :article, Article
198
219
  # belongs_to :article, Article, :view => 'lala'
199
220
 
@@ -204,7 +225,8 @@ module RelationMacros
204
225
 
205
226
  # === Examples
206
227
  #
207
- # refers_to Topic
228
+ # refers_to :topic # inflects Topic
229
+ # refers_to Topic # inflects :topic
208
230
 
209
231
  def refers_to(*args)
210
232
  require 'og/relation/refers_to'
@@ -230,11 +252,15 @@ module RelationMacros
230
252
  meta :relations, Og::HasMany.new(args, :owner_class => self, :collection => true)
231
253
  end
232
254
 
255
+ # ..
256
+
233
257
  def joins_many(*args)
234
258
  require 'og/relation/joins_many'
235
259
  meta :relations, Og::JoinsMany.new(args, :owner_class => self, :collection => true)
236
260
  end
237
261
 
262
+ # ..
263
+
238
264
  def many_to_many(*args)
239
265
  require 'og/relation/many_to_many'
240
266
  meta :relations, Og::ManyToMany.new(args, :owner_class => self, :collection => true)
@@ -1,6 +1,4 @@
1
- require 'facet/string/singular'
2
- require 'facet/string/demodulize'
3
- require 'facet/string/underscore'
1
+ require 'mega/orm_support'
4
2
 
5
3
  require 'og/relation'
6
4
  require 'og/collection'
@@ -1,6 +1,4 @@
1
- require 'facet/string/singular'
2
- require 'facet/string/demodulize'
3
- require 'facet/string/underscore'
1
+ require 'mega/orm_support'
4
2
 
5
3
  require 'og/relation'
6
4
  require 'og/collection'
@@ -26,8 +24,15 @@ class JoinsMany < Relation
26
24
  self[:target_singular_name] = target_plural_name.to_s.singular
27
25
 
28
26
  store = owner_class.ogmanager.store
29
- join_table_info = store.join_table_info(owner_class, target_class)
27
+
28
+ # handle schema_inheritance
30
29
 
30
+ join_class = owner_class
31
+ if sclass = owner_class.metadata.superclass
32
+ join_class = sclass.first
33
+ end
34
+ join_table_info = store.join_table_info(join_class, target_class)
35
+
31
36
  if through = self[:through]
32
37
  # A custom class is used for the join. Use the class
33
38
  # table and don't create a new table.
@@ -118,3 +123,4 @@ end
118
123
 
119
124
  # * George Moschovitis <gm@navel.gr>
120
125
  # * Ysabel <deb@ysabel.org>
126
+ # * Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
@@ -13,7 +13,7 @@ class RefersTo < Relation
13
13
 
14
14
  owner_class.module_eval %{
15
15
  attr_accessor :#{target_singular_name}
16
- prop_accessor :#{foreign_key}, #{target_pkclass}#{field}
16
+ prop_accessor :#{foreign_key}, #{target_pkclass}#{field}, :relation => true
17
17
 
18
18
  def #{target_singular_name}(reload = false)
19
19
  return nil if @#{foreign_key}.nil?
@@ -28,7 +28,7 @@ class RefersTo < Relation
28
28
  def #{target_singular_name}=(obj)
29
29
  @#{foreign_key} = obj.#{target_pk} if obj
30
30
  end
31
- }
31
+ }
32
32
  end
33
33
 
34
34
  end
@@ -12,6 +12,20 @@ rescue Object => ex
12
12
  end
13
13
  end
14
14
 
15
+ # Helper for scripts.
16
+ #
17
+ # === Example
18
+ #
19
+ # mysql "-u root -p", <<-END
20
+ # drop database if exists weblog_development;
21
+ # create database weblog_development;
22
+ # grant all on weblog_development.* to #{`id -un`.strip}@localhost;
23
+ # END
24
+
25
+ def mysql(opts, stream)
26
+ IO.popen("mysql #{opts}", 'w') { |io| io.puts stream }
27
+ end
28
+
15
29
  require 'og/store/sql'
16
30
 
17
31
  # Customize the standard mysql resultset to make
@@ -232,6 +246,7 @@ private
232
246
  create_join_table_sql(info).each do |sql|
233
247
  @conn.query sql
234
248
  end
249
+ Logger.debug "Created jointable '#{info[:table]}'."
235
250
  rescue => ex
236
251
  if ex.respond_to?(:errno) and ex.errno == 1050 # table already exists.
237
252
  Logger.debug 'Join table already exists' if $DBG
@@ -320,3 +335,5 @@ private
320
335
  end
321
336
 
322
337
  end
338
+
339
+ # * George Moschovitis <gm@navel.gr>
data/lib/og/store/psql.rb CHANGED
@@ -203,7 +203,7 @@ private
203
203
  rescue Object => ex
204
204
  # gmosx: any idea how to better test this?
205
205
  if ex.to_s =~ /relation .* already exists/i
206
- Logger.debug 'Table already exists' if $DBG
206
+ Logger.debug 'Table already exists'
207
207
  return
208
208
  else
209
209
  raise
@@ -219,6 +219,7 @@ private
219
219
  create_join_table_sql(info).each do |sql|
220
220
  @conn.exec(sql).clear
221
221
  end
222
+ Logger.debug "Created jointable '#{info[:table]}'."
222
223
  rescue Object => ex
223
224
  # gmosx: any idea how to better test this?
224
225
  if ex.to_s =~ /relation .* already exists/i
data/lib/og/store/sql.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'yaml'
2
2
 
3
- require 'facet/object/constant'
3
+ require 'nano/object/constant'
4
4
 
5
5
  module Og
6
6
 
@@ -323,7 +323,7 @@ class SqlStore < Store
323
323
  # selected properties. Pass the required properties as symbols
324
324
  # or strings.
325
325
  #--
326
- # gmosx, THINH: condition is not really useful here :(
326
+ # gmosx, THINK: condition is not really useful here :(
327
327
  #++
328
328
 
329
329
  def update(obj, options = nil)
@@ -445,7 +445,7 @@ class SqlStore < Store
445
445
 
446
446
  def unjoin(obj1, obj2, table)
447
447
  first, second = join_object_ordering(obj1, obj2)
448
- first_key, second_key = ordered_join_table_keys(obj1, obj2, table)
448
+ first_key, second_key = ordered_join_table_keys(obj1.class, obj2.class)
449
449
  exec "DELETE FROM #{table} WHERE #{first_key}=#{first.pk} AND #{second_key}=#{second.pk}"
450
450
  end
451
451
 
@@ -483,6 +483,9 @@ class SqlStore < Store
483
483
 
484
484
  private
485
485
 
486
+ # Create the sql table where objects of this class are
487
+ # persisted.
488
+
486
489
  def create_table(klass)
487
490
  raise 'Not implemented'
488
491
  end
@@ -494,6 +497,15 @@ private
494
497
  exec "DROP TABLE #{klass.table}"
495
498
  end
496
499
 
500
+ # Evolve (recreate) the sql table where objects of this class
501
+ # are persisted.
502
+
503
+ def evolve_table(klass)
504
+ drop_table(klass)
505
+ create_table(klass)
506
+ end
507
+ alias_method :update_table, :evolve_table
508
+
497
509
  # Return the field for the given property.
498
510
 
499
511
  def field_for_property(property)
@@ -772,7 +784,15 @@ private
772
784
  if rel = klass.relation(name)
773
785
  target_table = rel[:target_class]::OGTABLE
774
786
  tables << target_table
775
- join_conditions << "#{klass::OGTABLE}.#{rel[:foreign_key]}=#{target_table}.#{rel[:target_pk]}"
787
+ # join_conditions << "#{klass::OGTABLE}.#{rel[:foreign_key]}=#{target_table}.#{rel[:target_pk]}"
788
+ if rel.is_a?(JoinsMany)
789
+ tables << rel[:join_table]
790
+ owner_key, target_key = klass.ogmanager.store.join_table_keys(klass, rel[:target_class])
791
+ join_conditions << "#{rel[:join_table]}.#{owner_key}=#{klass::OGTABLE}.#{rel[:owner_pk]} AND \
792
+ #{rel[:join_table]}.#{target_key}=#{rel[:target_class]::OGTABLE}.#{rel[:target_pk]}"
793
+ else
794
+ join_conditions << "#{klass::OGTABLE}.#{rel[:foreign_key]}=#{target_table}.#{rel[:target_pk]}"
795
+ end
776
796
  else
777
797
  raise 'Unknown relation name'
778
798
  end
@@ -940,3 +960,4 @@ end
940
960
  # * Michael Neumann <mneumann@ntecs.de>
941
961
  # * Ghislain Mary
942
962
  # * Ysabel <deb@ysabel.org>
963
+ # * Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
@@ -159,6 +159,7 @@ private
159
159
  create_join_table_sql(info).each do |sql|
160
160
  @conn.query(sql).close
161
161
  end
162
+ Logger.debug "Created jointable '#{info[:table]}'."
162
163
  rescue Object => ex
163
164
  # gmosx: any idea how to better test this?
164
165
  if ex.to_s =~ /table .* already exists/i
@@ -1,9 +1,7 @@
1
1
  require 'test/unit'
2
2
  require 'test/unit/assertions'
3
3
 
4
- require 'facet/string/underscore'
5
- require 'facet/string/demodulize'
6
- require 'facet/string/pluralize'
4
+ require 'mega/orm_support'
7
5
 
8
6
  require 'glue'
9
7
  require 'glue/fixture'
data/lib/og/types.rb CHANGED
@@ -17,3 +17,6 @@ NotNull = { :sql => 'NOT NULL' }.freeze
17
17
  Null = { :sql => 'NULL' }.freeze
18
18
 
19
19
  end
20
+
21
+ # * Michael Neumann <mneumann@ntecs.de>
22
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,69 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+
6
+ require 'og'
7
+ require 'og/mixin/taggable'
8
+
9
+ class Article
10
+ property :title, :body, String
11
+ include Og::Taggable
12
+
13
+ def initialize(title = nil)
14
+ @title = title
15
+ end
16
+ end
17
+
18
+ $og = Og.setup(
19
+ :store => 'mysql',
20
+ :name => 'test',
21
+ :user => 'root',
22
+ :password => 'navelrulez',
23
+ :destroy => true
24
+ )
25
+
26
+ class TestOgTaggable < Test::Unit::TestCase # :nodoc: all
27
+
28
+ def test_all
29
+ a1 = Article.create('Hello')
30
+ a1.tag('navel gmosx sexy')
31
+ a1.save
32
+
33
+ a2 = Article.create('Other')
34
+ a2.tag('gmosx', 'rain')
35
+ a2.save
36
+
37
+ a3 = Article.create('George')
38
+ a3.tag('phd', 'name')
39
+ a3.save
40
+
41
+ assert_equal 3, a1.tags.size
42
+ assert a1.tag_names.include?('navel')
43
+
44
+ assert a1.tagged_with?('navel')
45
+
46
+ assert_equal false, a1.tagged_with?('photo')
47
+
48
+ res = Article.find_with_tags('navel', 'gmosx')
49
+ assert_equal 1, res.size
50
+ assert_equal 'Hello', res[0].title
51
+
52
+ res = Article.find_with_tag('gmosx')
53
+ assert_equal 2, res.size
54
+ res = res.map { |o| o.title }
55
+ assert res.include?('Hello')
56
+ assert res.include?('Other')
57
+
58
+ res = Article.find_with_any_tag('navel', 'gmosx', 'phd')
59
+ assert_equal 3, res.size
60
+
61
+ =begin
62
+ TODO:
63
+ Article.fing_with_no_tag('gmosx')
64
+ Article.find_by_tags('+name +gmosx -sexy')
65
+ Article.find_by_tags(:with => '', :any => '', :no => '')
66
+ =end
67
+ end
68
+
69
+ end
@@ -34,6 +34,21 @@ class TC_OgInheritance < Test::Unit::TestCase # :nodoc: all
34
34
  end
35
35
  end
36
36
 
37
+ class Car
38
+ property :name
39
+ end
40
+
41
+ class User
42
+ property :login, String
43
+ many_to_many Car
44
+ schema_inheritance
45
+ end
46
+
47
+ class Admin < User
48
+ property :password, String
49
+ has_one Car
50
+ end
51
+
37
52
  def test_all
38
53
  =begin
39
54
  @og = Og.setup(
@@ -48,7 +63,7 @@ class TC_OgInheritance < Test::Unit::TestCase # :nodoc: all
48
63
  :name => 'test'
49
64
  )
50
65
  =end
51
- #=begin
66
+ =begin
52
67
  @og = Og.setup(
53
68
  :destroy => true,
54
69
  :store => :psql,
@@ -56,8 +71,8 @@ class TC_OgInheritance < Test::Unit::TestCase # :nodoc: all
56
71
  :user => 'postgres',
57
72
  :password => 'navelrulez'
58
73
  )
59
- #=end
60
- =begin
74
+ =end
75
+ #=begin
61
76
  @og = Og.setup(
62
77
  :destroy => true,
63
78
  :store => :mysql,
@@ -65,7 +80,7 @@ class TC_OgInheritance < Test::Unit::TestCase # :nodoc: all
65
80
  :user => 'root',
66
81
  :password => 'navelrulez'
67
82
  )
68
- =end
83
+ #=end
69
84
  assert_equal [Document], Photo.metadata.superclass
70
85
  assert_equal [Photo, Article], Document.metadata.subclasses
71
86
 
@@ -108,5 +123,9 @@ class TC_OgInheritance < Test::Unit::TestCase # :nodoc: all
108
123
 
109
124
  articles = Article.all(:limit => 2)
110
125
  assert_equal 2, articles.size
126
+
127
+ # Bug report.
128
+ Admin.create
129
+ Admin.create.cars.size
111
130
  end
112
131
  end
@@ -0,0 +1,31 @@
1
+ $DBG = true
2
+
3
+ require 'og'
4
+ require 'test/unit'
5
+
6
+ class Book
7
+ property :title
8
+ belongs_to :owner, Person # this creates a problem?
9
+ end
10
+
11
+ class Person
12
+ property :name, Og::VarChar(128)
13
+ has_many :books, Book, :foreign_name => :owner
14
+ end
15
+
16
+ class TestOg < Test::Unit::TestCase
17
+ include Og
18
+
19
+ def test_basic
20
+ book = Book.create
21
+ person = Person.create
22
+ person.books << book
23
+ end
24
+
25
+ def setup
26
+ Og.table_prefix = nil
27
+ og = Og.setup(:destroy => true, :store => :sqlite, :name => 'test')
28
+ end
29
+ end
30
+
31
+ # * Kristof Jozsa <dyn@ond.vein.hu>
data/test/og/tc_store.rb CHANGED
@@ -31,7 +31,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
31
31
 
32
32
  class Article
33
33
  property :title, :body, String
34
- has_many Comment
34
+ has_many :comments
35
35
  has_one :author, User
36
36
  refers_to :owner, User
37
37
  many_to_many Category
@@ -103,7 +103,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
103
103
  conversions_test
104
104
  end
105
105
  =end
106
- #=begin
106
+ =begin
107
107
  def test_mysql
108
108
  @og = Og.setup(
109
109
  :destroy => true,
@@ -116,8 +116,8 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
116
116
  features_test
117
117
  # conversions_test
118
118
  end
119
- #=end
120
- =begin
119
+ =end
120
+ #=begin
121
121
  def test_sqlite
122
122
  @og = Og.setup(
123
123
  :destroy => true,
@@ -127,7 +127,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
127
127
  features_test
128
128
  conversions_test
129
129
  end
130
- =end
130
+ #=end
131
131
  =begin
132
132
  def test_memory
133
133
  @og = Og.setup(
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: og
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.22.0
7
- date: 2005-08-07 00:00:00 +03:00
6
+ version: 0.23.0
7
+ date: 2005-08-31 00:00:00 +03:00
8
8
  summary: Og (ObjectGraph)
9
9
  require_paths:
10
10
  - lib
@@ -29,82 +29,86 @@ cert_chain:
29
29
  authors:
30
30
  - George Moschovitis
31
31
  files:
32
+ - Rakefile
32
33
  - README
33
- - CHANGELOG
34
34
  - INSTALL
35
- - Rakefile
36
35
  - install.rb
37
- - benchmark/bench.rb
38
- - benchmark/sqlite-no-prepare.1.txt
39
- - benchmark/sqlite-no-prepare.2.txt
40
- - benchmark/sqlite-prepare.1.txt
41
36
  - benchmark/sqlite-prepare.2.txt
37
+ - benchmark/sqlite-prepare.1.txt
38
+ - benchmark/sqlite-no-prepare.2.txt
39
+ - benchmark/sqlite-no-prepare.1.txt
40
+ - benchmark/bench.rb
42
41
  - examples/run.rb
43
42
  - examples/mysql_to_psql.rb
44
43
  - examples/README
45
44
  - doc/tutorial.txt
46
- - doc/LICENSE
47
- - doc/RELEASES
48
45
  - doc/config.txt
46
+ - doc/RELEASES
47
+ - doc/LICENSE
49
48
  - doc/AUTHORS
49
+ - doc/CHANGELOG.1
50
50
  - lib/og
51
- - lib/og.rb
52
51
  - lib/vendor
53
- - lib/og/collection.rb
54
- - lib/og/entity.rb
55
- - lib/og/relation.rb
56
- - lib/og/relation
52
+ - lib/og.rb
57
53
  - lib/og/mixin
54
+ - lib/og/relation
58
55
  - lib/og/store
59
- - lib/og/manager.rb
60
- - lib/og/errors.rb
61
- - lib/og/store.rb
56
+ - lib/og/test
62
57
  - lib/og/validation.rb
63
58
  - lib/og/types.rb
64
- - lib/og/test
65
59
  - lib/og/test.rb
66
- - lib/og/relation/belongs_to.rb
67
- - lib/og/relation/has_many.rb
68
- - lib/og/relation/has_one.rb
60
+ - lib/og/store.rb
61
+ - lib/og/relation.rb
62
+ - lib/og/manager.rb
63
+ - lib/og/errors.rb
64
+ - lib/og/entity.rb
65
+ - lib/og/collection.rb
66
+ - lib/og/mixin/tree.rb
67
+ - lib/og/mixin/timestamped.rb
68
+ - lib/og/mixin/orderable.rb
69
+ - lib/og/mixin/optimistic_locking.rb
70
+ - lib/og/mixin/hierarchical.rb
71
+ - lib/og/mixin/taggable.rb
72
+ - lib/og/mixin/revisable.rb
69
73
  - lib/og/relation/refers_to.rb
70
74
  - lib/og/relation/many_to_many.rb
71
75
  - lib/og/relation/joins_many.rb
72
- - lib/og/mixin/hierarchical.rb
73
- - lib/og/mixin/orderable.rb
74
- - lib/og/mixin/timestamped.rb
75
- - lib/og/mixin/tree.rb
76
- - lib/og/mixin/optimistic_locking.rb
77
- - lib/og/store/filesys.rb
78
- - lib/og/store/psql.rb
79
- - lib/og/store/sql.rb
80
- - lib/og/store/mysql.rb
76
+ - lib/og/relation/has_one.rb
77
+ - lib/og/relation/has_many.rb
78
+ - lib/og/relation/belongs_to.rb
81
79
  - lib/og/store/sqlserver.rb
82
80
  - lib/og/store/sqlite.rb
83
- - lib/og/store/kirby.rb
81
+ - lib/og/store/sql.rb
82
+ - lib/og/store/psql.rb
83
+ - lib/og/store/mysql.rb
84
84
  - lib/og/store/memory.rb
85
- - lib/og/test/assertions.rb
85
+ - lib/og/store/kirby.rb
86
+ - lib/og/store/filesys.rb
86
87
  - lib/og/test/testcase.rb
88
+ - lib/og/test/assertions.rb
87
89
  - lib/vendor/mysql411.rb
88
90
  - lib/vendor/mysql.rb
89
91
  - lib/vendor/kirbybase.rb
90
92
  - lib/vendor/README
91
93
  - test/og
92
- - test/og/store
93
94
  - test/og/mixin
94
- - test/og/tc_inheritance.rb
95
+ - test/og/store
95
96
  - test/og/tc_types.rb
96
- - test/og/tc_relation.rb
97
97
  - test/og/tc_store.rb
98
- - test/og/tc_polymorphic.rb
99
- - test/og/tc_join.rb
100
98
  - test/og/tc_select.rb
101
99
  - test/og/tc_reverse.rb
100
+ - test/og/tc_relation.rb
101
+ - test/og/tc_polymorphic.rb
102
+ - test/og/tc_override.rb
102
103
  - test/og/tc_multiple.rb
103
- - test/og/store/tc_filesys.rb
104
- - test/og/mixin/tc_hierarchical.rb
105
- - test/og/mixin/tc_orderable.rb
104
+ - test/og/tc_join.rb
105
+ - test/og/tc_inheritance.rb
106
106
  - test/og/mixin/tc_timestamped.rb
107
+ - test/og/mixin/tc_orderable.rb
107
108
  - test/og/mixin/tc_optimistic_locking.rb
109
+ - test/og/mixin/tc_hierarchical.rb
110
+ - test/og/mixin/tc_taggable.rb
111
+ - test/og/store/tc_filesys.rb
108
112
  test_files: []
109
113
  rdoc_options:
110
114
  - "--main"
@@ -129,5 +133,5 @@ dependencies:
129
133
  -
130
134
  - "="
131
135
  - !ruby/object:Gem::Version
132
- version: 0.22.0
136
+ version: 0.23.0
133
137
  version: