og 0.22.0 → 0.23.0

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