sam-dm-core 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +5 -0
- data/QUICKLINKS +1 -2
- data/Rakefile +3 -3
- data/SPECS +9 -10
- data/lib/dm-core.rb +15 -22
- data/lib/dm-core/adapters.rb +18 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +17 -10
- data/lib/dm-core/adapters/data_objects_adapter.rb +18 -16
- data/lib/dm-core/adapters/mysql_adapter.rb +1 -1
- data/lib/dm-core/adapters/postgres_adapter.rb +2 -2
- data/lib/dm-core/adapters/sqlite3_adapter.rb +1 -1
- data/lib/dm-core/associations.rb +3 -2
- data/lib/dm-core/associations/many_to_many.rb +2 -2
- data/lib/dm-core/associations/many_to_one.rb +1 -1
- data/lib/dm-core/associations/one_to_many.rb +13 -7
- data/lib/dm-core/associations/relationship.rb +20 -15
- data/lib/dm-core/auto_migrations.rb +4 -12
- data/lib/dm-core/collection.rb +9 -5
- data/lib/dm-core/dependency_queue.rb +2 -1
- data/lib/dm-core/identity_map.rb +3 -6
- data/lib/dm-core/model.rb +44 -27
- data/lib/dm-core/property.rb +3 -13
- data/lib/dm-core/property_set.rb +29 -22
- data/lib/dm-core/query.rb +49 -47
- data/lib/dm-core/repository.rb +3 -3
- data/lib/dm-core/resource.rb +12 -12
- data/lib/dm-core/scope.rb +7 -7
- data/lib/dm-core/support/kernel.rb +6 -2
- data/lib/dm-core/transaction.rb +7 -7
- data/lib/dm-core/version.rb +1 -1
- data/script/performance.rb +109 -30
- data/script/profile.rb +2 -2
- data/spec/integration/association_spec.rb +13 -1
- data/spec/integration/associations/one_to_many_spec.rb +40 -3
- data/spec/integration/auto_migrations_spec.rb +16 -1
- data/spec/integration/dependency_queue_spec.rb +0 -12
- data/spec/integration/postgres_adapter_spec.rb +1 -1
- data/spec/integration/property_spec.rb +4 -4
- data/spec/integration/resource_spec.rb +6 -0
- data/spec/integration/sti_spec.rb +22 -0
- data/spec/integration/strategic_eager_loading_spec.rb +21 -6
- data/spec/integration/type_spec.rb +1 -1
- data/spec/lib/model_loader.rb +10 -1
- data/spec/models/zoo.rb +1 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/unit/adapters/data_objects_adapter_spec.rb +3 -3
- data/spec/unit/associations/many_to_many_spec.rb +16 -1
- data/spec/unit/associations/many_to_one_spec.rb +9 -2
- data/spec/unit/model_spec.rb +12 -30
- data/spec/unit/property_set_spec.rb +8 -1
- data/spec/unit/query_spec.rb +41 -0
- data/spec/unit/resource_spec.rb +27 -4
- data/spec/unit/transaction_spec.rb +13 -13
- data/tasks/ci.rb +4 -36
- data/tasks/dm.rb +3 -3
- metadata +7 -16
@@ -74,25 +74,29 @@ module DataMapper
|
|
74
74
|
|
75
75
|
# @api private
|
76
76
|
def get_children(parent, options = {}, finder = :all, *args)
|
77
|
-
|
78
|
-
|
77
|
+
parent_value = parent_key.get(parent)
|
78
|
+
bind_values = [ parent_value ]
|
79
79
|
|
80
80
|
with_repository(child_model) do |r|
|
81
81
|
parent_identity_map = parent.repository.identity_map(parent_model)
|
82
82
|
child_identity_map = r.identity_map(child_model)
|
83
83
|
|
84
|
-
query_values = parent_identity_map.keys
|
85
|
-
query_values.reject! { |k| child_identity_map[
|
84
|
+
query_values = parent_identity_map.keys
|
85
|
+
query_values.reject! { |k| child_identity_map[k] }
|
86
86
|
|
87
87
|
bind_values = query_values unless query_values.empty?
|
88
|
-
query = child_key.
|
88
|
+
query = child_key.zip(bind_values.transpose).to_hash
|
89
89
|
|
90
90
|
collection = child_model.send(finder, *(args.dup << @query.merge(options).merge(query)))
|
91
|
+
|
91
92
|
return collection unless collection.kind_of?(Collection) && collection.any?
|
92
93
|
|
93
|
-
grouped_collection =
|
94
|
+
grouped_collection = {}
|
94
95
|
collection.each do |resource|
|
95
|
-
|
96
|
+
child_value = child_key.get(resource)
|
97
|
+
parent_obj = parent_identity_map[child_value]
|
98
|
+
grouped_collection[parent_obj] ||= []
|
99
|
+
grouped_collection[parent_obj] << resource
|
96
100
|
end
|
97
101
|
|
98
102
|
association_accessor = "#{self.name}_association"
|
@@ -112,14 +116,14 @@ module DataMapper
|
|
112
116
|
parents_children = Collection.new(query)
|
113
117
|
children.each { |child| parents_children.send(:add, child) }
|
114
118
|
|
115
|
-
if parent_key.get(parent) ==
|
119
|
+
if parent_key.get(parent) == parent_value
|
116
120
|
ret = parents_children
|
117
121
|
else
|
118
122
|
association.instance_variable_set(:@children, parents_children)
|
119
123
|
end
|
120
124
|
end
|
121
125
|
|
122
|
-
ret || child_model.send(finder, *(args.dup << @query.merge(options).merge(child_key.zip(
|
126
|
+
ret || child_model.send(finder, *(args.dup << @query.merge(options).merge(child_key.zip([ parent_value ]).to_hash)))
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
@@ -129,14 +133,15 @@ module DataMapper
|
|
129
133
|
return nil unless child_value.nitems == child_value.size
|
130
134
|
|
131
135
|
with_repository(parent || parent_model) do
|
132
|
-
parent_identity_map = (parent || parent_model).repository.identity_map(parent_model)
|
133
|
-
child_identity_map = child.repository.identity_map(child_model)
|
136
|
+
parent_identity_map = (parent || parent_model).repository.identity_map(parent_model.base_model)
|
137
|
+
child_identity_map = child.repository.identity_map(child_model.base_model)
|
134
138
|
|
135
139
|
if parent = parent_identity_map[child_value]
|
136
140
|
return parent
|
137
141
|
end
|
138
142
|
|
139
|
-
children = child_identity_map.values
|
143
|
+
children = child_identity_map.values
|
144
|
+
children << child unless child_identity_map[child.key]
|
140
145
|
|
141
146
|
bind_values = children.map { |c| child_key.get(c) }.uniq
|
142
147
|
query_values = bind_values.reject { |k| parent_identity_map[k] }
|
@@ -157,14 +162,14 @@ module DataMapper
|
|
157
162
|
end
|
158
163
|
|
159
164
|
# @api private
|
160
|
-
def with_repository(object = nil
|
165
|
+
def with_repository(object = nil)
|
161
166
|
other_model = object.model == child_model ? parent_model : child_model if object.respond_to?(:model)
|
162
167
|
other_model = object == child_model ? parent_model : child_model if object.kind_of?(DataMapper::Resource)
|
163
168
|
|
164
169
|
if other_model && other_model.repository == object.repository && object.repository.name != @repository_name
|
165
|
-
object.repository.scope(
|
170
|
+
object.repository.scope { |block_args| yield(*block_args) }
|
166
171
|
else
|
167
|
-
repository(@repository_name
|
172
|
+
repository(@repository_name) { |block_args| yield(*block_args) }
|
168
173
|
end
|
169
174
|
end
|
170
175
|
|
@@ -73,12 +73,8 @@ module DataMapper
|
|
73
73
|
# @api private
|
74
74
|
def auto_migrate_down!(repository_name = self.repository_name)
|
75
75
|
# repository_name ||= default_repository_name
|
76
|
-
|
77
|
-
|
78
|
-
else
|
79
|
-
repository(repository_name) do |r|
|
80
|
-
r.adapter.destroy_model_storage(r, self)
|
81
|
-
end
|
76
|
+
repository(repository_name) do |r|
|
77
|
+
r.adapter.destroy_model_storage(r, self.base_model)
|
82
78
|
end
|
83
79
|
end
|
84
80
|
|
@@ -88,12 +84,8 @@ module DataMapper
|
|
88
84
|
# @param Symbol repository_name the repository to be migrated
|
89
85
|
# @api private
|
90
86
|
def auto_migrate_up!(repository_name = self.repository_name)
|
91
|
-
|
92
|
-
|
93
|
-
else
|
94
|
-
repository(repository_name) do |r|
|
95
|
-
r.adapter.create_model_storage(r, self)
|
96
|
-
end
|
87
|
+
repository(repository_name) do |r|
|
88
|
+
r.adapter.create_model_storage(r, self.base_model)
|
97
89
|
end
|
98
90
|
end
|
99
91
|
|
data/lib/dm-core/collection.rb
CHANGED
@@ -52,8 +52,9 @@ module DataMapper
|
|
52
52
|
def get(*key)
|
53
53
|
key = model.typecast_key(key)
|
54
54
|
if loaded?
|
55
|
-
#
|
56
|
-
|
55
|
+
# find indexed resource (create index first if it does not exist)
|
56
|
+
each {|r| @cache[r.key] = r } if @cache.empty?
|
57
|
+
@cache[key]
|
57
58
|
elsif query.limit || query.offset > 0
|
58
59
|
# current query is exclusive, find resource within the set
|
59
60
|
|
@@ -167,7 +168,7 @@ module DataMapper
|
|
167
168
|
end
|
168
169
|
|
169
170
|
##
|
170
|
-
# Simulates Array#at and returns the
|
171
|
+
# Simulates Array#at and returns the entry at that index.
|
171
172
|
# Also accepts negative indexes and appropriate reverses
|
172
173
|
# the order of the query
|
173
174
|
#
|
@@ -295,7 +296,7 @@ module DataMapper
|
|
295
296
|
# @see Array#delete
|
296
297
|
#
|
297
298
|
# @api public
|
298
|
-
def delete(resource
|
299
|
+
def delete(resource)
|
299
300
|
orphan_resource(super)
|
300
301
|
end
|
301
302
|
|
@@ -515,6 +516,7 @@ module DataMapper
|
|
515
516
|
|
516
517
|
@query = query
|
517
518
|
@key_properties = model.key(repository.name)
|
519
|
+
@cache = {}
|
518
520
|
|
519
521
|
super()
|
520
522
|
|
@@ -533,6 +535,7 @@ module DataMapper
|
|
533
535
|
def relate_resource(resource)
|
534
536
|
return unless resource
|
535
537
|
resource.collection = self
|
538
|
+
@cache[resource.key] = resource
|
536
539
|
resource
|
537
540
|
end
|
538
541
|
|
@@ -540,7 +543,8 @@ module DataMapper
|
|
540
543
|
# @api private
|
541
544
|
def orphan_resource(resource)
|
542
545
|
return unless resource
|
543
|
-
resource.collection = nil if resource.collection == self
|
546
|
+
resource.collection = nil if resource.collection.object_id == self.object_id
|
547
|
+
@cache.delete(resource.key)
|
544
548
|
resource
|
545
549
|
end
|
546
550
|
|
@@ -6,10 +6,11 @@ module DataMapper
|
|
6
6
|
#
|
7
7
|
class DependencyQueue
|
8
8
|
def initialize
|
9
|
-
@dependencies =
|
9
|
+
@dependencies = {}
|
10
10
|
end
|
11
11
|
|
12
12
|
def add(class_name, &callback)
|
13
|
+
@dependencies[class_name] ||= []
|
13
14
|
@dependencies[class_name] << callback
|
14
15
|
resolve!
|
15
16
|
end
|
data/lib/dm-core/identity_map.rb
CHANGED
@@ -5,7 +5,7 @@ module DataMapper
|
|
5
5
|
class IdentityMap
|
6
6
|
# Get a resource from the IdentityMap
|
7
7
|
def get(key)
|
8
|
-
@cache[key]
|
8
|
+
@cache[key] || (@second_level_cache && @second_level_cache.get(key))
|
9
9
|
end
|
10
10
|
|
11
11
|
alias [] get
|
@@ -27,11 +27,8 @@ module DataMapper
|
|
27
27
|
private
|
28
28
|
|
29
29
|
def initialize(second_level_cache = nil)
|
30
|
-
@cache =
|
31
|
-
|
32
|
-
else
|
33
|
-
Hash.new
|
34
|
-
end
|
30
|
+
@cache = {}
|
31
|
+
@second_level_cache = second_level_cache
|
35
32
|
end
|
36
33
|
|
37
34
|
def cache
|
data/lib/dm-core/model.rb
CHANGED
@@ -29,15 +29,15 @@ module DataMapper
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.extended(model)
|
32
|
-
model.instance_variable_set(:@storage_names,
|
33
|
-
model.instance_variable_set(:@properties,
|
34
|
-
model.instance_variable_set(:@field_naming_conventions,
|
32
|
+
model.instance_variable_set(:@storage_names, {})
|
33
|
+
model.instance_variable_set(:@properties, {})
|
34
|
+
model.instance_variable_set(:@field_naming_conventions, {})
|
35
35
|
extra_extensions.each { |extension| model.extend(extension) }
|
36
36
|
end
|
37
37
|
|
38
38
|
def inherited(target)
|
39
39
|
target.instance_variable_set(:@storage_names, @storage_names.dup)
|
40
|
-
target.instance_variable_set(:@properties,
|
40
|
+
target.instance_variable_set(:@properties, {})
|
41
41
|
target.instance_variable_set(:@base_model, self.base_model)
|
42
42
|
target.instance_variable_set(:@paranoid_properties, @paranoid_properties)
|
43
43
|
target.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
|
@@ -58,12 +58,13 @@ module DataMapper
|
|
58
58
|
end
|
59
59
|
|
60
60
|
if @relationships
|
61
|
-
duped_relationships =
|
61
|
+
duped_relationships = {}
|
62
62
|
@relationships.each do |repository_name,relationships|
|
63
63
|
relationships.each do |name, relationship|
|
64
64
|
dup = relationship.dup
|
65
65
|
dup.instance_variable_set(:@child_model, target) if dup.instance_variable_get(:@child_model) == self
|
66
66
|
dup.instance_variable_set(:@parent_model, target) if dup.instance_variable_get(:@parent_model) == self
|
67
|
+
duped_relationships[repository_name] ||= {}
|
67
68
|
duped_relationships[repository_name][name] = dup
|
68
69
|
end
|
69
70
|
end
|
@@ -102,13 +103,17 @@ module DataMapper
|
|
102
103
|
# if given a block, otherwise the requested repository.
|
103
104
|
#-
|
104
105
|
# @api public
|
105
|
-
def repository(name = nil
|
106
|
+
def repository(name = nil)
|
106
107
|
#
|
107
108
|
# There has been a couple of different strategies here, but me (zond) and dkubb are at least
|
108
109
|
# united in the concept of explicitness over implicitness. That is - the explicit wish of the
|
109
110
|
# caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last).
|
110
111
|
#
|
111
|
-
|
112
|
+
if block_given?
|
113
|
+
DataMapper.repository(name || repository_name) { |*block_args| yield(*block_args) }
|
114
|
+
else
|
115
|
+
DataMapper.repository(name || repository_name)
|
116
|
+
end
|
112
117
|
end
|
113
118
|
|
114
119
|
##
|
@@ -116,7 +121,7 @@ module DataMapper
|
|
116
121
|
#
|
117
122
|
# @return <String> the storage name (IE table name, for database stores) associated with this resource in the given repository
|
118
123
|
def storage_name(repository_name = default_repository_name)
|
119
|
-
@storage_names[repository_name]
|
124
|
+
@storage_names[repository_name] ||= repository(repository_name).adapter.resource_naming_convention.call(base_model.send(:default_storage_name))
|
120
125
|
end
|
121
126
|
|
122
127
|
##
|
@@ -130,9 +135,9 @@ module DataMapper
|
|
130
135
|
##
|
131
136
|
# The field naming conventions for this resource across all repositories.
|
132
137
|
#
|
133
|
-
# @return <
|
134
|
-
def
|
135
|
-
@field_naming_conventions
|
138
|
+
# @return <String> The naming convention for the given repository
|
139
|
+
def field_naming_convention(repository_name = default_storage_name)
|
140
|
+
@field_naming_conventions[repository_name] ||= repository(repository_name).adapter.field_naming_convention
|
136
141
|
end
|
137
142
|
|
138
143
|
##
|
@@ -148,7 +153,8 @@ module DataMapper
|
|
148
153
|
create_property_getter(property)
|
149
154
|
create_property_setter(property)
|
150
155
|
|
151
|
-
|
156
|
+
properties(repository_name)[property.name] = property
|
157
|
+
@_valid_relations = false
|
152
158
|
|
153
159
|
# Add property to the other mappings as well if this is for the default
|
154
160
|
# repository.
|
@@ -168,7 +174,7 @@ module DataMapper
|
|
168
174
|
context = :default if context == true
|
169
175
|
|
170
176
|
Array(context).each do |item|
|
171
|
-
|
177
|
+
properties(repository_name).lazy_context(item) << name
|
172
178
|
end
|
173
179
|
end
|
174
180
|
|
@@ -190,11 +196,25 @@ module DataMapper
|
|
190
196
|
end
|
191
197
|
|
192
198
|
def properties(repository_name = default_repository_name)
|
193
|
-
|
199
|
+
# We need to check whether all relations are already set up.
|
200
|
+
# If this isn't the case, we try to reload them here
|
201
|
+
if !@_valid_relations && respond_to?(:many_to_one_relationships)
|
202
|
+
@_valid_relations = true
|
203
|
+
begin
|
204
|
+
many_to_one_relationships.each do |r|
|
205
|
+
r.child_key
|
206
|
+
end
|
207
|
+
rescue NameError
|
208
|
+
# Apparently not all relations are loaded,
|
209
|
+
# so we will try again later on
|
210
|
+
@_valid_relations = false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
@properties[repository_name] ||= repository_name == Repository.default_name ? PropertySet.new : properties(Repository.default_name).dup
|
194
214
|
end
|
195
215
|
|
196
216
|
def eager_properties(repository_name = default_repository_name)
|
197
|
-
|
217
|
+
properties(repository_name).defaults
|
198
218
|
end
|
199
219
|
|
200
220
|
# @api private
|
@@ -211,15 +231,12 @@ module DataMapper
|
|
211
231
|
end
|
212
232
|
|
213
233
|
def key(repository_name = default_repository_name)
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
def inheritance_property(repository_name = default_repository_name)
|
218
|
-
@properties[repository_name].inheritance_property
|
234
|
+
properties(repository_name).key
|
219
235
|
end
|
220
236
|
|
221
237
|
def default_order(repository_name = default_repository_name)
|
222
|
-
|
238
|
+
@default_order ||= {}
|
239
|
+
@default_order[repository_name] ||= key(repository_name).map { |property| Query::Direction.new(property) }
|
223
240
|
end
|
224
241
|
|
225
242
|
def get(*key)
|
@@ -292,8 +309,8 @@ module DataMapper
|
|
292
309
|
# TODO SPEC
|
293
310
|
def copy(source, destination, query = {})
|
294
311
|
repository(destination) do
|
295
|
-
repository(source).read_many(query).each do |resource|
|
296
|
-
self.create(resource)
|
312
|
+
repository(source).read_many(scoped_query(query)).each do |resource|
|
313
|
+
self.create(resource.attributes)
|
297
314
|
end
|
298
315
|
end
|
299
316
|
end
|
@@ -304,7 +321,7 @@ module DataMapper
|
|
304
321
|
repository = query.repository
|
305
322
|
model = self
|
306
323
|
|
307
|
-
if inheritance_property_index = query.inheritance_property_index
|
324
|
+
if inheritance_property_index = query.inheritance_property_index
|
308
325
|
model = values.at(inheritance_property_index) || model
|
309
326
|
end
|
310
327
|
|
@@ -345,7 +362,7 @@ module DataMapper
|
|
345
362
|
|
346
363
|
# TODO: spec this
|
347
364
|
def to_query(repository, key, query = {})
|
348
|
-
conditions = Hash[ *self.key(
|
365
|
+
conditions = Hash[ *self.key(repository.name).zip(key).flatten ]
|
349
366
|
Query.new(repository, self, query.merge(conditions))
|
350
367
|
end
|
351
368
|
|
@@ -451,8 +468,8 @@ module DataMapper
|
|
451
468
|
# @api public
|
452
469
|
#
|
453
470
|
# TODO: move to dm-more/dm-transactions
|
454
|
-
def transaction
|
455
|
-
DataMapper::Transaction.new(self
|
471
|
+
def transaction
|
472
|
+
DataMapper::Transaction.new(self) { |block_args| yield(*block_args) }
|
456
473
|
end
|
457
474
|
end # module Transaction
|
458
475
|
|
data/lib/dm-core/property.rb
CHANGED
@@ -302,7 +302,7 @@ module DataMapper
|
|
302
302
|
# -
|
303
303
|
# @api semi-public
|
304
304
|
def field(repository_name = nil)
|
305
|
-
@field
|
305
|
+
@field || @fields[repository_name] ||= self.model.field_naming_convention(repository_name).call(self)
|
306
306
|
end
|
307
307
|
|
308
308
|
def unique
|
@@ -432,13 +432,6 @@ module DataMapper
|
|
432
432
|
new_value = typecast(value)
|
433
433
|
old_value = get!(resource)
|
434
434
|
|
435
|
-
# skip setting the property if the new value is equal
|
436
|
-
# to the old value, and the old value was defined
|
437
|
-
# ---
|
438
|
-
# [YK] Why bother? Does this change the result at all?
|
439
|
-
# ---
|
440
|
-
# return if new_value == old_value && resource.attribute_loaded?(name)
|
441
|
-
|
442
435
|
set_original_value(resource, old_value)
|
443
436
|
|
444
437
|
set!(resource, new_value)
|
@@ -458,7 +451,7 @@ module DataMapper
|
|
458
451
|
# If we're trying to load a lazy property, load it. Otherwise, lazy-load
|
459
452
|
# any properties that should be eager-loaded but were not included
|
460
453
|
# in the original :fields list
|
461
|
-
contexts = lazy? ? name : model.eager_properties(resource.repository.name)
|
454
|
+
contexts = lazy? ? name : model.eager_properties(resource.repository.name)
|
462
455
|
resource.send(:lazy_load, contexts)
|
463
456
|
end
|
464
457
|
|
@@ -565,6 +558,7 @@ module DataMapper
|
|
565
558
|
@index = @options.fetch(:index, false)
|
566
559
|
@unique_index = @options.fetch(:unique_index, false)
|
567
560
|
@lazy = @options.fetch(:lazy, @type.respond_to?(:lazy) ? @type.lazy : false) && !@key
|
561
|
+
@fields = {}
|
568
562
|
|
569
563
|
@track = @options.fetch(:track) do
|
570
564
|
if @custom && @type.respond_to?(:track) && @type.track
|
@@ -605,10 +599,6 @@ module DataMapper
|
|
605
599
|
@model.property_serialization_setup(self) if @model.respond_to?(:property_serialization_setup)
|
606
600
|
end
|
607
601
|
|
608
|
-
def fields
|
609
|
-
@fields ||= Hash.new { |h,k| h[k] = self.model.field_naming_conventions[k].call(self) }
|
610
|
-
end
|
611
|
-
|
612
602
|
def determine_visibility # :nodoc:
|
613
603
|
@reader_visibility = @options[:reader] || @options[:accessor] || :public
|
614
604
|
@writer_visibility = @options[:writer] || @options[:accessor] || :public
|
data/lib/dm-core/property_set.rb
CHANGED
@@ -4,10 +4,11 @@ module DataMapper
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
def [](name)
|
7
|
-
|
7
|
+
property_for(name) || raise(ArgumentError, "Unknown property '#{name}'", caller)
|
8
8
|
end
|
9
9
|
|
10
10
|
def []=(name, property)
|
11
|
+
@key, @defaults = nil
|
11
12
|
if existing_property = detect { |p| p.name == name }
|
12
13
|
property.hash
|
13
14
|
@entries[@entries.index(existing_property)] = property
|
@@ -18,14 +19,23 @@ module DataMapper
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def has_property?(name)
|
21
|
-
|
22
|
+
!!property_for(name)
|
22
23
|
end
|
23
24
|
|
24
25
|
def slice(*names)
|
25
|
-
@
|
26
|
+
@key, @defaults = nil
|
27
|
+
names.map do |name|
|
28
|
+
property_for(name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear
|
33
|
+
@key, @defaults = nil
|
34
|
+
@entries.clear
|
26
35
|
end
|
27
36
|
|
28
37
|
def add(*properties)
|
38
|
+
@key, @defaults = nil
|
29
39
|
@entries.push(*properties)
|
30
40
|
properties.each { |property| property.hash }
|
31
41
|
self
|
@@ -47,11 +57,11 @@ module DataMapper
|
|
47
57
|
end
|
48
58
|
|
49
59
|
def defaults
|
50
|
-
reject { |property| property.lazy? }
|
60
|
+
@defaults ||= reject { |property| property.lazy? }
|
51
61
|
end
|
52
62
|
|
53
63
|
def key
|
54
|
-
select { |property| property.key? }
|
64
|
+
@key ||= select { |property| property.key? }
|
55
65
|
end
|
56
66
|
|
57
67
|
def indexes
|
@@ -68,10 +78,6 @@ module DataMapper
|
|
68
78
|
index_hash
|
69
79
|
end
|
70
80
|
|
71
|
-
def inheritance_property
|
72
|
-
detect { |property| property.type == DataMapper::Types::Discriminator }
|
73
|
-
end
|
74
|
-
|
75
81
|
def get(resource)
|
76
82
|
map { |property| property.get(resource) }
|
77
83
|
end
|
@@ -93,7 +99,7 @@ module DataMapper
|
|
93
99
|
end
|
94
100
|
|
95
101
|
def lazy_context(name)
|
96
|
-
lazy_contexts[name]
|
102
|
+
lazy_contexts[name] ||= []
|
97
103
|
end
|
98
104
|
|
99
105
|
def lazy_load_context(names)
|
@@ -128,25 +134,17 @@ module DataMapper
|
|
128
134
|
assert_kind_of 'properties', properties, Enumerable
|
129
135
|
|
130
136
|
@entries = properties
|
131
|
-
@property_for =
|
137
|
+
@property_for = {}
|
132
138
|
end
|
133
139
|
|
134
140
|
def initialize_copy(orig)
|
141
|
+
@key, @defaults = nil
|
135
142
|
@entries = orig.entries.dup
|
136
|
-
@property_for =
|
137
|
-
end
|
138
|
-
|
139
|
-
def hash_for_property_for
|
140
|
-
Hash.new do |h,k|
|
141
|
-
ksym = k.to_sym
|
142
|
-
if property = detect { |property| property.name == ksym }
|
143
|
-
h[ksym] = h[k.to_s] = property
|
144
|
-
end
|
145
|
-
end
|
143
|
+
@property_for = {}
|
146
144
|
end
|
147
145
|
|
148
146
|
def lazy_contexts
|
149
|
-
@lazy_contexts ||=
|
147
|
+
@lazy_contexts ||= {}
|
150
148
|
end
|
151
149
|
|
152
150
|
def parse_index(index, property, index_hash)
|
@@ -158,5 +156,14 @@ module DataMapper
|
|
158
156
|
when Enumerable then index.each { |idx| parse_index(idx, property, index_hash) }
|
159
157
|
end
|
160
158
|
end
|
159
|
+
|
160
|
+
def property_for(name)
|
161
|
+
unless @property_for[name]
|
162
|
+
property = detect { |property| property.name == name.to_sym }
|
163
|
+
@property_for[name.to_s] = @property_for[name.to_sym] = property if property
|
164
|
+
end
|
165
|
+
@property_for[name]
|
166
|
+
end
|
167
|
+
|
161
168
|
end # class PropertySet
|
162
169
|
end # module DataMapper
|