dm-core 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/dm-core/property.rb
CHANGED
@@ -61,9 +61,9 @@ module DataMapper
|
|
61
61
|
#
|
62
62
|
# class Post
|
63
63
|
# include DataMapper::Resource
|
64
|
-
# property :title, String,
|
64
|
+
# property :title, String, :accessor => :private
|
65
65
|
# # Both reader and writer are private
|
66
|
-
# property :body, Text,
|
66
|
+
# property :body, Text, :accessor => :protected
|
67
67
|
# # Both reader and writer are protected
|
68
68
|
# end
|
69
69
|
#
|
@@ -243,7 +243,7 @@ module DataMapper
|
|
243
243
|
# NOTE: PLEASE update PROPERTY_OPTIONS in DataMapper::Type when updating
|
244
244
|
# them here
|
245
245
|
PROPERTY_OPTIONS = [
|
246
|
-
:
|
246
|
+
:accessor, :reader, :writer,
|
247
247
|
:lazy, :default, :nullable, :key, :serial, :field, :size, :length,
|
248
248
|
:format, :index, :unique_index, :check, :ordinal, :auto_validation,
|
249
249
|
:validates, :unique, :track, :precision, :scale
|
@@ -264,7 +264,8 @@ module DataMapper
|
|
264
264
|
Time,
|
265
265
|
Object,
|
266
266
|
Class,
|
267
|
-
DataMapper::Types::Discriminator
|
267
|
+
DataMapper::Types::Discriminator,
|
268
|
+
DataMapper::Types::Serial
|
268
269
|
]
|
269
270
|
|
270
271
|
IMMUTABLE_TYPES = [ TrueClass, Float, Integer, BigDecimal]
|
@@ -273,7 +274,8 @@ module DataMapper
|
|
273
274
|
|
274
275
|
DEFAULT_LENGTH = 50
|
275
276
|
DEFAULT_PRECISION = 10
|
276
|
-
|
277
|
+
DEFAULT_SCALE_BIGDECIMAL = 0
|
278
|
+
DEFAULT_SCALE_FLOAT = nil
|
277
279
|
|
278
280
|
attr_reader :primitive, :model, :name, :instance_variable_name,
|
279
281
|
:type, :reader_visibility, :writer_visibility, :getter, :options,
|
@@ -284,18 +286,14 @@ module DataMapper
|
|
284
286
|
# @return <String> name of field in data-store
|
285
287
|
# -
|
286
288
|
# @api semi-public
|
287
|
-
def field(
|
288
|
-
@
|
289
|
+
def field(repository_name = nil)
|
290
|
+
@field || fields[repository_name || model.repository_name]
|
289
291
|
end
|
290
292
|
|
291
293
|
def unique
|
292
294
|
@unique ||= @options.fetch(:unique, @serial || @key || false)
|
293
295
|
end
|
294
296
|
|
295
|
-
def repository(*args)
|
296
|
-
@model.repository(*args)
|
297
|
-
end
|
298
|
-
|
299
297
|
def hash
|
300
298
|
if @custom && !@bound
|
301
299
|
@type.bind(self)
|
@@ -336,7 +334,6 @@ module DataMapper
|
|
336
334
|
@lazy
|
337
335
|
end
|
338
336
|
|
339
|
-
|
340
337
|
# Returns whether or not the property is a key or a part of a key
|
341
338
|
#
|
342
339
|
# @return <TrueClass, FalseClass> whether the property is a key or a part of
|
@@ -377,17 +374,7 @@ module DataMapper
|
|
377
374
|
def get(resource)
|
378
375
|
new_record = resource.new_record?
|
379
376
|
|
380
|
-
unless new_record || resource.attribute_loaded?(name)
|
381
|
-
# TODO: refactor this section
|
382
|
-
contexts = if lazy?
|
383
|
-
name
|
384
|
-
else
|
385
|
-
model.properties(resource.repository.name).reject do |property|
|
386
|
-
property.lazy? || resource.attribute_loaded?(property.name)
|
387
|
-
end
|
388
|
-
end
|
389
|
-
resource.send(:lazy_load, contexts)
|
390
|
-
end
|
377
|
+
lazy_load(resource) unless new_record || resource.attribute_loaded?(name)
|
391
378
|
|
392
379
|
value = get!(resource)
|
393
380
|
|
@@ -416,6 +403,7 @@ module DataMapper
|
|
416
403
|
#-
|
417
404
|
# @api private
|
418
405
|
def set(resource, value)
|
406
|
+
lazy_load(resource) unless resource.new_record? || resource.attribute_loaded?(name)
|
419
407
|
new_value = typecast(value)
|
420
408
|
old_value = get!(resource)
|
421
409
|
|
@@ -432,6 +420,21 @@ module DataMapper
|
|
432
420
|
resource.instance_variable_set(instance_variable_name, value)
|
433
421
|
end
|
434
422
|
|
423
|
+
# Loads lazy columns when get or set is called.
|
424
|
+
#-
|
425
|
+
# @api private
|
426
|
+
def lazy_load(resource)
|
427
|
+
# TODO: refactor this section
|
428
|
+
contexts = if lazy?
|
429
|
+
name
|
430
|
+
else
|
431
|
+
model.properties(resource.repository.name).reject do |property|
|
432
|
+
property.lazy? || resource.attribute_loaded?(property.name)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
resource.send(:lazy_load, contexts)
|
436
|
+
end
|
437
|
+
|
435
438
|
# typecasts values into a primitive
|
436
439
|
#
|
437
440
|
# @return <TrueClass, String, Float, Integer, BigDecimal, DateTime, Date, Time
|
@@ -439,17 +442,37 @@ module DataMapper
|
|
439
442
|
#-
|
440
443
|
# @api private
|
441
444
|
def typecast(value)
|
442
|
-
return value if
|
445
|
+
return type.typecast(value, self) if type.respond_to?(:typecast)
|
446
|
+
return value if value.kind_of?(primitive) || value.nil?
|
443
447
|
begin
|
444
|
-
if
|
445
|
-
elsif
|
446
|
-
elsif
|
447
|
-
elsif
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
448
|
+
if primitive == TrueClass then %w[ true 1 t ].include?(value.to_s.downcase)
|
449
|
+
elsif primitive == String then value.to_s
|
450
|
+
elsif primitive == Float then value.to_f
|
451
|
+
elsif primitive == Integer
|
452
|
+
# The simplest possible implementation, i.e. value.to_i, is not
|
453
|
+
# desirable because "junk".to_i gives "0". We want nil instead,
|
454
|
+
# because this makes it clear that the typecast failed.
|
455
|
+
#
|
456
|
+
# After benchmarking, we preferred the current implementation over
|
457
|
+
# these two alternatives:
|
458
|
+
# * Integer(value) rescue nil
|
459
|
+
# * Integer(value_to_s =~ /(\d+)/ ? $1 : value_to_s) rescue nil
|
460
|
+
value_to_i = value.to_i
|
461
|
+
if value_to_i == 0 && value != '0'
|
462
|
+
value_to_s = value.to_s
|
463
|
+
begin
|
464
|
+
Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
|
465
|
+
rescue ArgumentError
|
466
|
+
nil
|
467
|
+
end
|
468
|
+
else
|
469
|
+
value_to_i
|
470
|
+
end
|
471
|
+
elsif primitive == BigDecimal then BigDecimal(value.to_s)
|
472
|
+
elsif primitive == DateTime then typecast_to_datetime(value)
|
473
|
+
elsif primitive == Date then typecast_to_date(value)
|
474
|
+
elsif primitive == Time then typecast_to_time(value)
|
475
|
+
elsif primitive == Class then self.class.find_const(value)
|
453
476
|
else
|
454
477
|
value
|
455
478
|
end
|
@@ -503,6 +526,7 @@ module DataMapper
|
|
503
526
|
@primitive = @options.fetch(:primitive, @type.respond_to?(:primitive) ? @type.primitive : @type)
|
504
527
|
|
505
528
|
@getter = TrueClass == @primitive ? "#{@name}?".to_sym : @name
|
529
|
+
@field = @options.fetch(:field, nil)
|
506
530
|
@serial = @options.fetch(:serial, false)
|
507
531
|
@key = @options.fetch(:key, @serial || false)
|
508
532
|
@default = @options.fetch(:default, nil)
|
@@ -524,18 +548,23 @@ module DataMapper
|
|
524
548
|
@length = @options.fetch(:length, @options.fetch(:size, DEFAULT_LENGTH))
|
525
549
|
elsif BigDecimal == @primitive || Float == @primitive
|
526
550
|
@precision = @options.fetch(:precision, DEFAULT_PRECISION)
|
527
|
-
|
551
|
+
|
552
|
+
default_scale = (Float == @primitive) ? DEFAULT_SCALE_FLOAT : DEFAULT_SCALE_BIGDECIMAL
|
553
|
+
@scale = @options.fetch(:scale, default_scale)
|
554
|
+
# @scale = @options.fetch(:scale, DEFAULT_SCALE_BIGDECIMAL)
|
528
555
|
|
529
556
|
unless @precision > 0
|
530
557
|
raise ArgumentError, "precision must be greater than 0, but was #{@precision.inspect}"
|
531
558
|
end
|
532
559
|
|
533
|
-
|
534
|
-
|
535
|
-
|
560
|
+
if (BigDecimal == @primitive) || (Float == @primitive && !@scale.nil?)
|
561
|
+
unless @scale >= 0
|
562
|
+
raise ArgumentError, "scale must be equal to or greater than 0, but was #{@scale.inspect}"
|
563
|
+
end
|
536
564
|
|
537
|
-
|
538
|
-
|
565
|
+
unless @precision >= @scale
|
566
|
+
raise ArgumentError, "precision must be equal to or greater than scale, but was #{@precision.inspect} and scale was #{@scale.inspect}"
|
567
|
+
end
|
539
568
|
end
|
540
569
|
end
|
541
570
|
|
@@ -545,11 +574,13 @@ module DataMapper
|
|
545
574
|
@model.property_serialization_setup(self) if @model.respond_to?(:property_serialization_setup)
|
546
575
|
end
|
547
576
|
|
577
|
+
def fields
|
578
|
+
@fields ||= Hash.new { |h,k| h[k] = repository(k).adapter.field_naming_convention.call(self.name) }
|
579
|
+
end
|
580
|
+
|
548
581
|
def determine_visibility # :nodoc:
|
549
582
|
@reader_visibility = @options[:reader] || @options[:accessor] || :public
|
550
583
|
@writer_visibility = @options[:writer] || @options[:accessor] || :public
|
551
|
-
@writer_visibility = :protected if @options[:protected]
|
552
|
-
@writer_visibility = :private if @options[:private]
|
553
584
|
|
554
585
|
unless VISIBILITY_OPTIONS.include?(@reader_visibility) && VISIBILITY_OPTIONS.include?(@writer_visibility)
|
555
586
|
raise ArgumentError, 'property visibility must be :public, :protected, or :private', caller(2)
|
data/lib/dm-core/property_set.rb
CHANGED
@@ -4,10 +4,12 @@ module DataMapper
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
def [](name)
|
7
|
-
@property_for[name]
|
7
|
+
@property_for[name] || raise(ArgumentError, "Unknown property '#{name}'", caller)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
def has_property?(name)
|
11
|
+
!!@property_for[name]
|
12
|
+
end
|
11
13
|
|
12
14
|
def slice(*names)
|
13
15
|
@property_for.values_at(*names)
|
@@ -44,13 +46,15 @@ module DataMapper
|
|
44
46
|
|
45
47
|
def indexes
|
46
48
|
index_hash = {}
|
47
|
-
|
49
|
+
repository_name = repository.name
|
50
|
+
each { |property| parse_index(property.index, property.field(repository_name), index_hash) }
|
48
51
|
index_hash
|
49
52
|
end
|
50
53
|
|
51
54
|
def unique_indexes
|
52
55
|
index_hash = {}
|
53
|
-
|
56
|
+
repository_name = repository.name
|
57
|
+
each { |property| parse_index(property.unique_index, property.field(repository_name), index_hash) }
|
54
58
|
index_hash
|
55
59
|
end
|
56
60
|
|
@@ -108,16 +112,6 @@ module DataMapper
|
|
108
112
|
'#<PropertySet:{' + map { |property| property.inspect }.join(',') + '}>'
|
109
113
|
end
|
110
114
|
|
111
|
-
def dup(target = nil)
|
112
|
-
return super() unless target
|
113
|
-
|
114
|
-
properties = map do |property|
|
115
|
-
Property.new(target || property.model, property.name, property.type, property.options.dup)
|
116
|
-
end
|
117
|
-
|
118
|
-
self.class.new(properties)
|
119
|
-
end
|
120
|
-
|
121
115
|
private
|
122
116
|
|
123
117
|
def initialize(properties = [])
|
data/lib/dm-core/query.rb
CHANGED
@@ -3,10 +3,10 @@ module DataMapper
|
|
3
3
|
include Assertions
|
4
4
|
|
5
5
|
OPTIONS = [
|
6
|
-
:reload, :offset, :limit, :order, :add_reversed, :fields, :links, :includes, :conditions
|
6
|
+
:reload, :offset, :limit, :order, :add_reversed, :fields, :links, :includes, :conditions, :unique
|
7
7
|
]
|
8
8
|
|
9
|
-
attr_reader :repository, :model, *OPTIONS - [ :reload ]
|
9
|
+
attr_reader :repository, :model, *OPTIONS - [ :reload, :unique ]
|
10
10
|
attr_writer :add_reversed
|
11
11
|
alias add_reversed? add_reversed
|
12
12
|
|
@@ -14,6 +14,10 @@ module DataMapper
|
|
14
14
|
@reload
|
15
15
|
end
|
16
16
|
|
17
|
+
def unique?
|
18
|
+
@unique
|
19
|
+
end
|
20
|
+
|
17
21
|
def reverse
|
18
22
|
dup.reverse!
|
19
23
|
end
|
@@ -42,6 +46,7 @@ module DataMapper
|
|
42
46
|
|
43
47
|
# only overwrite the attributes with non-default values
|
44
48
|
@reload = other.reload? unless other.reload? == false
|
49
|
+
@unique = other.unique? unless other.unique? == false
|
45
50
|
@offset = other.offset unless other.offset == 0
|
46
51
|
@limit = other.limit unless other.limit == nil
|
47
52
|
@order = other.order unless other.order == model.default_order
|
@@ -67,6 +72,7 @@ module DataMapper
|
|
67
72
|
# return hash == other.hash
|
68
73
|
@model == other.model &&
|
69
74
|
@reload == other.reload? &&
|
75
|
+
@unique == other.unique? &&
|
70
76
|
@offset == other.offset &&
|
71
77
|
@limit == other.limit &&
|
72
78
|
@order == other.order && # order is significant, so do not sort this
|
@@ -136,6 +142,7 @@ module DataMapper
|
|
136
142
|
[ :limit, limit ],
|
137
143
|
[ :offset, offset ],
|
138
144
|
[ :reload, reload? ],
|
145
|
+
[ :unique, unique? ],
|
139
146
|
]
|
140
147
|
|
141
148
|
"#<#{self.class.name} #{attrs.map { |(k,v)| "@#{k}=#{v.inspect}" } * ' '}>"
|
@@ -157,6 +164,7 @@ module DataMapper
|
|
157
164
|
|
158
165
|
@model = model # must be Class that includes DM::Resource
|
159
166
|
@reload = options.fetch :reload, false # must be true or false
|
167
|
+
@unique = options.fetch :unique, false # must be true or false
|
160
168
|
@offset = options.fetch :offset, 0 # must be an Integer greater than or equal to 0
|
161
169
|
@limit = options.fetch :limit, nil # must be an Integer greater than or equal to 1
|
162
170
|
@order = options.fetch :order, model.default_order # must be an Array of Symbol, DM::Query::Direction or DM::Property
|
@@ -214,18 +222,20 @@ module DataMapper
|
|
214
222
|
options.each do |key, value|
|
215
223
|
case key
|
216
224
|
when DataMapper::Query::Operator
|
217
|
-
options[key] = properties[key.target].type.dump(value, properties[key.target]) if
|
225
|
+
options[key] = properties[key.target].type.dump(value, properties[key.target]) if properties.has_property?(key.target) && properties[key.target].custom?
|
218
226
|
when Symbol, String
|
219
|
-
options[key] = properties[key].type.dump(value, properties[key]) if
|
227
|
+
options[key] = properties[key].type.dump(value, properties[key]) if properties.has_property?(key) && properties[key].custom?
|
220
228
|
end
|
221
229
|
end
|
222
230
|
end
|
223
231
|
|
224
232
|
# validate the options
|
225
233
|
def assert_valid_options(options)
|
226
|
-
# validate the reload option
|
227
|
-
|
228
|
-
|
234
|
+
# validate the reload option and unique option
|
235
|
+
([ :reload, :unique ] & options.keys).each do |attribute|
|
236
|
+
if options[attribute] != true && options[attribute] != false
|
237
|
+
raise ArgumentError, "+options[:#{attribute}]+ must be true or false, but was #{options[attribute].inspect}", caller(2)
|
238
|
+
end
|
229
239
|
end
|
230
240
|
|
231
241
|
# validate the offset and limit options
|
@@ -248,7 +258,17 @@ module DataMapper
|
|
248
258
|
assert_kind_of "options[:#{attribute}]", value, Array
|
249
259
|
|
250
260
|
if value.empty?
|
251
|
-
|
261
|
+
if attribute == :fields
|
262
|
+
if options[:unique] == false
|
263
|
+
raise ArgumentError, '+options[:fields]+ cannot be empty if +options[:unique] is false', caller(2)
|
264
|
+
end
|
265
|
+
elsif attribute == :order
|
266
|
+
if options[:fields] && options[:fields].any? { |p| !p.kind_of?(Operator) }
|
267
|
+
raise ArgumentError, '+options[:order]+ cannot be empty if +options[:fields] contains a non-operator', caller(2)
|
268
|
+
end
|
269
|
+
else
|
270
|
+
raise ArgumentError, "+options[:#{attribute}]+ cannot be empty", caller(2)
|
271
|
+
end
|
252
272
|
end
|
253
273
|
end
|
254
274
|
|
@@ -318,9 +338,10 @@ module DataMapper
|
|
318
338
|
# normalize fields to DM::Property
|
319
339
|
def normalize_fields(fields)
|
320
340
|
# TODO: return a PropertySet
|
341
|
+
# TODO: raise an exception if the property is not available in the repository
|
321
342
|
fields.map do |field|
|
322
343
|
case field
|
323
|
-
when Property
|
344
|
+
when Property, Operator
|
324
345
|
# TODO: if the Property's model doesn't match
|
325
346
|
# self.model, append the property's model to @links
|
326
347
|
# eg:
|
@@ -527,6 +548,8 @@ module DataMapper
|
|
527
548
|
end
|
528
549
|
|
529
550
|
def ==(other)
|
551
|
+
return true if super
|
552
|
+
return false unless other.kind_of?(self.class)
|
530
553
|
@operator == other.operator && @target == other.target
|
531
554
|
end
|
532
555
|
|
@@ -542,6 +565,8 @@ module DataMapper
|
|
542
565
|
|
543
566
|
class Path
|
544
567
|
include Assertions
|
568
|
+
|
569
|
+
%w[ id type ].each { |m| undef_method m }
|
545
570
|
|
546
571
|
attr_reader :relationships, :model, :property, :operator
|
547
572
|
|
data/lib/dm-core/repository.rb
CHANGED
File without changes
|
data/lib/dm-core/resource.rb
CHANGED
@@ -2,6 +2,8 @@ require 'set'
|
|
2
2
|
|
3
3
|
module DataMapper
|
4
4
|
module Resource
|
5
|
+
include Assertions
|
6
|
+
|
5
7
|
##
|
6
8
|
#
|
7
9
|
# Appends a module for inclusion into the model class after
|
@@ -22,12 +24,10 @@ module DataMapper
|
|
22
24
|
extra_inclusions.concat inclusions
|
23
25
|
true
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
def self.extra_inclusions
|
27
29
|
@extra_inclusions ||= []
|
28
30
|
end
|
29
|
-
|
30
|
-
include Assertions
|
31
31
|
|
32
32
|
# When Resource is included in a class this method makes sure
|
33
33
|
# it gets all the methods
|
@@ -334,11 +334,7 @@ module DataMapper
|
|
334
334
|
# --
|
335
335
|
# @api public
|
336
336
|
def loaded_attributes
|
337
|
-
|
338
|
-
properties.each do |property|
|
339
|
-
names << property.name if attribute_loaded?(property.name)
|
340
|
-
end
|
341
|
-
names
|
337
|
+
properties.map{|p| p.name if attribute_loaded?(p.name)}.compact
|
342
338
|
end
|
343
339
|
|
344
340
|
# set of original values of properties
|
@@ -471,7 +467,9 @@ module DataMapper
|
|
471
467
|
# --
|
472
468
|
# @api public
|
473
469
|
def attributes
|
474
|
-
properties.map
|
470
|
+
properties.map do |p|
|
471
|
+
[p.name, send(p.getter)] if p.reader_visibility == :public
|
472
|
+
end.compact.to_hash
|
475
473
|
end
|
476
474
|
|
477
475
|
# Mass assign of attributes
|
@@ -485,9 +483,11 @@ module DataMapper
|
|
485
483
|
values_hash.each_pair do |k,v|
|
486
484
|
setter = "#{k.to_s.sub(/\?\z/, '')}="
|
487
485
|
|
488
|
-
|
489
|
-
|
490
|
-
|
486
|
+
if respond_to?(setter)
|
487
|
+
send(setter, v)
|
488
|
+
else
|
489
|
+
raise NameError, "#{setter} is not a public property"
|
490
|
+
end
|
491
491
|
end
|
492
492
|
end
|
493
493
|
|
@@ -585,7 +585,7 @@ module DataMapper
|
|
585
585
|
end
|
586
586
|
|
587
587
|
def lazy_load(name)
|
588
|
-
reload_attributes(*properties.lazy_load_context(name))
|
588
|
+
reload_attributes(*properties.lazy_load_context(name) - loaded_attributes)
|
589
589
|
end
|
590
590
|
|
591
591
|
def child_associations
|