Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 949 lines (815 sloc) 26.244 kb
eeb1702 Resolved ticket #212.
Martin Kihlgren authored
1 require 'set'
e8b4f3b @sam Importing from old repository.
sam authored
2
3 module DataMapper
4 module Resource
cdd64b7 Refactored Resource#attribute_get and #attribute_set
Dan Kubb authored
5 include Assertions
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
6
7 def self.new(default_name, &b)
e7c88b5 @sam Pretty close...
sam authored
8 x = Class.new
9 x.send(:include, self)
04f928b @sam Fixed an issue with the naming conventions applied to anonymous-resource...
sam authored
10 x.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(default_name) })
e7c88b5 @sam Pretty close...
sam authored
11 x.instance_eval(&b)
12 x
13 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
14
78daf51 @advany add docs to DataMapper::Resource
advany authored
15 # When Resource is included in a class this method makes sure
16 # it gets all the methods
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
17 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
18 # -
19 # @private
74ef620 Modules now push themselves into Resource rather than it pulling them
Dan Kubb authored
20 def self.included(model)
21 model.extend ClassMethods
3684f20 Minor Resource cleanup
Dan Kubb authored
22 descendants << model
748b8d9 Enabled DataMapper::Resource to know what classes have included it.
Martin Kihlgren authored
23 end
24
10b3266 Added better documentation for Resource.including_classes.
Martin Kihlgren authored
25 # Return all classes that include the DataMapper::Resource module
26 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
27 # ==== Returns
28 # Set:: a set containing the including classes
29 #
30 # ==== Example
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
31 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
32 # Class Foo
33 # include DataMapper::Resource
34 # end
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
35 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
36 # DataMapper.Resource.decendents[1].type == Foo
37 #
10b3266 Added better documentation for Resource.including_classes.
Martin Kihlgren authored
38 # -
78daf51 @advany add docs to DataMapper::Resource
advany authored
39 # @semipublic
aa7c427 @wzph -1 Resource::descendents ; +1 Resource::descendants
wzph authored
40 def self.descendants
3684f20 Minor Resource cleanup
Dan Kubb authored
41 @descendants ||= Set.new
bd0410f @sam resource_spec passes now.
sam authored
42 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
43
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
44 # +---------------
45 # Instance methods
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
46
d294bac Updated Adapter API
Dan Kubb authored
47 attr_writer :collection
48
49 alias model class
6db24c7 Small performance optimizations
Dan Kubb authored
50
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
51 # returns the value of the attribute. Do not read from instance variables directly,
52 # but use this method. This method handels the lazy loading the attribute and returning
53 # of defaults if nessesary.
54 #
55 # ==== Parameters
56 # name<Symbol>:: name attribute to lookup
57 #
58 # ==== Returns
59 # <Types>:: the value stored at that given attribute, nil if none, and default if necessary
60 #
61 # ==== Example
62 #
63 # Class Foo
64 # include DataMapper::Resource
65 #
66 # property :first_name, String
67 # property :last_name, String
68 #
69 # def full_name
70 # "#{attribute_get(:first_name)} #{attribute_get(:last_name)}"
71 # end
72 #
73 # # using the shorter syntax
74 # def name_for_address_book
75 # "#{last_name}, #{first_name}"
76 # end
77 # end
78 #
79 # -
80 # @semipublic
81 def attribute_get(name)
82 properties[name].get(self)
83 end
84
85 # sets the value of the attribute and marks the attribute as dirty
86 # if it has been changed so that it may be saved. Do not set from
87 # instance variables directly, but use this method. This method
88 # handels the lazy loading the property and returning of defaults
89 # if nessesary.
90 #
91 # ==== Parameters
92 # name<Symbol>:: name attribute to set
93 # value<Type>:: value to store at that location
94 #
95 # ==== Returns
96 # <Types>:: the value stored at that given attribute, nil if none, and default if necessary
97 #
98 # ==== Example
99 #
100 # Class Foo
101 # include DataMapper::Resource
102 #
103 # property :first_name, String
104 # property :last_name, String
105 #
106 # def full_name(name)
107 # name = name.split(' ')
108 # attribute_set(:first_name, name[0])
109 # attribute_set(:last_name, name[1])
110 # end
111 #
112 # # using the shorter syntax
113 # def name_from_address_book(name)
114 # name = name.split(', ')
115 # first_name = name[1]
116 # last_name = name[0]
117 # end
118 # end
119 #
120 # -
121 # @semipublic
122 def attribute_set(name, value)
123 properties[name].set(self, value)
124 end
125
78daf51 @advany add docs to DataMapper::Resource
advany authored
126 # Compares if its the same object or if attributes are equal
127 #
128 # ==== Parameters
129 # other<Object>:: Object to compare to
130 #
131 # ==== Returns
132 # <True>:: the outcome of the comparison as a boolean
133 #
134 # -
135 # @public
e5847b9 Updated Collection to implement an interface similar to Array
Dan Kubb authored
136 def eql?(other)
137 return true if object_id == other.object_id
d294bac Updated Adapter API
Dan Kubb authored
138 return false unless other.kind_of?(model)
139 return true if repository == other.repository && key == other.key
3684f20 Minor Resource cleanup
Dan Kubb authored
140
141 properties.each do |property|
142 return false if property.get!(self) != property.get!(other)
143 end
144
145 true
e5847b9 Updated Collection to implement an interface similar to Array
Dan Kubb authored
146 end
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
147
e5847b9 Updated Collection to implement an interface similar to Array
Dan Kubb authored
148 alias == eql?
149
78daf51 @advany add docs to DataMapper::Resource
advany authored
150 # Inspection of the class name and the attributes
151 #
152 # ==== Returns
153 # <String>:: with the class name, attributes with their values
154 #
155 # ==== Example
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
156 #
157 # >> Foo.new
78daf51 @advany add docs to DataMapper::Resource
advany authored
158 # => #<Foo name=nil updated_at=nil created_at=nil id=nil>
159 #
160 # -
161 # @public
f7f784f @wycats Add #inspect and #pretty_print to DM::Resource
wycats authored
162 def inspect
852c46c Added Collection#reverse
Dan Kubb authored
163 attrs = []
c1b6c77 Updated Resource#inspect to not automatically lazy-load every property
Dan Kubb authored
164
3684f20 Minor Resource cleanup
Dan Kubb authored
165 properties.each do |property|
c1b6c77 Updated Resource#inspect to not automatically lazy-load every property
Dan Kubb authored
166 value = if property.lazy? && !attribute_loaded?(property.name) && !new_record?
167 '<not loaded>'
168 else
169 send(property.getter).inspect
170 end
171
172 attrs << "#{property.name}=#{value}"
852c46c Added Collection#reverse
Dan Kubb authored
173 end
c1b6c77 Updated Resource#inspect to not automatically lazy-load every property
Dan Kubb authored
174
d294bac Updated Adapter API
Dan Kubb authored
175 "#<#{model.name} #{attrs * ' '}>"
f7f784f @wycats Add #inspect and #pretty_print to DM::Resource
wycats authored
176 end
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
177
78daf51 @advany add docs to DataMapper::Resource
advany authored
178 # TODO docs
f7f784f @wycats Add #inspect and #pretty_print to DM::Resource
wycats authored
179 def pretty_print(pp)
d294bac Updated Adapter API
Dan Kubb authored
180 pp.group(1, "#<#{model.name}", ">") do
f7f784f @wycats Add #inspect and #pretty_print to DM::Resource
wycats authored
181 pp.breakable
3684f20 Minor Resource cleanup
Dan Kubb authored
182 pp.seplist(attributes.to_a) do |k_v|
f7f784f @wycats Add #inspect and #pretty_print to DM::Resource
wycats authored
183 pp.text k_v[0].to_s
184 pp.text " = "
185 pp.pp k_v[1]
186 end
187 end
188 end
189
15f56b7 more resolution
Adam French authored
190 ##
191 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
192 # ==== Returns
193 # <Repository>:: the respository this resource belongs to in the context of a collection OR in the class's context
194 #
195 # @public
d409c1f @sam Added and specced LoadedSet.
sam authored
196 def repository
d294bac Updated Adapter API
Dan Kubb authored
197 @repository || model.repository
d409c1f @sam Added and specced LoadedSet.
sam authored
198 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
199
15f56b7 more resolution
Adam French authored
200 # default id method to return the resource id when there is a
201 # single key, and the model was defined with a primary key named
202 # something other than id
203 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
204 # ==== Returns
205 # <Array[Key], Key> key or keys
206 #
207 # --
208 # @public
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
209 def id
210 key = self.key
211 key.first if key.size == 1
212 end
213
a519fb4 @sam CRUD in DataObjectAdapter is mostly done. There appears to be a bug in d...
sam authored
214 def key
3684f20 Minor Resource cleanup
Dan Kubb authored
215 key_properties.map do |property|
216 property.get!(self)
a519fb4 @sam CRUD in DataObjectAdapter is mostly done. There appears to be a bug in d...
sam authored
217 end
218 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
219
d409c1f @sam Added and specced LoadedSet.
sam authored
220 def readonly!
221 @readonly = true
222 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
223
d409c1f @sam Added and specced LoadedSet.
sam authored
224 def readonly?
225 @readonly == true
b625ac1 @sam Stuck on a stupid naming conflict with RSpec. So frustrating...
sam authored
226 end
1a1d51e Began cleaning up DO specific specs to be more consistent
Dan Kubb authored
227
15f56b7 more resolution
Adam French authored
228 # save the instance to the data-store
229 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
230 # ==== Returns
231 # <True, False>:: results of the save
232 #
15f56b7 more resolution
Adam French authored
233 # @see DataMapper::Repository#save
78daf51 @advany add docs to DataMapper::Resource
advany authored
234 #
235 # --
236 # #public
48f73dc Adds an argument to Resource#save. The argument is ignored by default. T...
Carl Lerche authored
237 def save(context = :default)
238 # Takes a context, but does nothing with it. This is to maintain the
239 # same API through out all of dm-more. dm-validations requires a
240 # context to be passed
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
241
242 child_associations.each { |a| a.save }
243
3684f20 Minor Resource cleanup
Dan Kubb authored
244 success = if dirty? || (new_record? && key_properties.any? { |p| p.serial? })
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
245 new_record? ? create : update
246 end
247
248 if success
249 original_values.clear
250 end
251
252 parent_associations.each { |a| a.save }
253
254 success == true
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
255 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
256
15f56b7 more resolution
Adam French authored
257 # destroy the instance, remove it from the repository
258 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
259 # ==== Returns
260 # <True, False>:: results of the destruction
261 #
262 # --
263 # @public
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
264 def destroy
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
265 return false unless repository.delete(to_query)
266
267 @new_record = true
268 repository.identity_map(model).delete(key)
269 original_values.clear
270
3684f20 Minor Resource cleanup
Dan Kubb authored
271 properties.each do |property|
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
272 # We'll set the original value to nil as if we had a new record
273 original_values[property.name] = nil if attribute_loaded?(property.name)
274 end
275
276 true
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
277 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
278
78daf51 @advany add docs to DataMapper::Resource
advany authored
279 # Checks if the attribute has been loaded
280 #
281 # ==== Example
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
282 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
283 # class Foo
284 # include DataMapper::Resource
285 # property :name, String
286 # property :description, Text, :lazy => false
287 # end
288 #
289 # Foo.new.attribute_loaded?(:description) # will return false
290 #
291 # --
292 # @public
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
293 def attribute_loaded?(name)
3684f20 Minor Resource cleanup
Dan Kubb authored
294 instance_variable_defined?(properties[name].instance_variable_name)
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
295 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
296
78daf51 @advany add docs to DataMapper::Resource
advany authored
297 # fetches all the names of the attributes that have been loaded,
298 # even if they are lazy but have been called
299 #
300 # ==== Returns
301 # Array[<Symbol>]:: names of attributes that have been loaded
302 #
303 # ==== Example
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
304 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
305 # class Foo
306 # include DataMapper::Resource
307 # property :name, String
308 # property :description, Text, :lazy => false
309 # end
310 #
311 # Foo.new.loaded_attributes # returns [:name]
312 #
313 # --
314 # @public
68a9fd7 @sam Fixed reload issue: http://wm.lighthouseapp.com/projects/4819/tickets/23...
sam authored
315 def loaded_attributes
316 names = []
3684f20 Minor Resource cleanup
Dan Kubb authored
317 properties.each do |property|
318 names << property.name if attribute_loaded?(property.name)
68a9fd7 @sam Fixed reload issue: http://wm.lighthouseapp.com/projects/4819/tickets/23...
sam authored
319 end
320 names
321 end
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
322
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
323 # set of original values of properties
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
324 #
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
325 # ==== Returns
63ab157 @bernerdschaefer Adding track => :load support
bernerdschaefer authored
326 # Hash:: original values of properties
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
327 #
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
328 # --
329 # @public
330 def original_values
63ab157 @bernerdschaefer Adding track => :load support
bernerdschaefer authored
331 @original_values ||= {}
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
332 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
333
d294bac Updated Adapter API
Dan Kubb authored
334 # Hash of attributes that have been marked dirty
78daf51 @advany add docs to DataMapper::Resource
advany authored
335 #
336 # ==== Returns
d294bac Updated Adapter API
Dan Kubb authored
337 # Hash:: attributes that have been marked dirty
78daf51 @advany add docs to DataMapper::Resource
advany authored
338 #
339 # --
e1b03e1 Moved more code into Migration and Transaction modules
Dan Kubb authored
340 # @private
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
341 def dirty_attributes
d294bac Updated Adapter API
Dan Kubb authored
342 dirty_attributes = {}
3684f20 Minor Resource cleanup
Dan Kubb authored
343 properties = self.properties
d294bac Updated Adapter API
Dan Kubb authored
344
345 original_values.each do |name, old_value|
3684f20 Minor Resource cleanup
Dan Kubb authored
346 property = properties[name]
347 new_value = property.get!(self)
d294bac Updated Adapter API
Dan Kubb authored
348
8098fd4 Typecast attributes when set
Dan Kubb authored
349 if property.custom?
350 new_value = property.type.dump(new_value, property)
351 old_value = property.type.dump(old_value, property)
352 end
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
353
9c49edb @bernerdschaefer Property#track :hash now functions correctly
bernerdschaefer authored
354 dirty = case property.track
e173e1d Fixed typecasting bug for TrueClass property
Dan Kubb authored
355 when :hash then old_value != new_value.hash
356 else
357 old_value != new_value
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
358 end
6f26387 Stripped whitespace using "sake strip"
Dan Kubb authored
359
9c49edb @bernerdschaefer Property#track :hash now functions correctly
bernerdschaefer authored
360 if dirty
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
361 property.hash
e173e1d Fixed typecasting bug for TrueClass property
Dan Kubb authored
362 dirty_attributes[property] = new_value
e31b867 @bernerdschaefer Added Property#track :set to replace Resource#dirty_attributes
bernerdschaefer authored
363 end
d294bac Updated Adapter API
Dan Kubb authored
364 end
365
366 dirty_attributes
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
367 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
368
78daf51 @advany add docs to DataMapper::Resource
advany authored
369 # Checks if the class is dirty
370 #
371 # ==== Returns
372 # True:: returns if class is dirty
373 #
374 # --
375 # @public
041d9f1 @sam DataObjectAdapter sqlite3 integration spec passes for #create.
sam authored
376 def dirty?
7f5a76a Removed Resource#loaded_attributes
Dan Kubb authored
377 dirty_attributes.any?
041d9f1 @sam DataObjectAdapter sqlite3 integration spec passes for #create.
sam authored
378 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
379
78daf51 @advany add docs to DataMapper::Resource
advany authored
380 # Checks if the attribute is dirty
381 #
382 # ==== Parameters
383 # name<Symbol>:: name of attribute
384 #
385 # ==== Returns
386 # True:: returns if attribute is dirty
387 #
388 # --
389 # @public
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
390 def attribute_dirty?(name)
3684f20 Minor Resource cleanup
Dan Kubb authored
391 dirty_attributes.has_key?(properties[name])
0074905 @sam attribute_set/attribute_get are mostly implemented minus lazy-loading.
sam authored
392 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
393
b578dd9 @somebee made resource.collection make a new collection if it is not set, and the...
somebee authored
394 def collection
d294bac Updated Adapter API
Dan Kubb authored
395 @collection ||= if query = to_query
a525d16 Updated Collection#initialize to require a block
Dan Kubb authored
396 Collection.new(query) { |c| c << self }
d294bac Updated Adapter API
Dan Kubb authored
397 end
b578dd9 @somebee made resource.collection make a new collection if it is not set, and the...
somebee authored
398 end
399
78daf51 @advany add docs to DataMapper::Resource
advany authored
400 # Reload association and all child association
401 #
402 # ==== Returns
403 # self:: returns the class itself
404 #
405 # --
406 # @public
4367249 Minor refactoring
Dan Kubb authored
407 def reload
1dceba8 Updated Relationship#get_children to return Array when parent is not sav...
Dan Kubb authored
408 reload_attributes(*loaded_attributes)
91392ef Updated association proxy methods to not automatically save on append/re...
Dan Kubb authored
409 (parent_associations + child_associations).each { |association| association.reload }
8aa0525 @sam Added reloading for associations. Need to spec.
sam authored
410 self
3412634 @sam Custom Types are integrated (with some caveats) see spec/integration/typ...
sam authored
411 end
58c07c8 Whitespace cleanup with "sake strip" (from dm-dev sake tasks)
Dan Kubb authored
412
b578dd9 @somebee made resource.collection make a new collection if it is not set, and the...
somebee authored
413 # Reload specific attributes
78daf51 @advany add docs to DataMapper::Resource
advany authored
414 #
415 # ==== Parameters
416 # *attributes<Array[<Symbol>]>:: name of attribute
417 #
418 # ==== Returns
419 # self:: returns the class itself
420 #
421 # --
422 # @public
ece0d18 @somebee some small convenient changes. added possibility for iterating through t...
somebee authored
423 def reload_attributes(*attributes)
b578dd9 @somebee made resource.collection make a new collection if it is not set, and the...
somebee authored
424 collection.reload(:fields => attributes)
ece0d18 @somebee some small convenient changes. added possibility for iterating through t...
somebee authored
425 self
426 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
427
78daf51 @advany add docs to DataMapper::Resource
advany authored
428 # Checks if the model has been saved
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
429 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
430 # ==== Returns
431 # True:: status if the model is new
805e402 @myabc YARD conversion for dm-core
myabc authored
432 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
433 # --
434 # @public
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
435 def new_record?
a51412a Updated LoadedSet API to match "Set" API for associations
Dan Kubb authored
436 !defined?(@new_record) || @new_record
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
437 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
438
78daf51 @advany add docs to DataMapper::Resource
advany authored
439 # all the attributes of the model
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
440 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
441 # ==== Returns
442 # Hash[<Symbol>]:: All the (non)-lazy attributes
443 #
444 # --
445 # @public
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
446 def attributes
447 pairs = {}
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
448
3684f20 Minor Resource cleanup
Dan Kubb authored
449 properties.each do |property|
450 next unless property.reader_visibility == :public
451 pairs[property.name] = send(property.getter)
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
452 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
453
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
454 pairs
e8b4f3b @sam Importing from old repository.
sam authored
455 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
456
78daf51 @advany add docs to DataMapper::Resource
advany authored
457 # Mass assign of attributes
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
458 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
459 # ==== Parameters
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
460 # value_hash <Hash[<Symbol>]>::
78daf51 @advany add docs to DataMapper::Resource
advany authored
461 #
462 # --
463 # @public
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
464 def attributes=(values_hash)
465 values_hash.each_pair do |k,v|
bb03497 Fixed failing specs
Dan Kubb authored
466 setter = "#{k.to_s.sub(/\?\z/, '')}="
3684f20 Minor Resource cleanup
Dan Kubb authored
467
468 # use the attribute mutator if it is public to set the value
469 next unless respond_to?(setter, false)
470 send(setter, v)
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
471 end
472 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
473
72db385 @advany update_attributes should save model
advany authored
474 # Updates attributes and saves model
475 #
78daf51 @advany add docs to DataMapper::Resource
advany authored
476 # ==== Parameters
477 # attributes<Hash> Attributes to be updated
478 # keys<Symbol, String, Array> keys of Hash to update (others won't be updated)
479 #
480 # ==== Returns
481 # <TrueClass, FalseClass> if model got saved or not
72db385 @advany update_attributes should save model
advany authored
482 #
483 #-
8708119 @myabc Convert docs to YARD-style
myabc authored
484 # @api public
1019ac3 @sam Added key validation to Resources, and added Resource#update_attributes.
sam authored
485 def update_attributes(hash, *update_only)
486 raise 'Update takes a hash as first parameter' unless hash.is_a?(Hash)
487 loop_thru = update_only.empty? ? hash.keys : update_only
3684f20 Minor Resource cleanup
Dan Kubb authored
488 loop_thru.each { |attr| send("#{attr}=", hash[attr]) }
72db385 @advany update_attributes should save model
advany authored
489 save
1019ac3 @sam Added key validation to Resources, and added Resource#update_attributes.
sam authored
490 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
491
d294bac Updated Adapter API
Dan Kubb authored
492 # TODO: add docs
493 def to_query(query = {})
494 model.to_query(repository, key, query) unless new_record?
e3ad4a2 Improved the transactional system greatly and introduced two-phase
Martin Kihlgren authored
495 end
496
3684f20 Minor Resource cleanup
Dan Kubb authored
497 protected
498
499 def properties
500 model.properties(repository.name)
501 end
502
503 def key_properties
504 model.key(repository.name)
505 end
506
507 def relationships
508 model.relationships(repository.name)
509 end
510
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
511 private
1a1d51e Began cleaning up DO specific specs to be more consistent
Dan Kubb authored
512
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
513 def initialize(attributes = {}) # :nodoc:
514 assert_valid_model
515 self.attributes = attributes
987e2ad Code reformatting, and refactoring of initialization methods
Dan Kubb authored
516 end
517
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
518 def assert_valid_model # :nodoc:
3684f20 Minor Resource cleanup
Dan Kubb authored
519 properties = self.properties
520
521 if properties.empty? && relationships.empty?
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
522 raise IncompleteResourceError, "#{model.name} must have at least one property or relationship to be initialized."
6db24c7 Small performance optimizations
Dan Kubb authored
523 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
524
3684f20 Minor Resource cleanup
Dan Kubb authored
525 if properties.key.empty?
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
526 raise IncompleteResourceError, "#{model.name} must have a key."
1019ac3 @sam Added key validation to Resources, and added Resource#update_attributes.
sam authored
527 end
6db24c7 Small performance optimizations
Dan Kubb authored
528 end
529
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
530 def create
531 # set defaults for new resource
3684f20 Minor Resource cleanup
Dan Kubb authored
532 properties.each do |property|
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
533 next if attribute_loaded?(property.name)
534 property.set(self, property.default_for(self))
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
535 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
536
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
537 return false unless repository.create([ self ]) == 1
538
539 @repository = repository
540 @new_record = false
541
542 repository.identity_map(model).set(key, self)
543
544 true
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
545 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
546
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
547 def update
3684f20 Minor Resource cleanup
Dan Kubb authored
548 dirty_attributes = self.dirty_attributes
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
549 return true if dirty_attributes.empty?
550 repository.update(dirty_attributes, to_query) == 1
551 end
552
cdd64b7 Refactored Resource#attribute_get and #attribute_set
Dan Kubb authored
553 # TODO document
554 # @semipublic
555 def attribute_get!(name)
3684f20 Minor Resource cleanup
Dan Kubb authored
556 properties[name].get!(self)
cdd64b7 Refactored Resource#attribute_get and #attribute_set
Dan Kubb authored
557 end
558
559 # TODO document
560 # @semipublic
561 def attribute_set!(name, value)
3684f20 Minor Resource cleanup
Dan Kubb authored
562 properties[name].set!(self, value)
cdd64b7 Refactored Resource#attribute_get and #attribute_set
Dan Kubb authored
563 end
564
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
565 def lazy_load(name)
3684f20 Minor Resource cleanup
Dan Kubb authored
566 reload_attributes(*properties.lazy_load_context(name))
567 end
568
569 def child_associations
570 @child_associations ||= []
571 end
572
573 def parent_associations
574 @parent_associations ||= []
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
575 end
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
576
e1b03e1 Moved more code into Migration and Transaction modules
Dan Kubb authored
577 # TODO: move to dm-more/dm-transactions
578 module Transaction
579 # Produce a new Transaction for the class of this Resource
580 #
581 # ==== Returns
582 # <DataMapper::Adapters::Transaction>::
583 # a new DataMapper::Adapters::Transaction with all DataMapper::Repositories
584 # of the class of this DataMapper::Resource added.
585 #-
586 # @api public
587 #
588 # TODO: move to dm-more/dm-transactions
589 def transaction(&block)
590 model.transaction(&block)
591 end
592
593 module ClassMethods
594 #
595 # Produce a new Transaction for this Resource class
596 #
597 # @return <DataMapper::Adapters::Transaction
598 # a new DataMapper::Adapters::Transaction with all DataMapper::Repositories
599 # of the class of this DataMapper::Resource added.
600 #-
601 # @api public
602 #
603 # TODO: move to dm-more/dm-transactions
604 def transaction(&block)
605 DataMapper::Transaction.new(self, &block)
606 end
607 end
608 end
609
610 include Transaction
611
e8b4f3b @sam Importing from old repository.
sam authored
612 module ClassMethods
e1b03e1 Moved more code into Migration and Transaction modules
Dan Kubb authored
613 include Transaction::ClassMethods
614
74ef620 Modules now push themselves into Resource rather than it pulling them
Dan Kubb authored
615 def self.extended(model)
867d311 Made it easy to let Resources use other bases than their class name for ...
Martin Kihlgren authored
616 model.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(model.instance_eval do default_storage_name end) })
a5ac488 Updated DataMapper.repository to throw exception if name is nil
Dan Kubb authored
617 model.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? PropertySet.new : h[Repository.default_name].dup })
987e2ad Code reformatting, and refactoring of initialization methods
Dan Kubb authored
618 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
619
2aab571 @sam Can target a new model with PropertySet#dup now.
sam authored
620 def inherited(target)
621 target.instance_variable_set(:@storage_names, @storage_names.dup)
a5ac488 Updated DataMapper.repository to throw exception if name is nil
Dan Kubb authored
622 target.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? self.properties(Repository.default_name).dup(target) : h[Repository.default_name].dup })
52a9321 @somebee added temporary fix for problems with Discriminator
somebee authored
623
2bb2178 @somebee fixed copying associations to inheriting classes
somebee authored
624 if @relationships
625 duped_relationships = {}; @relationships.each_pair{ |repos, rels| duped_relationships[repos] = rels.dup}
626 target.instance_variable_set(:@relationships, duped_relationships)
627 end
2aab571 @sam Can target a new model with PropertySet#dup now.
sam authored
628 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
629
15f56b7 more resolution
Adam French authored
630 ##
2f42d99 @myabc Clean up of comments and inline documentation
myabc authored
631 # Get the repository with a given name, or the default one for the current
632 # context, or the default one for this class.
4f7cc93 Added a spec for detecting if model-specific default repositories work.
Martin Kihlgren authored
633 #
805e402 @myabc YARD conversion for dm-core
myabc authored
634 # @param name<Symbol> the name of the repository wanted
635 # @param block<Block> block to execute with the fetched repository as parameter
4f7cc93 Added a spec for detecting if model-specific default repositories work.
Martin Kihlgren authored
636 #
805e402 @myabc YARD conversion for dm-core
myabc authored
637 # @return <Object, DataMapper::Respository> whatever the block returns,
638 # if given a block, otherwise the requested repository.
4f7cc93 Added a spec for detecting if model-specific default repositories work.
Martin Kihlgren authored
639 #-
7cf54e0 @myabc Further changes for YARD.
myabc authored
640 # @api public
4f7cc93 Added a spec for detecting if model-specific default repositories work.
Martin Kihlgren authored
641 def repository(name = nil, &block)
7b48517 Made the logic of Resource#repository more intuitive.
Martin Kihlgren authored
642 #
643 # There has been a couple of different strategies here, but me (zond) and dkubb are at least
644 # united in the concept of explicitness over implicitness. That is - the explicit wish of the
645 # caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last).
646 #
647 DataMapper.repository(*Array(name || (Repository.context.last ? nil : default_repository_name)), &block)
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
648 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
649
15f56b7 more resolution
Adam French authored
650 ##
651 # the name of the storage recepticle for this resource. IE. table name, for database stores
652 #
653 # @return <String> the storage name (IE table name, for database stores) associated with this resource in the given repository
179820a Renamed Resource::ClassMethods#resource_name as #storage_name
Dan Kubb authored
654 def storage_name(repository_name = default_repository_name)
655 @storage_names[repository_name]
e8b4f3b @sam Importing from old repository.
sam authored
656 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
657
15f56b7 more resolution
Adam French authored
658 ##
659 # the names of the storage recepticles for this resource across all repositories
660 #
661 # @return <Hash(Symbol => String)> All available names of storage recepticles
179820a Renamed Resource::ClassMethods#resource_name as #storage_name
Dan Kubb authored
662 def storage_names
663 @storage_names
e8b4f3b @sam Importing from old repository.
sam authored
664 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
665
15f56b7 more resolution
Adam French authored
666 ##
667 # defines a property on the resource
668 #
669 # @param <Symbol> name the name for which to call this property
670 # @param <Type> type the type to define this property ass
671 # @param <Hash(Symbol => String)> options a hash of available options
672 # @see DataMapper::Property
e8b4f3b @sam Importing from old repository.
sam authored
673 def property(name, type, options = {})
bae6dbc @sam Started on adding associations. The big news is the Relationship class i...
sam authored
674 property = Property.new(self, name, type, options)
8b3eed8 Refactored type assertion code into assert_kind_of helper method
Dan Kubb authored
675
676 create_property_getter(property)
677 create_property_setter(property)
678
987e2ad Code reformatting, and refactoring of initialization methods
Dan Kubb authored
679 @properties[repository.name] << property
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
680
2f42d99 @myabc Clean up of comments and inline documentation
myabc authored
681 # Add property to the other mappings as well if this is for the default
682 # repository.
d409c1f @sam Added and specced LoadedSet.
sam authored
683 if repository.name == default_repository_name
bd0410f @sam resource_spec passes now.
sam authored
684 @properties.each_pair do |repository_name, properties|
8e0b2e6 @sam Details...
sam authored
685 next if repository_name == default_repository_name
edb129d @sam Rolling back earlier patch...
sam authored
686 properties << property
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
687 end
e8b4f3b @sam Importing from old repository.
sam authored
688 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
689
2f42d99 @myabc Clean up of comments and inline documentation
myabc authored
690 # Add the property to the lazy_loads set for this resources repository
691 # only.
692 # TODO Is this right or should we add the lazy contexts to all
693 # repositories?
54f8aed @sam Working on custom-types integration.
sam authored
694 if property.lazy?
4367249 Minor refactoring
Dan Kubb authored
695 context = options.fetch(:lazy, :default)
696 context = :default if context == true
697
698 Array(context).each do |item|
699 @properties[repository.name].lazy_context(item) << name
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
700 end
701 end
702
bd0410f @sam resource_spec passes now.
sam authored
703 property
e8b4f3b @sam Importing from old repository.
sam authored
704 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
705
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
706 # TODO: make this a Set?
e3ad4a2 Improved the transactional system greatly and introduced two-phase
Martin Kihlgren authored
707 def repositories
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
708 [ repository ] + @properties.keys.collect { |repository_name| DataMapper.repository(repository_name) }
e3ad4a2 Improved the transactional system greatly and introduced two-phase
Martin Kihlgren authored
709 end
710
179820a Renamed Resource::ClassMethods#resource_name as #storage_name
Dan Kubb authored
711 def properties(repository_name = default_repository_name)
bd0410f @sam resource_spec passes now.
sam authored
712 @properties[repository_name]
713 end
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
714
9e755c7 @cilquirm STI parent/child/nephew/uncle property fix
cilquirm authored
715 def properties_with_subclasses(repository_name = default_repository_name)
716 #return properties if we're not interested in sti
717 if @properties[repository_name].inheritance_property.nil?
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
718 @properties[repository_name]
9e755c7 @cilquirm STI parent/child/nephew/uncle property fix
cilquirm authored
719 else
720 props = @properties[repository_name].dup
721 self.child_classes.each do |subclass|
722 subclass.properties(repository_name).each do |subprop|
723 props << subprop if not props.any? { |prop| prop.name == subprop.name }
322419c Stripped whitespace with "sake strip"
Dan Kubb authored
724 end
9e755c7 @cilquirm STI parent/child/nephew/uncle property fix
cilquirm authored
725 end
726 props
727 end
728 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
729
179820a Renamed Resource::ClassMethods#resource_name as #storage_name
Dan Kubb authored
730 def key(repository_name = default_repository_name)
5ec4cec @sam Running some benchmarks, making some performance tweaks.
sam authored
731 @properties[repository_name].key
d409c1f @sam Added and specced LoadedSet.
sam authored
732 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
733
852c46c Added Collection#reverse
Dan Kubb authored
734 alias default_order key
735
179820a Renamed Resource::ClassMethods#resource_name as #storage_name
Dan Kubb authored
736 def inheritance_property(repository_name = default_repository_name)
ce0c4dc Optimizations and updated performance benchmarks
Dan Kubb authored
737 @properties[repository_name].inheritance_property
e58ed2e @sam Lots and lots of changes to move things over to the new Resource module,...
sam authored
738 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
739
1055bc4 @sam Some work on optimistic locking. Unfinished, but specs pass now.
sam authored
740 def get(*key)
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
741 repository.identity_map(self).get(key) || first(to_query(repository, key))
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
742 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
743
aca19bc Added Collection#get and Collection#get!
Dan Kubb authored
744 def get!(*key)
745 get(*key) || raise(ObjectNotFoundError, "Could not find #{self.name} with key #{key.inspect}")
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made the...
Bauerpauer authored
746 end
0ab12b1 Updated Rakefile to catch exceptions if Yard not properly loaded
Dan Kubb authored
747
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
748 def all(query = {})
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
749 query = scoped_query(query)
750 query.repository.read_many(query)
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
751 end
752
753 def first(*args)
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
754 query = args.last.respond_to?(:merge) ? args.pop : {}
755 query = scoped_query(query.merge(:limit => args.first || 1))
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
756
757 if args.any?
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
758 query.repository.read_many(query)
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
759 else
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
760 query.repository.read_one(query)
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
761 end
762 end
763
aca19bc Added Collection#get and Collection#get!
Dan Kubb authored
764 def [](*key)
998be8c Changed deprecated Model[key] to Model.get!(key) in specs
Dan Kubb authored
765 warn("#{name}[] is deprecated. Use #{name}.get! instead.")
aca19bc Added Collection#get and Collection#get!
Dan Kubb authored
766 get!(*key)
c7a1aa5 @sam Resource::[] is deprecated in favor of Resource::get!.
sam authored
767 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
768
3badf46 Updated Query#update to overwrite non-default values
Dan Kubb authored
769 def first_or_create(query, attributes = {})
770 first(query) || begin
8709c1f @sam Added Resource::first_or_create
sam authored
771 resource = allocate
3badf46 Updated Query#update to overwrite non-default values
Dan Kubb authored
772 query = query.dup
0ab12b1 Updated Rakefile to catch exceptions if Yard not properly loaded
Dan Kubb authored
773
5990fda Added repository name as an argument to methods where it is optional
Dan Kubb authored
774 properties(repository.name).key.each do |property|
3badf46 Updated Query#update to overwrite non-default values
Dan Kubb authored
775 if value = query.delete(property.name)
8709c1f @sam Added Resource::first_or_create
sam authored
776 resource.send("#{property.name}=", value)
777 end
778 end
0ab12b1 Updated Rakefile to catch exceptions if Yard not properly loaded
Dan Kubb authored
779
3badf46 Updated Query#update to overwrite non-default values
Dan Kubb authored
780 resource.attributes = query.merge(attributes)
8709c1f @sam Added Resource::first_or_create
sam authored
781 resource.save
782 resource
783 end
784 end
0ab12b1 Updated Rakefile to catch exceptions if Yard not properly loaded
Dan Kubb authored
785
15f56b7 more resolution
Adam French authored
786 ##
787 # Create an instance of Resource with the given attributes
788 #
789 # @param <Hash(Symbol => Object)> attributes hash of attributes to set
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
790 def create(attributes = {})
c073732 Updated Repository to be a thinner wrapper around the adapter
Dan Kubb authored
791 resource = new(attributes)
3c6260e @sam Resource::create should just return the instance created.
sam authored
792 resource.save
793 resource
1aa8977 @david Added #create.
david authored
794 end
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
795
15f56b7 more resolution
Adam French authored
796 ##
797 # Dangerous version of #create. Raises if there is a failure
798 #
799 # @see DataMapper::Resource#create
800 # @param <Hash(Symbol => Object)> attributes hash of attributes to set
801 # @raise <PersistenceError> The resource could not be saved
456b9ca Updated automigration integrations specs to check every primitive
Dan Kubb authored
802 def create!(attributes = {})
803 resource = create(attributes)
2e143d0 @sam I think STI should be pretty much working now.
sam authored
804 raise PersistenceError, "Resource not saved: :new_record => #{resource.new_record?}, :dirty_attributes => #{resource.dirty_attributes.inspect}" if resource.new_record?
805 resource
806 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
807
9cbadc7 @sam An idea I wanted to get into the API...
sam authored
808 # TODO SPEC
3badf46 Updated Query#update to overwrite non-default values
Dan Kubb authored
809 def copy(source, destination, query = {})
9cbadc7 @sam An idea I wanted to get into the API...
sam authored
810 repository(destination) do
1279f9f Major Repository API change
Dan Kubb authored
811 repository(source).read_many(query).each do |resource|
ce0c4dc Optimizations and updated performance benchmarks
Dan Kubb authored
812 self.create(resource)
9cbadc7 @sam An idea I wanted to get into the API...
sam authored
813 end
814 end
815 end
2514de1 Changed the Thread.current hash keys to use the dm prefix
Dan Kubb authored
816
d294bac Updated Adapter API
Dan Kubb authored
817 # @private
818 # TODO: spec this
819 def load(values, query)
820 repository = query.repository
5ed6c20 Optimized Model#load
Dan Kubb authored
821 model = self
d294bac Updated Adapter API
Dan Kubb authored
822
823 if inheritance_property_index = query.inheritance_property_index(repository)
77ed0a7 Fixed Model#load error when discriminator value is nil [#380]
Dan Kubb authored
824 model = values.at(inheritance_property_index) || model
d294bac Updated Adapter API
Dan Kubb authored
825 end
826
827 if key_property_indexes = query.key_property_indexes(repository)
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
828 key_values = values.values_at(*key_property_indexes)
829 identity_map = repository.identity_map(model)
d294bac Updated Adapter API
Dan Kubb authored
830
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
831 if resource = identity_map.get(key_values)
d294bac Updated Adapter API
Dan Kubb authored
832 return resource unless query.reload?
833 else
5ed6c20 Optimized Model#load
Dan Kubb authored
834 resource = model.allocate
d294bac Updated Adapter API
Dan Kubb authored
835 resource.instance_variable_set(:@repository, repository)
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
836 identity_map.set(key_values, resource)
d294bac Updated Adapter API
Dan Kubb authored
837 end
838 else
5ed6c20 Optimized Model#load
Dan Kubb authored
839 resource = model.allocate
d294bac Updated Adapter API
Dan Kubb authored
840 resource.readonly!
841 end
842
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
843 resource.instance_variable_set(:@new_record, false)
844
d294bac Updated Adapter API
Dan Kubb authored
845 query.fields.zip(values) do |property,value|
846 value = property.custom? ? property.type.load(value, property) : property.typecast(value)
cdd64b7 Refactored Resource#attribute_get and #attribute_set
Dan Kubb authored
847 property.set!(resource, value)
d294bac Updated Adapter API
Dan Kubb authored
848
849 if track = property.track
850 case track
851 when :hash
852 resource.original_values[property.name] = value.dup.hash unless resource.original_values.has_key?(property.name) rescue value.hash
853 when :load
854 resource.original_values[property.name] = value unless resource.original_values.has_key?(property.name)
855 end
856 end
857 end
858
859 resource
860 end
861
862 # TODO: spec this
863 def to_query(repository, key, query = {})
864 conditions = Hash[ *self.key(repository.name).zip(key).flatten ]
865 Query.new(repository, self, query.merge(conditions))
866 end
867
2514de1 Changed the Thread.current hash keys to use the dm prefix
Dan Kubb authored
868 private
869
867d311 Made it easy to let Resources use other bases than their class name for ...
Martin Kihlgren authored
870 def default_storage_name
871 self.name
872 end
873
989297b Make Resource.default_repository_name private
Dan Kubb authored
874 def default_repository_name
875 Repository.default_name
876 end
877
8098fd4 Typecast attributes when set
Dan Kubb authored
878 def scoped_query(query = self.query)
8b3eed8 Refactored type assertion code into assert_kind_of helper method
Dan Kubb authored
879 assert_kind_of 'query', query, Query, Hash
880
8098fd4 Typecast attributes when set
Dan Kubb authored
881 return self.query if query == self.query
882
1279f9f Major Repository API change
Dan Kubb authored
883 query = if query.kind_of?(Hash)
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
884 Query.new(query.has_key?(:repository) ? query.delete(:repository) : self.repository, self, query)
1279f9f Major Repository API change
Dan Kubb authored
885 else
8b3eed8 Refactored type assertion code into assert_kind_of helper method
Dan Kubb authored
886 query
1279f9f Major Repository API change
Dan Kubb authored
887 end
888
889 self.query ? self.query.merge(query) : query
890 end
891
8b3eed8 Refactored type assertion code into assert_kind_of helper method
Dan Kubb authored
892 # defines the getter for the property
893 def create_property_getter(property)
894 class_eval <<-EOS, __FILE__, __LINE__
895 #{property.reader_visibility}
896 def #{property.getter}
897 attribute_get(#{property.name.inspect})
898 end
899 EOS
900
901 if property.primitive == TrueClass && !property.model.instance_methods.include?(property.name.to_s)
902 class_eval <<-EOS, __FILE__, __LINE__
903 #{property.reader_visibility}
904 alias #{property.name} #{property.getter}
905 EOS
906 end
907 end
908
909 # defines the setter for the property
910 def create_property_setter(property)
911 unless instance_methods.include?(property.name.to_s + '=')
912 class_eval <<-EOS, __FILE__, __LINE__
913 #{property.writer_visibility}
914 def #{property.name}=(value)
915 attribute_set(#{property.name.inspect}, value)
916 end
917 EOS
918 end
919 end
920
2514de1 Changed the Thread.current hash keys to use the dm prefix
Dan Kubb authored
921 def method_missing(method, *args, &block)
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
922 if relationship = relationships(repository.name)[method]
e7fd112 Start of Query::Path fix for modular model names
Guy van den Berg authored
923 clazz = if self == relationship.child_model
924 relationship.parent_model
925 else
926 relationship.child_model
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
927 end
e7fd112 Start of Query::Path fix for modular model names
Guy van den Berg authored
928 return DataMapper::Query::Path.new(repository, [relationship],clazz)
2514de1 Changed the Thread.current hash keys to use the dm prefix
Dan Kubb authored
929 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
930
2514de1 Changed the Thread.current hash keys to use the dm prefix
Dan Kubb authored
931 if property = properties(repository.name)[method]
932 return property
933 end
934 super
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
935 end
ef642f3 Optimize Model#first, Model#all and Collection#all
Dan Kubb authored
936
937 # TODO: move to dm-more/dm-migrations
938 module Migration
939 # TODO: move to dm-more/dm-migrations
940 def storage_exists?(repository_name = default_repository_name)
941 repository(repository_name).storage_exists?(storage_name(repository_name))
942 end
943 end # module Migration
944
945 include Migration
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataMapp...
myabc authored
946 end # module ClassMethods
947 end # module Resource
948 end # module DataMapper
Something went wrong with that request. Please try again.