dm-core 0.10.1 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +29 -0
- data/.document +5 -0
- data/.gitignore +27 -0
- data/LICENSE +20 -0
- data/{README.txt → README.rdoc} +14 -3
- data/Rakefile +23 -22
- data/VERSION +1 -0
- data/dm-core.gemspec +201 -10
- data/lib/dm-core.rb +32 -23
- data/lib/dm-core/adapters.rb +0 -1
- data/lib/dm-core/adapters/data_objects_adapter.rb +230 -151
- data/lib/dm-core/adapters/mysql_adapter.rb +7 -8
- data/lib/dm-core/adapters/oracle_adapter.rb +39 -59
- data/lib/dm-core/adapters/postgres_adapter.rb +0 -1
- data/lib/dm-core/adapters/sqlite3_adapter.rb +5 -0
- data/lib/dm-core/adapters/sqlserver_adapter.rb +114 -0
- data/lib/dm-core/adapters/yaml_adapter.rb +0 -5
- data/lib/dm-core/associations/many_to_many.rb +118 -56
- data/lib/dm-core/associations/many_to_one.rb +48 -21
- data/lib/dm-core/associations/one_to_many.rb +8 -30
- data/lib/dm-core/associations/one_to_one.rb +1 -5
- data/lib/dm-core/associations/relationship.rb +89 -97
- data/lib/dm-core/collection.rb +299 -184
- data/lib/dm-core/core_ext/enumerable.rb +28 -0
- data/lib/dm-core/core_ext/kernel.rb +0 -2
- data/lib/dm-core/migrations.rb +314 -170
- data/lib/dm-core/model.rb +97 -66
- data/lib/dm-core/model/descendant_set.rb +1 -1
- data/lib/dm-core/model/hook.rb +0 -3
- data/lib/dm-core/model/property.rb +7 -10
- data/lib/dm-core/model/relationship.rb +79 -26
- data/lib/dm-core/model/scope.rb +3 -4
- data/lib/dm-core/property.rb +152 -90
- data/lib/dm-core/property_set.rb +18 -37
- data/lib/dm-core/query.rb +452 -153
- data/lib/dm-core/query/conditions/comparison.rb +266 -173
- data/lib/dm-core/query/conditions/operation.rb +499 -57
- data/lib/dm-core/query/direction.rb +0 -3
- data/lib/dm-core/query/operator.rb +0 -4
- data/lib/dm-core/query/path.rb +10 -12
- data/lib/dm-core/query/sort.rb +4 -10
- data/lib/dm-core/repository.rb +10 -6
- data/lib/dm-core/resource.rb +343 -148
- data/lib/dm-core/spec/adapter_shared_spec.rb +17 -1
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +277 -17
- data/lib/dm-core/support/chainable.rb +0 -2
- data/lib/dm-core/support/equalizer.rb +27 -3
- data/lib/dm-core/transaction.rb +75 -75
- data/lib/dm-core/type.rb +19 -5
- data/lib/dm-core/types/discriminator.rb +4 -4
- data/lib/dm-core/types/object.rb +2 -7
- data/lib/dm-core/types/paranoid_boolean.rb +8 -2
- data/lib/dm-core/types/paranoid_datetime.rb +8 -2
- data/lib/dm-core/version.rb +1 -1
- data/script/performance.rb +7 -7
- data/script/profile.rb +6 -6
- data/spec/lib/collection_helpers.rb +2 -2
- data/spec/lib/pending_helpers.rb +22 -3
- data/spec/lib/rspec_immediate_feedback_formatter.rb +1 -0
- data/spec/public/associations/many_to_many_spec.rb +6 -4
- data/spec/public/associations/many_to_one_spec.rb +10 -1
- data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +39 -0
- data/spec/public/associations/one_to_many_spec.rb +4 -3
- data/spec/public/associations/one_to_one_spec.rb +19 -1
- data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +45 -0
- data/spec/public/collection_spec.rb +4 -3
- data/spec/public/migrations_spec.rb +144 -0
- data/spec/public/model/relationship_spec.rb +115 -55
- data/spec/public/model_spec.rb +13 -13
- data/spec/public/property/object_spec.rb +106 -0
- data/spec/public/property_spec.rb +18 -14
- data/spec/public/resource_spec.rb +10 -1
- data/spec/public/sel_spec.rb +16 -49
- data/spec/public/setup_spec.rb +1 -1
- data/spec/public/shared/association_collection_shared_spec.rb +6 -14
- data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
- data/spec/public/shared/collection_shared_spec.rb +214 -217
- data/spec/public/shared/finder_shared_spec.rb +259 -365
- data/spec/public/shared/resource_shared_spec.rb +524 -248
- data/spec/public/transaction_spec.rb +27 -3
- data/spec/public/types/discriminator_spec.rb +1 -1
- data/spec/rcov.opts +6 -0
- data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +17 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +3 -20
- data/spec/semipublic/associations_spec.rb +2 -2
- data/spec/semipublic/collection_spec.rb +0 -32
- data/spec/semipublic/model_spec.rb +96 -0
- data/spec/semipublic/property_spec.rb +3 -3
- data/spec/semipublic/query/conditions/comparison_spec.rb +1719 -0
- data/spec/semipublic/query/conditions/operation_spec.rb +1292 -0
- data/spec/semipublic/query_spec.rb +1285 -144
- data/spec/semipublic/resource_spec.rb +0 -24
- data/spec/semipublic/shared/resource_shared_spec.rb +103 -38
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +15 -6
- data/tasks/ci.rake +1 -0
- data/tasks/metrics.rake +37 -0
- data/tasks/spec.rake +41 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +99 -29
- data/CONTRIBUTING +0 -51
- data/FAQ +0 -93
- data/History.txt +0 -27
- data/MIT-LICENSE +0 -22
- data/Manifest.txt +0 -121
- data/QUICKLINKS +0 -11
- data/SPECS +0 -35
- data/TODO +0 -1
- data/spec/semipublic/query/conditions_spec.rb +0 -528
- data/tasks/ci.rb +0 -24
- data/tasks/dm.rb +0 -58
- data/tasks/doc.rb +0 -17
- data/tasks/gemspec.rb +0 -23
- data/tasks/hoe.rb +0 -45
- data/tasks/install.rb +0 -18
data/lib/dm-core/type.rb
CHANGED
@@ -84,20 +84,18 @@ module DataMapper
|
|
84
84
|
# end # module Types
|
85
85
|
# end # module DataMapper
|
86
86
|
class Type
|
87
|
-
|
88
87
|
# Until cooperation of Property and Type does not change, each must
|
89
88
|
# have a separate list of options, because plugins (ex.: dm-validations)
|
90
89
|
# may want to extend one or the other, and expects no side effects
|
91
90
|
PROPERTY_OPTIONS = [
|
92
91
|
:accessor, :reader, :writer,
|
93
|
-
:lazy, :default, :
|
92
|
+
:lazy, :default, :key, :serial, :field, :size, :length,
|
94
93
|
:format, :index, :unique_index, :auto_validation,
|
95
|
-
:validates, :unique, :precision, :scale, :min, :max
|
94
|
+
:validates, :unique, :precision, :scale, :min, :max,
|
95
|
+
:allow_nil, :allow_blank, :required
|
96
96
|
]
|
97
97
|
|
98
98
|
class << self
|
99
|
-
|
100
|
-
# TODO: document
|
101
99
|
# @api private
|
102
100
|
def configure(primitive_type, options)
|
103
101
|
warn "DataMapper.Type.configure is deprecated, specify the primitive and options explicitly (#{caller[0]})"
|
@@ -126,6 +124,16 @@ module DataMapper
|
|
126
124
|
def primitive(primitive = nil)
|
127
125
|
return @primitive if primitive.nil?
|
128
126
|
@primitive = primitive
|
127
|
+
|
128
|
+
return unless @primitive.respond_to?(:options)
|
129
|
+
options = @primitive.options
|
130
|
+
|
131
|
+
return unless options.respond_to?(:each)
|
132
|
+
|
133
|
+
# inherit the options from the primitive if any
|
134
|
+
options.each do |key, value|
|
135
|
+
send(key, value) unless send(key)
|
136
|
+
end
|
129
137
|
end
|
130
138
|
|
131
139
|
# Load Property options
|
@@ -141,6 +149,12 @@ module DataMapper
|
|
141
149
|
RUBY
|
142
150
|
end
|
143
151
|
|
152
|
+
def nullable(value)
|
153
|
+
# :required is preferable to :allow_nil, but :nullable maps precisely to :allow_nil
|
154
|
+
warn "#nullable is deprecated, use #required instead (#{caller[0]})"
|
155
|
+
allow_nil(value)
|
156
|
+
end
|
157
|
+
|
144
158
|
# Gives all the options set on this type
|
145
159
|
#
|
146
160
|
# @return [Hash] with all options and their values set on this type
|
@@ -3,15 +3,15 @@ module DataMapper
|
|
3
3
|
class Discriminator < Type
|
4
4
|
primitive Class
|
5
5
|
default lambda { |resource, property| resource.model }
|
6
|
-
|
6
|
+
required true
|
7
7
|
|
8
|
-
# TODO: document
|
9
8
|
# @api private
|
10
9
|
def self.bind(property)
|
11
10
|
repository_name = property.repository_name
|
12
11
|
model = property.model
|
12
|
+
property_name = property.name
|
13
13
|
|
14
|
-
model.default_scope(repository_name).update(
|
14
|
+
model.default_scope(repository_name).update(property_name => model.descendants)
|
15
15
|
|
16
16
|
model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
17
17
|
extend Chainable
|
@@ -38,7 +38,7 @@ module DataMapper
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def set_discriminator_scope_for(model)
|
41
|
-
model.default_scope(#{repository_name.inspect}).update(#{
|
41
|
+
model.default_scope(#{repository_name.inspect}).update(#{property_name.inspect} => model.descendants)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
RUBY
|
data/lib/dm-core/types/object.rb
CHANGED
@@ -1,23 +1,18 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module Types
|
3
3
|
class Object < Type
|
4
|
-
primitive
|
5
|
-
length 65535
|
6
|
-
lazy true
|
4
|
+
primitive Text
|
7
5
|
|
8
|
-
# TODO: document
|
9
6
|
# @api private
|
10
7
|
def self.typecast(value, property)
|
11
8
|
value
|
12
9
|
end
|
13
10
|
|
14
|
-
# TODO: document
|
15
11
|
# @api private
|
16
12
|
def self.dump(value, property)
|
17
|
-
[ Marshal.dump(value) ].pack('m')
|
13
|
+
[ Marshal.dump(value) ].pack('m') unless value.nil?
|
18
14
|
end
|
19
15
|
|
20
|
-
# TODO: document
|
21
16
|
# @api private
|
22
17
|
def self.load(value, property)
|
23
18
|
Marshal.load(value.unpack('m').first) unless value.nil?
|
@@ -5,7 +5,6 @@ module DataMapper
|
|
5
5
|
default false
|
6
6
|
lazy true
|
7
7
|
|
8
|
-
# TODO: document
|
9
8
|
# @api private
|
10
9
|
def self.bind(property)
|
11
10
|
repository_name = property.repository_name
|
@@ -22,10 +21,17 @@ module DataMapper
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def destroy
|
24
|
+
paranoid_destroy
|
25
|
+
end
|
26
|
+
|
27
|
+
def paranoid_destroy
|
25
28
|
self.class.paranoid_properties.each do |name, blk|
|
26
29
|
attribute_set(name, blk.call(self))
|
27
30
|
end
|
28
|
-
|
31
|
+
save_self
|
32
|
+
@_destroyed = true
|
33
|
+
@_readonly = true
|
34
|
+
reset
|
29
35
|
end
|
30
36
|
RUBY
|
31
37
|
|
@@ -4,7 +4,6 @@ module DataMapper
|
|
4
4
|
primitive DateTime
|
5
5
|
lazy true
|
6
6
|
|
7
|
-
# TODO: document
|
8
7
|
# @api private
|
9
8
|
def self.bind(property)
|
10
9
|
repository_name = property.repository_name
|
@@ -21,10 +20,17 @@ module DataMapper
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def destroy
|
23
|
+
paranoid_destroy
|
24
|
+
end
|
25
|
+
|
26
|
+
def paranoid_destroy
|
24
27
|
self.class.paranoid_properties.each do |name, blk|
|
25
28
|
attribute_set(name, blk.call(self))
|
26
29
|
end
|
27
|
-
|
30
|
+
save_self
|
31
|
+
@_destroyed = true
|
32
|
+
@_readonly = true
|
33
|
+
reset
|
28
34
|
end
|
29
35
|
RUBY
|
30
36
|
|
data/lib/dm-core/version.rb
CHANGED
data/script/performance.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
#!/usr/bin/env ruby -
|
1
|
+
#!/usr/bin/env ruby -Ku
|
2
2
|
|
3
3
|
require 'ftools'
|
4
4
|
require 'rubygems'
|
5
5
|
|
6
|
-
gem 'activerecord', '~>2.3.
|
7
|
-
gem 'addressable', '~>2.
|
8
|
-
gem 'faker', '~>0.3.1'
|
9
|
-
gem 'rbench', '~>0.2.3'
|
6
|
+
gem 'activerecord', '~> 2.3.4'
|
7
|
+
gem 'addressable', '~> 2.1'
|
8
|
+
gem 'faker', '~> 0.3.1'
|
9
|
+
gem 'rbench', '~> 0.2.3'
|
10
10
|
|
11
11
|
require 'active_record'
|
12
12
|
require 'addressable/uri'
|
@@ -144,13 +144,13 @@ else
|
|
144
144
|
|
145
145
|
if sqlfile
|
146
146
|
answer = nil
|
147
|
-
until answer && answer[
|
147
|
+
until answer && answer[/\A(?:y(?:es)?|no?)\b/i]
|
148
148
|
print('Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]');
|
149
149
|
STDOUT.flush
|
150
150
|
answer = gets
|
151
151
|
end
|
152
152
|
|
153
|
-
if
|
153
|
+
if %w[ y yes ].include?(answer.downcase)
|
154
154
|
File.makedirs(File.dirname(sqlfile))
|
155
155
|
#adapter.execute("SELECT * INTO OUTFILE '#{sqlfile}' FROM exhibits;")
|
156
156
|
`#{mysqldump_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} exhibits users > #{sqlfile}`
|
data/script/profile.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
#!/usr/bin/env ruby -
|
1
|
+
#!/usr/bin/env ruby -Ku
|
2
2
|
|
3
3
|
require 'ftools'
|
4
4
|
require 'rubygems'
|
5
5
|
|
6
|
-
gem 'addressable', '~>2.
|
7
|
-
gem 'faker', '~>0.3.1'
|
8
|
-
gem 'ruby-prof', '~>0.7.3'
|
6
|
+
gem 'addressable', '~> 2.1'
|
7
|
+
gem 'faker', '~> 0.3.1'
|
8
|
+
gem 'ruby-prof', '~> 0.7.3'
|
9
9
|
|
10
10
|
require 'addressable/uri'
|
11
11
|
require 'faker'
|
@@ -139,13 +139,13 @@ else
|
|
139
139
|
|
140
140
|
if sqlfile
|
141
141
|
answer = nil
|
142
|
-
until answer && answer[
|
142
|
+
until answer && answer[/\A(?:y(?:es)?|no?)\b/i]
|
143
143
|
print('Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]');
|
144
144
|
STDOUT.flush
|
145
145
|
answer = gets
|
146
146
|
end
|
147
147
|
|
148
|
-
if
|
148
|
+
if %w[ y yes ].include?(answer.downcase)
|
149
149
|
File.makedirs(File.dirname(sqlfile))
|
150
150
|
#adapter.execute("SELECT * INTO OUTFILE '#{sqlfile}' FROM exhibits;")
|
151
151
|
`#{mysqldump_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} exhibits users > #{sqlfile}`
|
@@ -6,10 +6,10 @@ module DataMapper::Spec
|
|
6
6
|
base.loaded = false
|
7
7
|
end
|
8
8
|
|
9
|
-
def should_not_be_a_kicker
|
9
|
+
def should_not_be_a_kicker(ivar = :@articles)
|
10
10
|
unless loaded
|
11
11
|
it 'should not be a kicker' do
|
12
|
-
|
12
|
+
instance_variable_get(ivar).should_not be_loaded
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/spec/lib/pending_helpers.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module DataMapper::Spec
|
2
2
|
module PendingHelpers
|
3
|
-
def pending_if(
|
3
|
+
def pending_if(*args)
|
4
|
+
message, boolean = parse_args(*args)
|
5
|
+
|
4
6
|
if boolean
|
5
7
|
pending(message) { yield }
|
6
8
|
else
|
@@ -8,7 +10,9 @@ module DataMapper::Spec
|
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
|
-
def rescue_if(
|
13
|
+
def rescue_if(*args)
|
14
|
+
message, boolean = parse_args(*args)
|
15
|
+
|
12
16
|
if boolean
|
13
17
|
raised = nil
|
14
18
|
begin
|
@@ -18,10 +22,25 @@ module DataMapper::Spec
|
|
18
22
|
raised = true
|
19
23
|
end
|
20
24
|
|
21
|
-
raise
|
25
|
+
raise "should have raised: #{message || 'TODO'}" if raised == false
|
22
26
|
else
|
23
27
|
yield
|
24
28
|
end
|
25
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse_args(*args)
|
34
|
+
case args.map { |arg| arg.class }
|
35
|
+
when [ String, TrueClass ], [ String, FalseClass ] then args
|
36
|
+
when [ String, NilClass ] then [ args.first, false ]
|
37
|
+
when [ String ] then [ args.first, true ]
|
38
|
+
when [ TrueClass ], [ FalseClass ] then [ '', args.first ]
|
39
|
+
when [ NilClass ] then [ '', false ]
|
40
|
+
when [] then [ '', true ] # defaults
|
41
|
+
else
|
42
|
+
raise ArgumentError, "Invalid arguments: #{args.inspect}"
|
43
|
+
end
|
44
|
+
end
|
26
45
|
end
|
27
46
|
end
|
@@ -40,12 +40,12 @@ end
|
|
40
40
|
include DataMapper::Resource
|
41
41
|
|
42
42
|
property :id, Serial
|
43
|
-
property :title, String, :
|
43
|
+
property :title, String, :required => true
|
44
44
|
property :content, Text
|
45
45
|
property :subtitle, String
|
46
46
|
|
47
47
|
has n, :authors, :through => Resource
|
48
|
-
belongs_to :original, self, :
|
48
|
+
belongs_to :original, self, :required => false
|
49
49
|
has n, :revisions, self, :child_key => [ :original_id ]
|
50
50
|
has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
|
51
51
|
has n, :publications, :through => Resource
|
@@ -94,6 +94,7 @@ end
|
|
94
94
|
it_should_behave_like 'A public Association Collection'
|
95
95
|
it_should_behave_like 'A Collection supporting Strategic Eager Loading' unless loaded
|
96
96
|
it_should_behave_like 'Finder Interface'
|
97
|
+
it_should_behave_like 'Collection Finder Interface'
|
97
98
|
it_should_behave_like 'A Limited Many to Many Collection'
|
98
99
|
end
|
99
100
|
end
|
@@ -129,7 +130,7 @@ end
|
|
129
130
|
include DataMapper::Resource
|
130
131
|
|
131
132
|
property :id, Serial
|
132
|
-
property :title, String, :
|
133
|
+
property :title, String, :required => true
|
133
134
|
property :content, Text
|
134
135
|
property :subtitle, String
|
135
136
|
|
@@ -137,7 +138,7 @@ end
|
|
137
138
|
|
138
139
|
belongs_to :site
|
139
140
|
has n, :authors, :through => :site
|
140
|
-
belongs_to :original, self, :
|
141
|
+
belongs_to :original, self, :required => false
|
141
142
|
has n, :revisions, self, :child_key => [ :original_id ]
|
142
143
|
has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
|
143
144
|
has n, :publications, :through => Resource
|
@@ -187,6 +188,7 @@ end
|
|
187
188
|
it_should_behave_like 'A public Association Collection'
|
188
189
|
it_should_behave_like 'A Collection supporting Strategic Eager Loading' unless loaded
|
189
190
|
it_should_behave_like 'Finder Interface'
|
191
|
+
it_should_behave_like 'Collection Finder Interface'
|
190
192
|
it_should_behave_like 'A Limited Many to Many Collection'
|
191
193
|
end
|
192
194
|
end
|
@@ -12,7 +12,10 @@ describe 'Many to One Associations' do
|
|
12
12
|
property :description, Text
|
13
13
|
property :admin, Boolean, :accessor => :private
|
14
14
|
|
15
|
-
belongs_to :
|
15
|
+
belongs_to :parent, self, :required => false
|
16
|
+
has n, :children, self, :inverse => :parent
|
17
|
+
|
18
|
+
belongs_to :referrer, self, :required => false
|
16
19
|
has n, :comments
|
17
20
|
|
18
21
|
# FIXME: figure out a different approach than stubbing things out
|
@@ -51,6 +54,12 @@ describe 'Many to One Associations' do
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
class ::Default
|
58
|
+
include DataMapper::Resource
|
59
|
+
|
60
|
+
property :name, String, :key => true, :default => 'a default value'
|
61
|
+
end
|
62
|
+
|
54
63
|
@user_model = Blog::User
|
55
64
|
@author_model = Blog::Author
|
56
65
|
@comment_model = Blog::Comment
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
|
3
|
+
# TODO: combine this into many_to_one_spec.rb
|
4
|
+
|
5
|
+
describe 'Many to One Associations when foreign key is part of a composite key, with an integer and a boolean making up the composite key' do
|
6
|
+
before :all do
|
7
|
+
class ::ManyModel
|
8
|
+
include DataMapper::Resource
|
9
|
+
|
10
|
+
property :integer_key, Integer, :key => true
|
11
|
+
property :boolean_key, Boolean, :key => true
|
12
|
+
|
13
|
+
belongs_to :one_model, :child_key => [ :integer_key ]
|
14
|
+
end
|
15
|
+
|
16
|
+
class ::OneModel
|
17
|
+
include DataMapper::Resource
|
18
|
+
|
19
|
+
property :integer_key, Integer, :key => true
|
20
|
+
|
21
|
+
has n, :many_models, :child_key => [ :integer_key ]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
supported_by :all do
|
26
|
+
before :all do
|
27
|
+
@one = OneModel.create(:integer_key => 1)
|
28
|
+
@many = ManyModel.create(:integer_key => 1, :boolean_key => false)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should be able to access parent' do
|
32
|
+
@many.one_model.should == @one
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should be able to access the child' do
|
36
|
+
@one.many_models.should == [ @many ]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -23,12 +23,12 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_hel
|
|
23
23
|
include DataMapper::Resource
|
24
24
|
|
25
25
|
property :id, Serial
|
26
|
-
property :title, String, :
|
26
|
+
property :title, String, :required => true
|
27
27
|
property :content, Text
|
28
28
|
property :subtitle, String
|
29
29
|
|
30
|
-
belongs_to :author, :
|
31
|
-
belongs_to :original, self, :
|
30
|
+
belongs_to :author, :required => false
|
31
|
+
belongs_to :original, self, :required => false
|
32
32
|
has n, :revisions, self, :child_key => [ :original_id ]
|
33
33
|
has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
|
34
34
|
has n, :publications, :through => Resource
|
@@ -72,6 +72,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_hel
|
|
72
72
|
it_should_behave_like 'A public Association Collection'
|
73
73
|
it_should_behave_like 'A Collection supporting Strategic Eager Loading'
|
74
74
|
it_should_behave_like 'Finder Interface'
|
75
|
+
it_should_behave_like 'Collection Finder Interface'
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|