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