og 0.26.0 → 0.27.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 +10 -5
- data/ProjectInfo +9 -2
- data/README +3 -3
- data/Rakefile +5 -1
- data/doc/AUTHORS +3 -0
- data/doc/RELEASES +57 -0
- data/lib/glue/orderable.rb +8 -8
- data/lib/og.rb +6 -6
- data/lib/og/collection.rb +12 -3
- data/lib/og/entity.rb +2 -2
- data/lib/og/manager.rb +2 -1
- data/lib/og/store.rb +5 -8
- data/lib/og/store/kirby.rb +93 -12
- data/lib/og/store/mysql.rb +7 -21
- data/lib/og/store/psql.rb +9 -3
- data/lib/og/store/sql.rb +4 -2
- data/lib/og/store/sqlite.rb +3 -1
- data/lib/og/vendor/mysql.rb +1 -1
- data/setup.rb +1585 -0
- data/test/og/mixin/tc_hierarchical.rb +2 -0
- data/test/og/mixin/tc_optimistic_locking.rb +2 -0
- data/test/og/mixin/tc_orderable.rb +2 -0
- data/test/og/mixin/tc_taggable.rb +2 -0
- data/test/og/mixin/tc_timestamped.rb +2 -0
- data/test/og/store/tc_filesys.rb +2 -0
- data/test/og/store/tc_kirby.rb +2 -0
- data/test/og/tc_accumulator.rb +92 -0
- data/test/og/tc_delete_all.rb +2 -0
- data/test/og/tc_finder.rb +2 -0
- data/test/og/tc_inheritance.rb +2 -0
- data/test/og/tc_inheritance2.rb +35 -0
- data/test/og/tc_join.rb +2 -0
- data/test/og/tc_multi_validations.rb +19 -0
- data/test/og/tc_multiple.rb +2 -0
- data/test/og/tc_override.rb +2 -0
- data/test/og/tc_polymorphic.rb +3 -1
- data/test/og/tc_relation.rb +2 -0
- data/test/og/tc_reverse.rb +2 -0
- data/test/og/tc_scoped.rb +2 -0
- data/test/og/tc_select.rb +3 -0
- data/test/og/tc_store.rb +2 -0
- data/test/og/tc_types.rb +2 -0
- data/test/og/tc_validation.rb +2 -0
- data/test/og/tc_validation2.rb +207 -0
- data/test/og/tc_validation_loop.rb +36 -0
- metadata +124 -120
- data/benchmark/bench.rb +0 -75
- data/benchmark/sqlite-no-prepare.1.txt +0 -13
- data/benchmark/sqlite-no-prepare.2.txt +0 -13
- data/benchmark/sqlite-prepare.1.txt +0 -13
- data/benchmark/sqlite-prepare.2.txt +0 -13
- data/install.rb +0 -37
data/INSTALL
CHANGED
@@ -40,16 +40,21 @@ a standard installation script is provided.
|
|
40
40
|
|
41
41
|
2. Run the installation script.
|
42
42
|
|
43
|
-
$ ruby
|
43
|
+
$ ruby setup.rb
|
44
44
|
|
45
45
|
This installation script also installs some vendor libraries
|
46
46
|
that you possibly have allready installed. Use with caution.
|
47
47
|
|
48
|
-
|
48
|
+
Dependencies needed: See 'ProjectInfo' file located in the
|
49
|
+
current directory.
|
50
|
+
|
51
|
+
Install the desired database client libraries Libraries are not
|
52
|
+
required for Og to run. If you wish to use an adapter which
|
53
|
+
uses one of the databases, then you'll need to install the
|
54
|
+
client library
|
55
|
+
|
56
|
+
Postgres, MySQL, Kirbybase
|
49
57
|
|
50
|
-
* Nano
|
51
|
-
* Mega
|
52
|
-
* RedCloth
|
53
58
|
|
54
59
|
= Manual installation.
|
55
60
|
|
data/ProjectInfo
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
TITLE : &title Og
|
4
4
|
NAME : &pkg og
|
5
|
-
VERSION : '0.
|
5
|
+
VERSION : '0.27.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.
|
20
|
+
- [ glue, '= 0.27.0' ]
|
21
21
|
|
22
22
|
DISTRIBUTE: [ gem, tgz, zip ]
|
23
23
|
|
@@ -25,6 +25,13 @@ RUBYFORGE:
|
|
25
25
|
PROJECT: 'nitro'
|
26
26
|
USERNAME: 'gmosx'
|
27
27
|
|
28
|
+
RDOC:
|
29
|
+
- dir: rdoc
|
30
|
+
options: ['--all', '--inline-source']
|
31
|
+
include:
|
32
|
+
- 'lib/og/**/*'
|
33
|
+
- '[A-Z]*'
|
34
|
+
|
28
35
|
# Anything to require upfront?
|
29
36
|
#TEST:
|
30
37
|
# fixture: ''
|
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Og 0.
|
1
|
+
= Og 0.27.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
|
@@ -163,8 +163,8 @@ http://rubyforge.org/mailman/listinfo/nitro-general
|
|
163
163
|
|
164
164
|
== Licence
|
165
165
|
|
166
|
-
Copyright (c) 2004-
|
167
|
-
Copyright (c) 2004-
|
166
|
+
Copyright (c) 2004-2006, George 'gmosx' Moschovitis (http://www.gmosx.com).
|
167
|
+
Copyright (c) 2004-2006, Navel Ltd (http://www.navel.gr)
|
168
168
|
|
169
169
|
Og (http://www.nitrohq.com) is copyrighted free
|
170
170
|
software created and maintained by George Moschovitis (mailto:gm@navel.gr)
|
data/Rakefile
CHANGED
@@ -30,7 +30,11 @@ 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
34
|
t.libs << 'test'
|
35
|
+
%w[glue nitro og].each do |dir|
|
36
|
+
t.libs << File.join(cwd, dir, 'lib')
|
37
|
+
end
|
34
38
|
t.test_files = FileList['test/**/tc*.rb']
|
35
39
|
t.verbose = true
|
36
40
|
end
|
@@ -65,7 +69,7 @@ spec = Gem::Specification.new do |s|
|
|
65
69
|
s.required_ruby_version = '= 1.8.3'
|
66
70
|
|
67
71
|
s.files = FileList[
|
68
|
-
'[A-Z]*', '
|
72
|
+
'[A-Z]*', 'setup.rb', '{bin,benchmark,examples,doc,lib,test,vendor}/**/*'
|
69
73
|
].exclude("_darcs").exclude("_darcs/**/*").exclude('**/*.log').to_a
|
70
74
|
|
71
75
|
s.require_path = 'lib'
|
data/doc/AUTHORS
CHANGED
data/doc/RELEASES
CHANGED
@@ -1,3 +1,60 @@
|
|
1
|
+
== Version 0.27.0
|
2
|
+
|
3
|
+
Once again we have a great mix of cool new features, along
|
4
|
+
with bugfixes and a myriad of smaller improvements. Go and
|
5
|
+
download the most advanced Ruby ORM Framework you can find.
|
6
|
+
|
7
|
+
Most notable changes:
|
8
|
+
|
9
|
+
* Og live collections support accumulation. Here is an example:
|
10
|
+
|
11
|
+
class Category
|
12
|
+
has_many :projects
|
13
|
+
end
|
14
|
+
|
15
|
+
class Project
|
16
|
+
has_many :clients
|
17
|
+
end
|
18
|
+
|
19
|
+
class Client
|
20
|
+
end
|
21
|
+
|
22
|
+
clients = category.projects.clients
|
23
|
+
|
24
|
+
# => returns all clients for this category!
|
25
|
+
|
26
|
+
* New WebFile system. Uploading files and handling photos was
|
27
|
+
never easier:
|
28
|
+
|
29
|
+
class Photo
|
30
|
+
is Timestamped
|
31
|
+
is Taggable
|
32
|
+
property :title, String
|
33
|
+
property :file, WebFile, :magick => { :small => '64x64', :medium => '128x128' }
|
34
|
+
end
|
35
|
+
|
36
|
+
# the upload action
|
37
|
+
|
38
|
+
def upload
|
39
|
+
photo = Photo.assign(request)
|
40
|
+
photo.save
|
41
|
+
end
|
42
|
+
|
43
|
+
This saves the photo, and creates 2 thumbnails. You can easily
|
44
|
+
access the photo and thumbnails like this:
|
45
|
+
|
46
|
+
<img src="#{photo.file_medium_thumbnail}" />
|
47
|
+
<img src="#{photo.file_small_thumbnail}" />
|
48
|
+
|
49
|
+
ie obj.{propertyname}_#{thumbname}_thumbnail
|
50
|
+
|
51
|
+
* Improved the generated RDOC comments.
|
52
|
+
|
53
|
+
* Added evolution support to the KirbyBase adapter.
|
54
|
+
|
55
|
+
* Added setup.rb for non-gem installation.
|
56
|
+
|
57
|
+
|
1
58
|
== Version 0.26.0
|
2
59
|
|
3
60
|
This is the release with the most community contributions. Check
|
data/lib/glue/orderable.rb
CHANGED
@@ -128,7 +128,7 @@ module Orderable
|
|
128
128
|
end
|
129
129
|
self.class.update( adj, :condition => con.join(' AND ') )
|
130
130
|
@position = dest_position
|
131
|
-
update_property(
|
131
|
+
update_property(pos.to_sym)
|
132
132
|
end
|
133
133
|
|
134
134
|
self
|
@@ -185,12 +185,12 @@ module Orderable
|
|
185
185
|
|
186
186
|
def increment_position
|
187
187
|
@position += 1
|
188
|
-
update_property(
|
188
|
+
update_property(orderable_position.to_sym)
|
189
189
|
end
|
190
190
|
|
191
191
|
def decrement_position
|
192
192
|
@position -= 1
|
193
|
-
update_property(
|
193
|
+
update_property(orderable_position.to_sym)
|
194
194
|
end
|
195
195
|
|
196
196
|
def bottom_position
|
@@ -200,31 +200,31 @@ module Orderable
|
|
200
200
|
|
201
201
|
def set_top_position
|
202
202
|
@position = 1
|
203
|
-
update_property(
|
203
|
+
update_property(orderable_position.to_sym)
|
204
204
|
end
|
205
205
|
|
206
206
|
def set_bottom_position
|
207
207
|
@position = bottom_position + 1
|
208
|
-
update_property(
|
208
|
+
update_property(orderable_position.to_sym)
|
209
209
|
end
|
210
210
|
|
211
211
|
def increment_position_of_higher_items
|
212
212
|
pos = orderable_position
|
213
213
|
con = orderable_condition + [ "#{pos} < #{@position}" ]
|
214
|
-
self.class.update
|
214
|
+
self.class.update "#{pos}=(#{pos} + 1)", :condition => con.join(' AND ')
|
215
215
|
end
|
216
216
|
|
217
217
|
def increment_position_of_all_items
|
218
218
|
pos = orderable_position
|
219
219
|
con = orderable_condition
|
220
220
|
con = con.empty? ? nil : con.join(' AND ')
|
221
|
-
self.class.update
|
221
|
+
self.class.update "#{pos}=(#{pos} + 1)", :condition => con
|
222
222
|
end
|
223
223
|
|
224
224
|
def decrement_position_of_lower_items
|
225
225
|
pos = orderable_position
|
226
226
|
con = orderable_condition + [ "#{pos} > #{@position}" ]
|
227
|
-
self.class.update
|
227
|
+
self.class.update "#{pos}=(#{pos} - 1)", :condition => con.join(' AND ')
|
228
228
|
end
|
229
229
|
|
230
230
|
end
|
data/lib/og.rb
CHANGED
@@ -43,7 +43,7 @@ module Og
|
|
43
43
|
|
44
44
|
# The version.
|
45
45
|
|
46
|
-
Version = '0.
|
46
|
+
Version = '0.27.0'
|
47
47
|
|
48
48
|
# Library path.
|
49
49
|
|
@@ -115,16 +115,16 @@ module Og
|
|
115
115
|
# if it was being called by Og.setup to provide
|
116
116
|
# additional, faster or enhanced functionality.
|
117
117
|
|
118
|
-
puts options[:called_by_og_setup]
|
119
118
|
options[:called_by_og_setup] = true if options[:called_by_og_setup].nil?
|
120
119
|
|
121
120
|
m = @@manager = Manager.new(options)
|
122
121
|
m.manage_classes
|
123
122
|
|
124
|
-
# Allows functionality that requires a store is
|
125
|
-
# to be implemented. A vastly superior
|
126
|
-
# foreign key constraints is an
|
127
|
-
# this provides. Currently
|
123
|
+
# Allows functionality that requires a store is
|
124
|
+
# finalized to be implemented. A vastly superior
|
125
|
+
# method of constructing foreign key constraints is an
|
126
|
+
# example of functionality this provides. Currently
|
127
|
+
# only used by the PostgreSQL store.
|
128
128
|
|
129
129
|
m.post_setup if options[:called_by_og_setup]
|
130
130
|
rescue Exception => ex
|
data/lib/og/collection.rb
CHANGED
@@ -228,11 +228,20 @@ class Collection
|
|
228
228
|
find(options).first
|
229
229
|
end
|
230
230
|
|
231
|
-
#
|
231
|
+
# Try to execute an accumulator or else
|
232
|
+
# redirect all other methods to the members array.
|
233
|
+
#
|
234
|
+
# An example of the accumulator:
|
235
|
+
#
|
236
|
+
# foo_foobars = foo1.bars.foobars
|
232
237
|
|
233
238
|
def method_missing(symbol, *args, &block)
|
234
239
|
load_members
|
235
|
-
@
|
240
|
+
if @member_class.instance_methods.include? symbol.to_s
|
241
|
+
@members.inject([]) { |a, x| a << x.send(symbol) }.flatten
|
242
|
+
else
|
243
|
+
@members.send(symbol, *args, &block)
|
244
|
+
end
|
236
245
|
end
|
237
246
|
|
238
247
|
private
|
@@ -245,4 +254,4 @@ end
|
|
245
254
|
end
|
246
255
|
|
247
256
|
# * George Moschovitis <gm@navel.gr>
|
248
|
-
# *
|
257
|
+
# * Julien Perrot <jperrot@exosec.fr>
|
data/lib/og/entity.rb
CHANGED
@@ -106,8 +106,8 @@ module EntityMixin
|
|
106
106
|
return obj
|
107
107
|
end
|
108
108
|
|
109
|
-
def assign_properties(values, options)
|
110
|
-
Property.
|
109
|
+
def assign_properties(values, options = {})
|
110
|
+
Property.populate_object(self.new, values, options)
|
111
111
|
end
|
112
112
|
alias_method :assign, :assign_properties
|
113
113
|
|
data/lib/og/manager.rb
CHANGED
@@ -102,9 +102,10 @@ class Manager
|
|
102
102
|
info = EntityInfo.new(klass)
|
103
103
|
|
104
104
|
# DON'T DO THIS!!!
|
105
|
+
|
105
106
|
klass.module_eval %{
|
106
107
|
def ==(other)
|
107
|
-
other ? @#{klass.primary_key.symbol} == other.#{klass.primary_key.symbol} : false
|
108
|
+
other.instance_of?(#{klass}) ? @#{klass.primary_key.symbol} == other.#{klass.primary_key.symbol} : false
|
108
109
|
end
|
109
110
|
}
|
110
111
|
|
data/lib/og/store.rb
CHANGED
@@ -18,12 +18,9 @@ class Store
|
|
18
18
|
|
19
19
|
def self.for_name(name)
|
20
20
|
Logger.info "Og uses the #{name.to_s.capitalize} store."
|
21
|
-
|
22
21
|
# gmosx: to keep RDoc happy.
|
23
|
-
|
24
|
-
|
25
|
-
return #{name.to_s.capitalize}Store
|
26
|
-
}
|
22
|
+
require('og/store/' + name.to_s)
|
23
|
+
return Og.const_get("#{name.to_s.capitalize}Store")
|
27
24
|
end
|
28
25
|
|
29
26
|
# Creates a store.
|
@@ -192,10 +189,8 @@ class Store
|
|
192
189
|
yield(self)
|
193
190
|
commit
|
194
191
|
rescue => ex
|
195
|
-
Logger.error 'Error in transaction'
|
196
|
-
Logger.error ex
|
197
|
-
Logger.error ex.backtrace
|
198
192
|
rollback
|
193
|
+
raise ex
|
199
194
|
end
|
200
195
|
end
|
201
196
|
|
@@ -218,3 +213,5 @@ private
|
|
218
213
|
end
|
219
214
|
|
220
215
|
end
|
216
|
+
|
217
|
+
# * George Moschovitis <gm@navel.gr>
|
data/lib/og/store/kirby.rb
CHANGED
@@ -34,6 +34,12 @@ class KirbyStore < SqlStore
|
|
34
34
|
|
35
35
|
def initialize(options)
|
36
36
|
super
|
37
|
+
|
38
|
+
@typemap = {
|
39
|
+
:Fixnum => :Integer,
|
40
|
+
:TrueClass => :Boolean
|
41
|
+
}
|
42
|
+
|
37
43
|
mode = options[:mode] || :local
|
38
44
|
|
39
45
|
if mode == :client
|
@@ -62,10 +68,14 @@ class KirbyStore < SqlStore
|
|
62
68
|
klass.send :alias_method, :recno, :oid
|
63
69
|
klass.send :alias_method, :recno=, :oid=
|
64
70
|
|
71
|
+
unless klass.properties.include? :recno
|
72
|
+
klass.property :recno, Fixnum
|
73
|
+
end
|
74
|
+
|
65
75
|
symbols = klass.properties.keys
|
66
76
|
|
67
77
|
klass.module_eval %{
|
68
|
-
def self.kb_create(
|
78
|
+
def self.kb_create(#{symbols.join(', ')})
|
69
79
|
obj = self.allocate
|
70
80
|
obj.recno = recno
|
71
81
|
#{ symbols.map { |s| "obj.#{s} = #{s}; "} }
|
@@ -158,29 +168,101 @@ class KirbyStore < SqlStore
|
|
158
168
|
# nop, not supported.
|
159
169
|
end
|
160
170
|
|
171
|
+
def join(obj1, obj2, table, options = nil)
|
172
|
+
first, second = join_object_ordering(obj1, obj2)
|
173
|
+
@conn.get_table(table.to_sym).insert(first.pk, second.pk)
|
174
|
+
end
|
175
|
+
|
176
|
+
def unjoin(obj1, obj2, table)
|
177
|
+
first, second = join_object_ordering(obj1, obj2)
|
178
|
+
|
179
|
+
@conn.get_table(table.to_sym).delete do |r|
|
180
|
+
require 'dev-utils/debug'
|
181
|
+
breakpoint
|
182
|
+
r.send(:first_key) == first.pk and
|
183
|
+
r.send(:second_key) == second.pk
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
161
187
|
private
|
162
188
|
|
189
|
+
def typemap(key)
|
190
|
+
@typemap[key] || key
|
191
|
+
end
|
192
|
+
|
163
193
|
def create_table(klass)
|
164
|
-
|
165
|
-
|
194
|
+
if @conn.table_exists?(klass.table.to_sym)
|
195
|
+
get_table(klass).pack # Kirby specific method of database cleanup.
|
196
|
+
|
197
|
+
field_names = field_names_for_class(klass)
|
198
|
+
actual_fields = get_table(klass).field_names
|
199
|
+
|
200
|
+
field_names.each do |needed_field|
|
201
|
+
next if actual_fields.include?(needed_field)
|
202
|
+
|
203
|
+
if @options[:evolve_schema] == true
|
204
|
+
Logger.debug "Adding field '#{needed_field}' to '#{klass.table}'"
|
205
|
+
field_type = typemap(klass.properties[needed_field].klass.name.to_sym)
|
206
|
+
if get_table(klass).respond_to?(:add_column)
|
207
|
+
get_table(klass).add_column(needed_field, field_type)
|
208
|
+
else
|
209
|
+
@conn.add_table_column(klass.table, needed_field, field_type)
|
210
|
+
end
|
211
|
+
else
|
212
|
+
Logger.warn "Table '#{klass.table}' is missing field '#{needed_field}' and :evolve_schema is not set to true!"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
actual_fields.each do |obsolete_field|
|
217
|
+
next if field_names.include?(obsolete_field)
|
218
|
+
|
219
|
+
if @options[:evolve_schema] == true and @options[:evolve_schema_cautious] == false
|
220
|
+
Logger.debug "Removing obsolete field '#{obsolete_field}' from '#{klass.table}'"
|
221
|
+
if get_table(klass).respond_to?(:drop_column)
|
222
|
+
get_table(klass).drop_column(obsolete_field)
|
223
|
+
else
|
224
|
+
@conn.drop_table_column(klass.table, obsolete_field)
|
225
|
+
end
|
226
|
+
else
|
227
|
+
Logger.warn "You have an obsolete field '#{obsolete_field}' on table '#{klass.table}' and :evolve_schema is not set or is in cautious mode!"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
else
|
231
|
+
Logger.debug "Creating table '#{klass.table}'"
|
232
|
+
fields = fields_for_class(klass)
|
166
233
|
table = @conn.create_table(klass.table.to_sym, *fields) do |t|
|
167
234
|
t.record_class = klass
|
168
235
|
end
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
236
|
+
end
|
237
|
+
|
238
|
+
=begin
|
239
|
+
# Create join tables if needed. Join tables are used in
|
240
|
+
# 'many_to_many' relations.
|
241
|
+
|
242
|
+
if join_tables = klass.ann.self[:join_tables]
|
243
|
+
for info in join_tables
|
244
|
+
unless @conn.table_exists?(info[:table].to_sym)
|
245
|
+
@conn.create_table(info[:table].to_sym, *create_join_table_sql(info))
|
246
|
+
Logger.debug "Created jointable '#{info[:table]}'."
|
247
|
+
end
|
176
248
|
end
|
177
249
|
end
|
250
|
+
=end
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
def create_join_table_sql(join_info)
|
255
|
+
[join_info[:first_key].to_sym, :Integer, join_info[:second_key].to_sym, :Integer]
|
178
256
|
end
|
179
257
|
|
180
258
|
def drop_table(klass)
|
181
259
|
@conn.drop_table(klass.table) if @conn.table_exists?(klass.table)
|
182
260
|
end
|
183
261
|
|
262
|
+
def field_names_for_class(klass)
|
263
|
+
klass.properties.values.map {|p| p.symbol }
|
264
|
+
end
|
265
|
+
|
184
266
|
def fields_for_class(klass)
|
185
267
|
fields = []
|
186
268
|
|
@@ -189,8 +271,7 @@ private
|
|
189
271
|
|
190
272
|
fields << p.symbol
|
191
273
|
|
192
|
-
type = p.klass.name.to_sym
|
193
|
-
type = :Integer if type == :Fixnum
|
274
|
+
type = typemap(p.klass.name.to_sym)
|
194
275
|
|
195
276
|
fields << type
|
196
277
|
end
|