dm-core 0.9.2 → 0.9.3
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/.autotest +26 -0
- data/{CHANGELOG → History.txt} +78 -77
- data/Manifest.txt +123 -0
- data/{README → README.txt} +0 -0
- data/Rakefile +29 -0
- data/SPECS +63 -0
- data/TODO +1 -0
- data/lib/dm-core.rb +6 -1
- data/lib/dm-core/adapters/data_objects_adapter.rb +29 -32
- data/lib/dm-core/adapters/mysql_adapter.rb +1 -1
- data/lib/dm-core/adapters/postgres_adapter.rb +1 -1
- data/lib/dm-core/adapters/sqlite3_adapter.rb +2 -2
- data/lib/dm-core/associations.rb +26 -0
- data/lib/dm-core/associations/many_to_many.rb +34 -25
- data/lib/dm-core/associations/many_to_one.rb +4 -4
- data/lib/dm-core/associations/one_to_many.rb +48 -13
- data/lib/dm-core/associations/one_to_one.rb +4 -4
- data/lib/dm-core/associations/relationship.rb +144 -42
- data/lib/dm-core/associations/relationship_chain.rb +31 -24
- data/lib/dm-core/auto_migrations.rb +0 -4
- data/lib/dm-core/collection.rb +40 -7
- data/lib/dm-core/dependency_queue.rb +31 -0
- data/lib/dm-core/hook.rb +2 -2
- data/lib/dm-core/is.rb +2 -2
- data/lib/dm-core/logger.rb +10 -10
- data/lib/dm-core/model.rb +94 -41
- data/lib/dm-core/property.rb +72 -41
- data/lib/dm-core/property_set.rb +8 -14
- data/lib/dm-core/query.rb +34 -9
- data/lib/dm-core/repository.rb +0 -0
- data/lib/dm-core/resource.rb +13 -13
- data/lib/dm-core/scope.rb +25 -2
- data/lib/dm-core/type.rb +3 -3
- data/lib/dm-core/types/discriminator.rb +10 -8
- data/lib/dm-core/types/object.rb +4 -0
- data/lib/dm-core/types/paranoid_boolean.rb +15 -4
- data/lib/dm-core/types/paranoid_datetime.rb +15 -4
- data/lib/dm-core/version.rb +3 -0
- data/script/all +5 -0
- data/script/performance.rb +191 -0
- data/script/profile.rb +86 -0
- data/spec/integration/association_spec.rb +288 -204
- data/spec/integration/association_through_spec.rb +9 -3
- data/spec/integration/associations/many_to_many_spec.rb +97 -31
- data/spec/integration/associations/many_to_one_spec.rb +41 -6
- data/spec/integration/associations/one_to_many_spec.rb +18 -2
- data/spec/integration/auto_migrations_spec.rb +0 -0
- data/spec/integration/collection_spec.rb +89 -42
- data/spec/integration/dependency_queue_spec.rb +58 -0
- data/spec/integration/model_spec.rb +67 -8
- data/spec/integration/postgres_adapter_spec.rb +19 -20
- data/spec/integration/property_spec.rb +17 -8
- data/spec/integration/query_spec.rb +273 -191
- data/spec/integration/resource_spec.rb +108 -10
- data/spec/integration/strategic_eager_loading_spec.rb +138 -0
- data/spec/integration/transaction_spec.rb +3 -3
- data/spec/integration/type_spec.rb +121 -0
- data/spec/lib/logging_helper.rb +18 -0
- data/spec/lib/model_loader.rb +91 -0
- data/spec/lib/publicize_methods.rb +28 -0
- data/spec/models/vehicles.rb +34 -0
- data/spec/models/zoo.rb +48 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +25 -62
- data/spec/unit/adapters/data_objects_adapter_spec.rb +1 -0
- data/spec/unit/associations/many_to_many_spec.rb +3 -0
- data/spec/unit/associations/many_to_one_spec.rb +9 -1
- data/spec/unit/associations/one_to_many_spec.rb +12 -4
- data/spec/unit/associations/relationship_spec.rb +19 -15
- data/spec/unit/associations_spec.rb +37 -0
- data/spec/unit/collection_spec.rb +8 -0
- data/spec/unit/data_mapper_spec.rb +14 -0
- data/spec/unit/model_spec.rb +2 -2
- data/spec/unit/property_set_spec.rb +0 -13
- data/spec/unit/property_spec.rb +92 -21
- data/spec/unit/query_spec.rb +49 -4
- data/spec/unit/resource_spec.rb +122 -60
- data/spec/unit/scope_spec.rb +11 -0
- data/tasks/ci.rb +68 -0
- data/tasks/dm.rb +63 -0
- data/tasks/doc.rb +20 -0
- data/tasks/hoe.rb +38 -0
- data/tasks/install.rb +20 -0
- metadata +63 -22
@@ -10,6 +10,7 @@ module DataMapper
|
|
10
10
|
undef_method :get_parent
|
11
11
|
undef_method :attach_parent
|
12
12
|
|
13
|
+
# @api private
|
13
14
|
def child_model
|
14
15
|
near_relationship.child_model
|
15
16
|
end
|
@@ -18,38 +19,19 @@ module DataMapper
|
|
18
19
|
def get_children(parent, options = {}, finder = :all, *args)
|
19
20
|
query = @query.merge(options).merge(child_key.to_query(parent_key.get(parent)))
|
20
21
|
|
21
|
-
query[:links]
|
22
|
+
query[:links] = links
|
23
|
+
query[:unique] = true
|
22
24
|
|
23
|
-
|
25
|
+
with_repository(parent) do
|
24
26
|
results = grandchild_model.send(finder, *(args << query))
|
25
27
|
# FIXME: remove the need for the uniq.freeze
|
26
|
-
finder == :all ? (@mutable ? results
|
28
|
+
finder == :all ? (@mutable ? results : results.freeze) : results
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
private
|
31
33
|
|
32
|
-
|
33
|
-
parent_model.relationships[@near_relationship_name]
|
34
|
-
end
|
35
|
-
|
36
|
-
def links
|
37
|
-
if remote_relationship.kind_of?(RelationshipChain)
|
38
|
-
remote_relationship.instance_eval { links } + [remote_relationship.instance_eval { near_relationship } ]
|
39
|
-
else
|
40
|
-
[ remote_relationship ]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def remote_relationship
|
45
|
-
near_relationship.child_model.relationships[@remote_relationship_name] ||
|
46
|
-
near_relationship.child_model.relationships[@remote_relationship_name.to_s.singularize.to_sym]
|
47
|
-
end
|
48
|
-
|
49
|
-
def grandchild_model
|
50
|
-
Class === @child_model ? @child_model : self.class.find_const(@child_model)
|
51
|
-
end
|
52
|
-
|
34
|
+
# @api private
|
53
35
|
def initialize(options)
|
54
36
|
if (missing_options = OPTIONS - [ :min, :max ] - options.keys ).any?
|
55
37
|
raise ArgumentError, "The options #{missing_options * ', '} are required", caller
|
@@ -69,6 +51,31 @@ module DataMapper
|
|
69
51
|
@extra_links = []
|
70
52
|
@options = options
|
71
53
|
end
|
54
|
+
|
55
|
+
# @api private
|
56
|
+
def near_relationship
|
57
|
+
parent_model.relationships[@near_relationship_name]
|
58
|
+
end
|
59
|
+
|
60
|
+
# @api private
|
61
|
+
def links
|
62
|
+
if remote_relationship.kind_of?(RelationshipChain)
|
63
|
+
remote_relationship.instance_eval { links } + [remote_relationship.instance_eval { near_relationship } ]
|
64
|
+
else
|
65
|
+
[ remote_relationship ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @api private
|
70
|
+
def remote_relationship
|
71
|
+
near_relationship.child_model.relationships[@remote_relationship_name] ||
|
72
|
+
near_relationship.child_model.relationships[@remote_relationship_name.to_s.singularize.to_sym]
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def grandchild_model
|
77
|
+
Class === @child_model ? @child_model : (Class === @parent_model ? @parent_model.find_const(@child_model) : Object.find_const(@child_model))
|
78
|
+
end
|
72
79
|
end # class Relationship
|
73
80
|
end # module Associations
|
74
81
|
end # module DataMapper
|
@@ -37,9 +37,7 @@ module DataMapper
|
|
37
37
|
if self.superclass != Object
|
38
38
|
self.superclass.auto_migrate!(repository_name)
|
39
39
|
else
|
40
|
-
repository_name ||= default_repository_name
|
41
40
|
repository(repository_name) do |r|
|
42
|
-
(relationships(r.name)||{}).each_value { |relationship| relationship.child_key }
|
43
41
|
r.adapter.destroy_model_storage(r, self)
|
44
42
|
r.adapter.create_model_storage(r, self)
|
45
43
|
end
|
@@ -52,9 +50,7 @@ module DataMapper
|
|
52
50
|
#
|
53
51
|
# @param Symbol repository_name the repository to be migrated
|
54
52
|
def auto_upgrade!(repository_name = nil)
|
55
|
-
repository_name ||= default_repository_name
|
56
53
|
repository(repository_name) do |r|
|
57
|
-
(relationships(r.name)||{}).each_value { |relationship| relationship.child_key }
|
58
54
|
r.adapter.upgrade_model_storage(r, self)
|
59
55
|
end
|
60
56
|
end
|
data/lib/dm-core/collection.rb
CHANGED
@@ -50,6 +50,7 @@ module DataMapper
|
|
50
50
|
#
|
51
51
|
# @api public
|
52
52
|
def get(*key)
|
53
|
+
key = model.typecast_key(key)
|
53
54
|
if loaded?
|
54
55
|
# loop over the collection to find the matching resource
|
55
56
|
detect { |resource| resource.key == key }
|
@@ -318,8 +319,22 @@ module DataMapper
|
|
318
319
|
self
|
319
320
|
end
|
320
321
|
|
322
|
+
# builds a new resource and appends it to the collection
|
323
|
+
#
|
324
|
+
# @param Hash[Symbol => Object] attributes attributes which
|
325
|
+
# the new resource should have.
|
326
|
+
#
|
327
|
+
# @api public
|
328
|
+
def build(attributes = {})
|
329
|
+
repository.scope do
|
330
|
+
resource = model.new(default_attributes.merge(attributes))
|
331
|
+
self << resource
|
332
|
+
resource
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
321
336
|
##
|
322
|
-
# creates a new
|
337
|
+
# creates a new resource, saves it, and appends it to the collection
|
323
338
|
#
|
324
339
|
# @param Hash[Symbol => Object] attributes attributes which
|
325
340
|
# the new resource should have.
|
@@ -462,12 +477,26 @@ module DataMapper
|
|
462
477
|
default_attributes
|
463
478
|
end
|
464
479
|
|
480
|
+
##
|
481
|
+
# check to see if collection can respond to the method
|
482
|
+
#
|
483
|
+
# @param method [Symbol] method to check in the object
|
484
|
+
# @param include_private [FalseClass, TrueClass] if set to true,
|
485
|
+
# collection will check private methods
|
486
|
+
#
|
487
|
+
# @return [TrueClass, FalseClass]
|
488
|
+
# TrueClass indicates the method can be responded to by the collection
|
489
|
+
# FalseClass indicates the method can not be responded to by the collection
|
490
|
+
#
|
491
|
+
# @api public
|
492
|
+
def respond_to?(method, include_private = false)
|
493
|
+
super || model.public_methods(false).include?(method.to_s) || relationships.has_key?(method)
|
494
|
+
end
|
495
|
+
|
465
496
|
protected
|
466
497
|
|
467
498
|
##
|
468
499
|
# @api private
|
469
|
-
#
|
470
|
-
# @api public
|
471
500
|
def model
|
472
501
|
query.model
|
473
502
|
end
|
@@ -579,7 +608,11 @@ module DataMapper
|
|
579
608
|
##
|
580
609
|
# @api private
|
581
610
|
def method_missing(method, *args, &block)
|
582
|
-
if
|
611
|
+
if model.public_methods(false).include?(method.to_s)
|
612
|
+
model.send(:with_scope, query) do
|
613
|
+
model.send(method, *args, &block)
|
614
|
+
end
|
615
|
+
elsif relationship = relationships[method]
|
583
616
|
klass = model == relationship.child_model ? relationship.parent_model : relationship.child_model
|
584
617
|
|
585
618
|
# TODO: when self.query includes an offset/limit use it as a
|
@@ -595,10 +628,10 @@ module DataMapper
|
|
595
628
|
:links => self.query.links + [ relationship ]
|
596
629
|
)
|
597
630
|
|
598
|
-
|
631
|
+
klass.all(query, &block)
|
632
|
+
else
|
633
|
+
super
|
599
634
|
end
|
600
|
-
|
601
|
-
super
|
602
635
|
end
|
603
636
|
end # class Collection
|
604
637
|
end # module DataMapper
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DataMapper
|
2
|
+
##
|
3
|
+
#
|
4
|
+
# DataMapper's DependencyQueue is used to store callbacks for classes which
|
5
|
+
# may or may not be loaded already.
|
6
|
+
#
|
7
|
+
class DependencyQueue
|
8
|
+
def initialize
|
9
|
+
@dependencies = Hash.new { |h,k| h[k] = [] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(class_name, &callback)
|
13
|
+
@dependencies[class_name] << callback
|
14
|
+
resolve!
|
15
|
+
end
|
16
|
+
|
17
|
+
def resolve!
|
18
|
+
@dependencies.each do |class_name, callbacks|
|
19
|
+
begin
|
20
|
+
klass = Object.find_const(class_name)
|
21
|
+
callbacks.each do |callback|
|
22
|
+
callback.call(klass)
|
23
|
+
end
|
24
|
+
callbacks.clear
|
25
|
+
rescue NameError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # class DependencyQueue
|
31
|
+
end # module DataMapper
|
data/lib/dm-core/hook.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module Hook
|
3
3
|
def self.included(model)
|
4
|
-
model.class_eval
|
4
|
+
model.class_eval <<-EOS, __FILE__, __LINE__
|
5
5
|
include Extlib::Hook
|
6
6
|
register_instance_hooks :save, :create, :update, :destroy
|
7
|
-
|
7
|
+
EOS
|
8
8
|
end
|
9
9
|
end
|
10
10
|
DataMapper::Resource.append_inclusions Hook
|
data/lib/dm-core/is.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module Is
|
3
3
|
|
4
|
-
def is(plugin
|
4
|
+
def is(plugin, *pars, &block)
|
5
5
|
generator_method = "is_#{plugin}".to_sym
|
6
6
|
|
7
7
|
if self.respond_to?(generator_method)
|
8
|
-
self.send(generator_method
|
8
|
+
self.send(generator_method, *pars, &block)
|
9
9
|
else
|
10
10
|
raise PluginNotFoundError, "could not find plugin named #{plugin}"
|
11
11
|
end
|
data/lib/dm-core/logger.rb
CHANGED
@@ -213,19 +213,19 @@ module DataMapper
|
|
213
213
|
# :off only gets a off? method
|
214
214
|
LEVELS.each_pair do |name, number|
|
215
215
|
unless name.to_s == 'off'
|
216
|
-
class_eval <<-EOS
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
216
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
217
|
+
# DOC
|
218
|
+
def #{name}(message)
|
219
|
+
self.<<( prep_msg(message, "#{name}") ) if #{name}?
|
220
|
+
end
|
221
221
|
EOS
|
222
222
|
end
|
223
223
|
|
224
|
-
class_eval <<-EOS
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
224
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
225
|
+
# DOC
|
226
|
+
def #{name}?
|
227
|
+
#{number} >= level
|
228
|
+
end
|
229
229
|
EOS
|
230
230
|
end
|
231
231
|
|
data/lib/dm-core/model.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module DataMapper
|
2
4
|
module Model
|
3
5
|
##
|
@@ -21,23 +23,43 @@ module DataMapper
|
|
21
23
|
extra_extensions.concat extensions
|
22
24
|
true
|
23
25
|
end
|
24
|
-
|
26
|
+
|
25
27
|
def self.extra_extensions
|
26
28
|
@extra_extensions ||= []
|
27
29
|
end
|
28
|
-
|
30
|
+
|
29
31
|
def self.extended(model)
|
30
|
-
model.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(model.
|
32
|
+
model.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(model.send(:default_storage_name)) })
|
31
33
|
model.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? PropertySet.new : h[Repository.default_name].dup })
|
32
34
|
extra_extensions.each { |extension| model.extend(extension) }
|
33
35
|
end
|
34
36
|
|
35
37
|
def inherited(target)
|
36
|
-
target.instance_variable_set(:@storage_names,
|
37
|
-
target.instance_variable_set(:@properties,
|
38
|
+
target.instance_variable_set(:@storage_names, @storage_names.dup)
|
39
|
+
target.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? PropertySet.new : h[Repository.default_name].dup })
|
40
|
+
target.instance_variable_set(:@base_model, self.base_model)
|
41
|
+
target.instance_variable_set(:@paranoid_properties, @paranoid_properties)
|
42
|
+
target.instance_variable_set(:@validations, @validations.dup) if self.respond_to?(:validators)
|
43
|
+
|
44
|
+
@properties.each do |repository_name,properties|
|
45
|
+
repository(repository_name) do
|
46
|
+
properties.each do |property|
|
47
|
+
next if target.properties(repository_name).has_property?(property.name)
|
48
|
+
target.property(property.name, property.type, property.options.dup)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
38
52
|
|
39
53
|
if @relationships
|
40
|
-
duped_relationships =
|
54
|
+
duped_relationships = Hash.new { |h,k| h[k] = {} }
|
55
|
+
@relationships.each do |repository_name,relationships|
|
56
|
+
relationships.each do |name, relationship|
|
57
|
+
dup = relationship.dup
|
58
|
+
dup.instance_variable_set(:@child_model, target) if dup.instance_variable_get(:@child_model) == self
|
59
|
+
dup.instance_variable_set(:@parent_model, target) if dup.instance_variable_get(:@parent_model) == self
|
60
|
+
duped_relationships[repository_name][name] = dup
|
61
|
+
end
|
62
|
+
end
|
41
63
|
target.instance_variable_set(:@relationships, duped_relationships)
|
42
64
|
end
|
43
65
|
end
|
@@ -54,6 +76,14 @@ module DataMapper
|
|
54
76
|
model
|
55
77
|
end
|
56
78
|
|
79
|
+
def base_model
|
80
|
+
@base_model ||= self
|
81
|
+
end
|
82
|
+
|
83
|
+
def repository_name
|
84
|
+
Repository.context.any? ? Repository.context.last.name : default_repository_name
|
85
|
+
end
|
86
|
+
|
57
87
|
##
|
58
88
|
# Get the repository with a given name, or the default one for the current
|
59
89
|
# context, or the default one for this class.
|
@@ -71,7 +101,7 @@ module DataMapper
|
|
71
101
|
# united in the concept of explicitness over implicitness. That is - the explicit wish of the
|
72
102
|
# caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last).
|
73
103
|
#
|
74
|
-
DataMapper.repository(
|
104
|
+
DataMapper.repository(name || repository_name, &block)
|
75
105
|
end
|
76
106
|
|
77
107
|
##
|
@@ -103,11 +133,11 @@ module DataMapper
|
|
103
133
|
create_property_getter(property)
|
104
134
|
create_property_setter(property)
|
105
135
|
|
106
|
-
@properties[
|
136
|
+
@properties[repository_name] << property
|
107
137
|
|
108
138
|
# Add property to the other mappings as well if this is for the default
|
109
139
|
# repository.
|
110
|
-
if
|
140
|
+
if repository_name == default_repository_name
|
111
141
|
@properties.each_pair do |repository_name, properties|
|
112
142
|
next if repository_name == default_repository_name
|
113
143
|
properties << property
|
@@ -123,35 +153,42 @@ module DataMapper
|
|
123
153
|
context = :default if context == true
|
124
154
|
|
125
155
|
Array(context).each do |item|
|
126
|
-
@properties[
|
156
|
+
@properties[repository_name].lazy_context(item) << name
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# add the property to the child classes only if the property was
|
161
|
+
# added after the child classes' properties have been copied from
|
162
|
+
# the parent
|
163
|
+
if respond_to?(:descendants)
|
164
|
+
descendants.each do |model|
|
165
|
+
next if model.properties(repository_name).has_property?(name)
|
166
|
+
model.property(name, type, options)
|
127
167
|
end
|
128
168
|
end
|
129
169
|
|
130
170
|
property
|
131
171
|
end
|
132
172
|
|
133
|
-
# TODO: make this a Set?
|
134
173
|
def repositories
|
135
|
-
[ repository ] + @properties.keys.collect { |repository_name| DataMapper.repository(repository_name) }
|
174
|
+
[ repository ].to_set + @properties.keys.collect { |repository_name| DataMapper.repository(repository_name) }
|
136
175
|
end
|
137
176
|
|
138
177
|
def properties(repository_name = default_repository_name)
|
139
178
|
@properties[repository_name]
|
140
179
|
end
|
141
180
|
|
181
|
+
# @api private
|
142
182
|
def properties_with_subclasses(repository_name = default_repository_name)
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
subclass.properties(repository_name).each do |subprop|
|
150
|
-
props << subprop if not props.any? { |prop| prop.name == subprop.name }
|
151
|
-
end
|
183
|
+
properties = PropertySet.new
|
184
|
+
([ self ].to_set + (respond_to?(:descendants) ? descendants : [])).each do |model|
|
185
|
+
model.relationships(repository_name).each_value { |relationship| relationship.child_key }
|
186
|
+
model.many_to_one_relationships.each do |relationship| relationship.child_key end
|
187
|
+
model.properties(repository_name).each do |property|
|
188
|
+
properties << property unless properties.has_property?(property.name)
|
152
189
|
end
|
153
|
-
props
|
154
190
|
end
|
191
|
+
properties
|
155
192
|
end
|
156
193
|
|
157
194
|
def key(repository_name = default_repository_name)
|
@@ -167,6 +204,7 @@ module DataMapper
|
|
167
204
|
end
|
168
205
|
|
169
206
|
def get(*key)
|
207
|
+
key = typecast_key(key)
|
170
208
|
repository.identity_map(self).get(key) || first(to_query(repository, key))
|
171
209
|
end
|
172
210
|
|
@@ -200,7 +238,7 @@ module DataMapper
|
|
200
238
|
resource = allocate
|
201
239
|
query = query.dup
|
202
240
|
|
203
|
-
properties(
|
241
|
+
properties(repository_name).key.each do |property|
|
204
242
|
if value = query.delete(property.name)
|
205
243
|
resource.send("#{property.name}=", value)
|
206
244
|
end
|
@@ -223,12 +261,10 @@ module DataMapper
|
|
223
261
|
end
|
224
262
|
|
225
263
|
##
|
226
|
-
#
|
227
|
-
#
|
228
|
-
# @see DataMapper::Resource#create
|
229
|
-
# @param <Hash(Symbol => Object)> attributes hash of attributes to set
|
230
|
-
# @raise <PersistenceError> The resource could not be saved
|
264
|
+
# This method is deprecated, and will be removed from dm-core.
|
265
|
+
#
|
231
266
|
def create!(attributes = {})
|
267
|
+
warn("Model#create! is deprecated. It is moving to dm-validations, and will be used to create a record without validations")
|
232
268
|
resource = create(attributes)
|
233
269
|
raise PersistenceError, "Resource not saved: :new_record => #{resource.new_record?}, :dirty_attributes => #{resource.dirty_attributes.inspect}" if resource.new_record?
|
234
270
|
resource
|
@@ -280,7 +316,7 @@ module DataMapper
|
|
280
316
|
when :hash
|
281
317
|
resource.original_values[property.name] = value.dup.hash unless resource.original_values.has_key?(property.name) rescue value.hash
|
282
318
|
when :load
|
283
|
-
|
319
|
+
resource.original_values[property.name] = value unless resource.original_values.has_key?(property.name)
|
284
320
|
end
|
285
321
|
end
|
286
322
|
end
|
@@ -290,20 +326,29 @@ module DataMapper
|
|
290
326
|
|
291
327
|
# TODO: spec this
|
292
328
|
def to_query(repository, key, query = {})
|
293
|
-
conditions = Hash[ *self.key(
|
329
|
+
conditions = Hash[ *self.key(repository_name).zip(key).flatten ]
|
294
330
|
Query.new(repository, self, query.merge(conditions))
|
295
331
|
end
|
296
332
|
|
297
|
-
|
298
|
-
|
299
|
-
def default_storage_name
|
300
|
-
self.name
|
333
|
+
def typecast_key(key)
|
334
|
+
self.key(repository_name).zip(key).map { |k, v| k.typecast(v) }
|
301
335
|
end
|
302
336
|
|
303
337
|
def default_repository_name
|
304
338
|
Repository.default_name
|
305
339
|
end
|
306
340
|
|
341
|
+
def paranoid_properties
|
342
|
+
@paranoid_properties ||= {}
|
343
|
+
@paranoid_properties
|
344
|
+
end
|
345
|
+
|
346
|
+
private
|
347
|
+
|
348
|
+
def default_storage_name
|
349
|
+
self.name
|
350
|
+
end
|
351
|
+
|
307
352
|
def scoped_query(query = self.query)
|
308
353
|
assert_kind_of 'query', query, Query, Hash
|
309
354
|
|
@@ -315,7 +360,15 @@ module DataMapper
|
|
315
360
|
query
|
316
361
|
end
|
317
362
|
|
318
|
-
|
363
|
+
if self.query
|
364
|
+
self.query.merge(query)
|
365
|
+
else
|
366
|
+
merge_with_default_scope(query)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
def set_paranoid_property(name, &block)
|
371
|
+
self.paranoid_properties[name] = block
|
319
372
|
end
|
320
373
|
|
321
374
|
# defines the getter for the property
|
@@ -327,7 +380,7 @@ module DataMapper
|
|
327
380
|
end
|
328
381
|
EOS
|
329
382
|
|
330
|
-
if property.primitive == TrueClass && !
|
383
|
+
if property.primitive == TrueClass && !instance_methods.include?(property.name.to_s)
|
331
384
|
class_eval <<-EOS, __FILE__, __LINE__
|
332
385
|
#{property.reader_visibility}
|
333
386
|
alias #{property.name} #{property.getter}
|
@@ -337,7 +390,7 @@ module DataMapper
|
|
337
390
|
|
338
391
|
# defines the setter for the property
|
339
392
|
def create_property_setter(property)
|
340
|
-
unless instance_methods.include?(property.name
|
393
|
+
unless instance_methods.include?("#{property.name}=")
|
341
394
|
class_eval <<-EOS, __FILE__, __LINE__
|
342
395
|
#{property.writer_visibility}
|
343
396
|
def #{property.name}=(value)
|
@@ -353,14 +406,14 @@ module DataMapper
|
|
353
406
|
# a missing module can cause misleading recursive errors.
|
354
407
|
raise NotImplementedError.new
|
355
408
|
end
|
356
|
-
|
357
|
-
def method_missing(method, *args, &block)
|
358
|
-
if relationship = self.relationships(
|
409
|
+
|
410
|
+
def method_missing(method, *args, &block)
|
411
|
+
if relationship = self.relationships(repository_name)[method]
|
359
412
|
klass = self == relationship.child_model ? relationship.parent_model : relationship.child_model
|
360
413
|
return DataMapper::Query::Path.new(repository, [ relationship ], klass)
|
361
414
|
end
|
362
415
|
|
363
|
-
if property = properties(
|
416
|
+
if property = properties(repository_name)[method]
|
364
417
|
return property
|
365
418
|
end
|
366
419
|
|