sam-dm-core 0.9.6 → 0.9.7
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/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
|