Skip to content
Newer
Older
100644 1055 lines (943 sloc) 27.4 KB
e8b4f3b @sam Importing from old repository.
sam authored
1 module DataMapper
2 module Resource
bc3dd47 Initial commit of new Many To Many Relationship
Dan Kubb authored
3 include Extlib::Assertions
ecb4765 Made Resource#save chainable for easier extending in plugins
Dan Kubb authored
4 extend Chainable
d41858a @dkubb Added DM::Deprecate::deprecate() to mark methods as deprecated
dkubb authored
5 extend Deprecate
6
7 deprecate :new_record?, :new?
182e590 Minor code cleanup
Dan Kubb authored
8
27c926a @dkubb Stubbed out @api and other docs for several classes
dkubb authored
9 # @deprecated
ffa83a4 @sam Fixed autotest support, corrected some issues with reloading models.
sam authored
10 def self.append_inclusions(*inclusions)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
11 warn "DataMapper::Resource.append_inclusions is deprecated, use DataMapper::Model.append_inclusions instead (#{caller[0]})"
76a7974 Minor code reformatting
Dan Kubb authored
12 Model.append_inclusions(*inclusions)
ffa83a4 @sam Fixed autotest support, corrected some issues with reloading models.
sam authored
13 end
7e45d1a Stripped whitespace with "sake strip"
Dan Kubb authored
14
27c926a @dkubb Stubbed out @api and other docs for several classes
dkubb authored
15 # @deprecated
ffa83a4 @sam Fixed autotest support, corrected some issues with reloading models.
sam authored
16 def self.extra_inclusions
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
17 warn "DataMapper::Resource.extra_inclusions is deprecated, use DataMapper::Model.extra_inclusions instead (#{caller[0]})"
76a7974 Minor code reformatting
Dan Kubb authored
18 Model.extra_inclusions
19 end
20
27c926a @dkubb Stubbed out @api and other docs for several classes
dkubb authored
21 # @deprecated
76a7974 Minor code reformatting
Dan Kubb authored
22 def self.descendants
491bd1e @dbussink Improve deprecation messages I encountered during upgrading to 0.10
dbussink authored
23 warn "DataMapper::Resource.descendants is deprecated, use DataMapper::Model.descendants instead (#{caller[0]})"
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
24 Model.descendants
ffa83a4 @sam Fixed autotest support, corrected some issues with reloading models.
sam authored
25 end
7e45d1a Stripped whitespace with "sake strip"
Dan Kubb authored
26
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
27 # Deprecated API for updating attributes and saving Resource
28 #
29 # @see #update
30 #
67fbf33 @dkubb Tagged Resource#update_attributes as deprecated
dkubb authored
31 # @deprecated
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
32 def update_attributes(attributes = {}, *allowed)
d85c0af @dkubb Updated Resource#assert_update_clean_only to include the class/method…
dkubb authored
33 assert_update_clean_only(:update_attributes)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
34
35 warn "#{model}#update_attributes is deprecated, use #{model}#update instead (#{caller[0]})"
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
36
37 if allowed.any?
38 warn "specifying allowed in #{model}#update_attributes is deprecated, " \
88612ef @dkubb Add caller information to all deprecation warnings
dkubb authored
39 "use Hash#only to filter the attributes in the caller (#{caller[0]})"
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
40 attributes = attributes.only(*allowed)
41 end
42
43 update(attributes)
44 end
45
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
46 # Makes sure a class gets all the methods when it includes Resource
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
47 #
c5ecb84 moving/rewriting docs in newest yard style
Adam French authored
48 # @api private
74ef620 Modules now push themselves into Resource rather than it pulling them
Dan Kubb authored
49 def self.included(model)
e41f6ab Renamed Resource::ClassMethods to Model
Dan Kubb authored
50 model.extend Model
748b8d9 Enabled DataMapper::Resource to know what classes have included it.
Martin Kihlgren authored
51 end
52
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
53 # @api public
7361467 @michaelklishin Use alias_method so Emacs' ruby-mode don't consider 'class' a new ind…
michaelklishin authored
54 alias_method :model, :class
6db24c7 Small performance optimizations
Dan Kubb authored
55
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
56 # Repository this resource belongs to in the context of this collection
57 # or of the resource's class.
58 #
59 # @return [Repository]
60 # the respository this resource belongs to, in the context of
61 # a collection OR in the instance's Model's context
62 #
63 # @api semipublic
64 def repository
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
65 # only set @_repository explicitly when persisted
66 defined?(@_repository) ? @_repository : model.repository
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
67 end
68
69 # Retrieve the key(s) for this resource.
70 #
71 # This always returns the persisted key value,
72 # even if the key is changed and not yet persisted.
73 # This is done so all relations still work.
74 #
75 # @return [Array(Key)]
76 # the key(s) identifying this resource
77 #
78 # @api public
79 def key
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
80 return @_key if defined?(@_key)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
81
a105712 @dkubb Added PropertySet#valid? and refactored code that tests key validity
dkubb authored
82 model_key = model.key(repository_name)
83
84 key = model_key.map do |property|
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
85 original_attributes[property] || (property.loaded?(self) ? property.get!(self) : nil)
86 end
87
a105712 @dkubb Added PropertySet#valid? and refactored code that tests key validity
dkubb authored
88 # only memoize a valid key
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
89 @_key = key if model_key.valid?(key)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
90 end
91
92 # Checks if this Resource instance is new
93 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
94 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
95 # true if the resource is new and not saved
96 #
97 # @api public
98 def new?
99 !saved?
100 end
101
102 # Checks if this Resource instance is saved
103 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
104 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
105 # true if the resource has been saved
106 #
107 # @api public
108 def saved?
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
109 @_saved == true
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
110 end
111
19baffc @dkubb Added Resource#destroyed?
dkubb authored
112 # Checks if this Resource instance is destroyed
113 #
114 # @return [Boolean]
115 # true if the resource has been destroyed
116 #
117 # @api public
118 def destroyed?
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
119 @_destroyed == true
19baffc @dkubb Added Resource#destroyed?
dkubb authored
120 end
121
5dc4838 @dkubb Updated Collection#update and #update! to raise an exception when cal…
dkubb authored
122 # Checks if the resource has no changes to save
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
123 #
124 # @return [Boolean]
125 # true if the resource may not be persisted
126 #
127 # @api public
128 def clean?
129 !dirty?
130 end
131
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
132 # Checks if the resource has unsaved changes
133 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
134 # @return [Boolean]
135 # true if resource may be persisted
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
136 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
137 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
138 def dirty?
6a6add4 @dkubb Ensure Collection#first and Collection#last always return the same in…
dkubb authored
139 run_once(true) do
140 dirty_self? || dirty_parents? || dirty_children?
141 end
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
142 end
143
88fa9a6 @dkubb Added Resource#readonly?
dkubb authored
144 # Checks if this Resource instance is readonly
145 #
146 # @return [Boolean]
147 # true if the resource cannot be persisted
148 #
149 # @api public
150 def readonly?
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
151 @_readonly == true
88fa9a6 @dkubb Added Resource#readonly?
dkubb authored
152 end
153
6186835 Stripped whitespace
Dan Kubb authored
154 # Returns the value of the attribute.
155 #
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
156 # Do not read from instance variables directly, but use this method.
157 # This method handles lazy loading the attribute and returning of
158 # defaults if nessesary.
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
159 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
160 # @example
161 # class Foo
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
162 # include DataMapper::Resource
163 #
164 # property :first_name, String
76a7974 Minor code reformatting
Dan Kubb authored
165 # property :last_name, String
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
166 #
167 # def full_name
168 # "#{attribute_get(:first_name)} #{attribute_get(:last_name)}"
169 # end
170 #
171 # # using the shorter syntax
172 # def name_for_address_book
173 # "#{last_name}, #{first_name}"
174 # end
175 # end
176 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
177 # @param [Symbol] name
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
178 # name of attribute to retrieve
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
179 #
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
180 # @return [Object]
181 # the value stored at that given attribute
182 # (nil if none, and default if necessary)
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
183 #
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
184 # @api public
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
185 def attribute_get(name)
84880f2 Simplified Resource#attribute_get
Dan Kubb authored
186 properties[name].get(self)
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
187 end
188
1c119a2 Added Resource#[] and #[]= as aliases for #attribute_get and #attribu…
Dan Kubb authored
189 alias [] attribute_get
190
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
191 # Sets the value of the attribute and marks the attribute as dirty
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
192 # if it has been changed so that it may be saved. Do not set from
193 # instance variables directly, but use this method. This method
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
194 # handles the lazy loading the property and returning of defaults
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
195 # if nessesary.
196 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
197 # @example
198 # class Foo
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
199 # include DataMapper::Resource
200 #
201 # property :first_name, String
76a7974 Minor code reformatting
Dan Kubb authored
202 # property :last_name, String
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
203 #
204 # def full_name(name)
205 # name = name.split(' ')
206 # attribute_set(:first_name, name[0])
207 # attribute_set(:last_name, name[1])
208 # end
209 #
210 # # using the shorter syntax
211 # def name_from_address_book(name)
212 # name = name.split(', ')
213 # first_name = name[1]
214 # last_name = name[0]
215 # end
216 # end
217 #
2e14f81 Small cleanup of YARD doc formatting in Resource.
Emmanuel Gomez authored
218 # @param [Symbol] name
219 # name of attribute to set
220 # @param [Object] value
221 # value to store
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
222 #
2e14f81 Small cleanup of YARD doc formatting in Resource.
Emmanuel Gomez authored
223 # @return [Object]
224 # the value stored at that given attribute, nil if none,
225 # and default if necessary
25e6fe5 @emmanuel Began updating Resource API docs to YARD format (still in progress).
emmanuel authored
226 #
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
227 # @api public
fa3f914 Updated Resource#attribute_get and #attribute_set be public again
Dan Kubb authored
228 def attribute_set(name, value)
229 properties[name].set(self, value)
230 end
231
1c119a2 Added Resource#[] and #[]= as aliases for #attribute_get and #attribu…
Dan Kubb authored
232 alias []= attribute_set
233
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
234 # Gets all the attributes of the Resource instance
78daf51 @advany add docs to DataMapper::Resource
advany authored
235 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
236 # @param [Symbol] key_on
237 # Use this attribute of the Property as keys.
238 # defaults to :name. :field is useful for adapters
239 # :property or nil use the actual Property object.
78daf51 @advany add docs to DataMapper::Resource
advany authored
240 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
241 # @return [Hash]
242 # All the attributes
78daf51 @advany add docs to DataMapper::Resource
advany authored
243 #
c5ecb84 moving/rewriting docs in newest yard style
Adam French authored
244 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
245 def attributes(key_on = :name)
246 attributes = {}
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
247
248 lazy_load(properties)
249 fields.each do |property|
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
250 if model.public_method_defined?(name = property.name)
251 key = case key_on
252 when :name then name
253 when :field then property.field
254 else property
255 end
b050d8f Unrolled if/unless conditions to allow easier coverage testing
Dan Kubb authored
256
c1e78c6 @dkubb Use Resource#__send__ instead of #send in case it is overridden
dkubb authored
257 attributes[key] = __send__(name)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
258 end
b050d8f Unrolled if/unless conditions to allow easier coverage testing
Dan Kubb authored
259 end
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
260
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
261 attributes
e5847b9 Updated Collection to implement an interface similar to Array
Dan Kubb authored
262 end
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
263
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
264 # Assign values to multiple attributes in one call (mass assignment)
0cdf41a Updated Resource#eql? to be strict match
Dan Kubb authored
265 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
266 # @param [Hash] attributes
267 # names and values of attributes to assign
0cdf41a Updated Resource#eql? to be strict match
Dan Kubb authored
268 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
269 # @return [Hash]
270 # names and values of attributes assigned
0cdf41a Updated Resource#eql? to be strict match
Dan Kubb authored
271 #
272 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
273 def attributes=(attributes)
274 attributes.each do |name, value|
275 case name
276 when String, Symbol
277 if model.public_method_defined?(setter = "#{name}=")
c1e78c6 @dkubb Use Resource#__send__ instead of #send in case it is overridden
dkubb authored
278 __send__(setter, value)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
279 else
978c81a @dkubb Minor update to error message for unknown attribute in Resource#attri…
dkubb authored
280 raise ArgumentError, "The attribute '#{name}' is not accessible in #{model}"
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
281 end
282 when Associations::Relationship, Property
283 name.set(self, value)
284 end
b050d8f Unrolled if/unless conditions to allow easier coverage testing
Dan Kubb authored
285 end
0cdf41a Updated Resource#eql? to be strict match
Dan Kubb authored
286 end
e5847b9 Updated Collection to implement an interface similar to Array
Dan Kubb authored
287
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
288 # Reloads association and all child association
238682e Added Resource#<=>
Dan Kubb authored
289 #
6f57483 @dkubb Updated Resource#reload to clear non-key property and relationship ivars
dkubb authored
290 # This is accomplished by resetting the Resource key to it's
291 # original value, and then removing all the ivars for properties
292 # and relationships. On the next access of those ivars, the
293 # resource will eager load what it needs. While this is more of
294 # a lazy reload, it should result is more consistent behavior
295 # since no cached results will remain from the initial load.
296 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
297 # @return [Resource]
298 # the receiver, the current Resource instance
238682e Added Resource#<=>
Dan Kubb authored
299 #
300 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
301 def reload
6f57483 @dkubb Updated Resource#reload to clear non-key property and relationship ivars
dkubb authored
302 if key
303 reset_key
304 clear_subjects
238682e Added Resource#<=>
Dan Kubb authored
305 end
306
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
307 self
7b6845d Minor code refactoring
Dan Kubb authored
308 end
309
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
310 # Updates attributes and saves this Resource instance
78daf51 @advany add docs to DataMapper::Resource
advany authored
311 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
312 # @param [Hash] attributes
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
313 # attributes to be updated
6186835 Stripped whitespace
Dan Kubb authored
314 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
315 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
316 # true if resource and storage state match
78daf51 @advany add docs to DataMapper::Resource
advany authored
317 #
c5ecb84 moving/rewriting docs in newest yard style
Adam French authored
318 # @api public
639f435 @dkubb Minor simplifications of Resource
dkubb authored
319 def update(attributes = {})
320 assert_update_clean_only(:update)
321 self.attributes = attributes
322 save
d409c1f @sam Added and specced LoadedSet.
sam authored
323 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
324
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
325 # Updates attributes and saves this Resource instance, bypassing hooks
6186835 Stripped whitespace
Dan Kubb authored
326 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
327 # @param [Hash] attributes
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
328 # attributes to be updated
dfac1c5 @dbussink Add more shared Resource specs
dbussink authored
329 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
330 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
331 # true if resource and storage state match
dfac1c5 @dbussink Add more shared Resource specs
dbussink authored
332 #
333 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
334 def update!(attributes = {})
d85c0af @dkubb Updated Resource#assert_update_clean_only to include the class/method…
dkubb authored
335 assert_update_clean_only(:update!)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
336 self.attributes = attributes
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
337 save!
a519fb4 @sam CRUD in DataObjectAdapter is mostly done. There appears to be a bug i…
sam authored
338 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
339
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
340 # Save the instance and loaded, dirty associations to the data-store
78daf51 @advany add docs to DataMapper::Resource
advany authored
341 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
342 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
343 # true if Resource instance and all associations were saved
78daf51 @advany add docs to DataMapper::Resource
advany authored
344 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
345 # @api public
1f9eed1 @dkubb Refactored Resource#save and Resource#dirty to handle circular depend…
dkubb authored
346 def save
7b1b917 @dkubb Moved assertions closer to the methods they should be called in
dkubb authored
347 assert_not_destroyed(:save)
1f9eed1 @dkubb Refactored Resource#save and Resource#dirty to handle circular depend…
dkubb authored
348 _save(true)
041d9f1 @sam DataObjectAdapter sqlite3 integration spec passes for #create.
sam authored
349 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
350
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
351 # Save the instance and loaded, dirty associations to the data-store, bypassing hooks
78daf51 @advany add docs to DataMapper::Resource
advany authored
352 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
353 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
354 # true if Resource instance and all associations were saved
78daf51 @advany add docs to DataMapper::Resource
advany authored
355 #
c5ecb84 moving/rewriting docs in newest yard style
Adam French authored
356 # @api public
1f9eed1 @dkubb Refactored Resource#save and Resource#dirty to handle circular depend…
dkubb authored
357 def save!
7b1b917 @dkubb Moved assertions closer to the methods they should be called in
dkubb authored
358 assert_not_destroyed(:save!)
1f9eed1 @dkubb Refactored Resource#save and Resource#dirty to handle circular depend…
dkubb authored
359 _save(false)
ece0d18 @somebee some small convenient changes. added possibility for iterating throug…
somebee authored
360 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
361
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
362 # Destroy the instance, remove it from the repository
4d8e324 Added Resource#new? and Resource#saved?
Dan Kubb authored
363 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
364 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
365 # true if resource was destroyed
4d8e324 Added Resource#new? and Resource#saved?
Dan Kubb authored
366 #
367 # @api public
639f435 @dkubb Minor simplifications of Resource
dkubb authored
368 def destroy
369 destroy!
4d8e324 Added Resource#new? and Resource#saved?
Dan Kubb authored
370 end
371
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
372 # Destroy the instance, remove it from the repository, bypassing hooks
4d8e324 Added Resource#new? and Resource#saved?
Dan Kubb authored
373 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
374 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
375 # true if resource was destroyed
805e402 @myabc YARD conversion for dm-core
myabc authored
376 #
c5ecb84 moving/rewriting docs in newest yard style
Adam French authored
377 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
378 def destroy!
ca8aa59 @dkubb Resource#update and Resource#destroy should be idempotent
dkubb authored
379 if saved? && !destroyed?
380 repository.delete(collection_for_self)
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
381 @_destroyed = true
382 @_readonly = true
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
383 reset
384 end
19baffc @dkubb Added Resource#destroyed?
dkubb authored
385
386 destroyed?
320fb84 @Bauerpauer Added a couple api-check specs. Restored Resource#new_record?. Made t…
Bauerpauer authored
387 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
388
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
389 # Compares another Resource for equality
40fcf73 Stripped whitespace
Dan Kubb authored
390 #
567d41c @dkubb Updated Resource#== to not test the type
dkubb authored
391 # Resource is equal to +other+ if they are the same object
392 # (identical object_id) or if they are both of the *same model* and
393 # all of their attributes are equivalent
c53a629 Updated property type to use Integer instead of Fixnum internally
Dan Kubb authored
394 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
395 # @param [Resource] other
396 # the other Resource to compare with
6186835 Stripped whitespace
Dan Kubb authored
397 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
398 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
399 # true if they are equal, false if not
78daf51 @advany add docs to DataMapper::Resource
advany authored
400 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
401 # @api public
402 def eql?(other)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
403 return true if equal?(other)
30bda1f @dkubb Simplified comparison methods
dkubb authored
404 instance_of?(other.class) && cmp?(other, :eql?)
e58ed2e @sam Lots and lots of changes to move things over to the new Resource modu…
sam authored
405 end
1260c12 Updated Resource#initialize to always validate the resource
Dan Kubb authored
406
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
407 # Compares another Resource for equivalency
6186835 Stripped whitespace
Dan Kubb authored
408 #
567d41c @dkubb Updated Resource#== to not test the type
dkubb authored
409 # Resource is equivalent to +other+ if they are the same object
410 # (identical object_id) or all of their attribute are equivalent
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
411 #
412 # @param [Resource] other
413 # the other Resource to compare with
414 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
415 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
416 # true if they are equivalent, false if not
6186835 Stripped whitespace
Dan Kubb authored
417 #
d3183e6 Deprecated Resource#update_attributes and renamed as Resource#update
Dan Kubb authored
418 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
419 def ==(other)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
420 return true if equal?(other)
567d41c @dkubb Updated Resource#== to not test the type
dkubb authored
421 other.respond_to?(:repository) &&
422 other.respond_to?(:key) &&
423 other.respond_to?(:clean?) &&
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
424 cmp?(other, :==)
d3183e6 Deprecated Resource#update_attributes and renamed as Resource#update
Dan Kubb authored
425 end
426
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
427 # Compares two Resources to allow them to be sorted
72db385 @advany update_attributes should save model
advany authored
428 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
429 # @param [Resource] other
430 # The other Resource to compare with
78daf51 @advany add docs to DataMapper::Resource
advany authored
431 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
432 # @return [Integer]
433 # Return 0 if Resources should be sorted as the same, -1 if the
434 # other Resource should be after self, and 1 if the other Resource
435 # should be before self
72db385 @advany update_attributes should save model
advany authored
436 #
8708119 @myabc Convert docs to YARD-style
myabc authored
437 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
438 def <=>(other)
5bfb4f3 @dkubb Allow instances of the same base model to be comparable
dkubb authored
439 unless other.kind_of?(model.base_model)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
440 raise ArgumentError, "Cannot compare a #{other.model} instance with a #{model} instance"
441 end
442 cmp = 0
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
443 model.default_order(repository_name).each do |direction|
e212100 @dkubb Use Query::Sort when sorting resources
dkubb authored
444 cmp = direction.get(self) <=> direction.get(other)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
445 break if cmp != 0
446 end
447 cmp
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
448 end
d3183e6 Deprecated Resource#update_attributes and renamed as Resource#update
Dan Kubb authored
449
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
450 # Returns hash value of the object.
451 # Two objects with the same hash value assumed equal (using eql? method)
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
452 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
453 # DataMapper resources are equal when their models have the same hash
454 # and they have the same set of properties
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
455 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
456 # When used as key in a Hash or Hash subclass, objects are compared
457 # by eql? and thus hash value has direct effect on lookup
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
458 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
459 # @api private
460 def hash
461 key.hash
1019ac3 @sam Added key validation to Resources, and added Resource#update_attributes.
sam authored
462 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
463
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
464 # Get a Human-readable representation of this Resource instance
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
465 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
466 # Foo.new #=> #<Foo name=nil updated_at=nil created_at=nil id=nil>
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
467 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
468 # @return [String]
469 # Human-readable representation of this Resource instance
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
470 #
471 # @api public
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
472 def inspect
473 # TODO: display relationship values
474 attrs = properties.map do |property|
475 value = if new? || property.loaded?(self)
476 property.get!(self).inspect
477 else
478 '<not loaded>'
479 end
480
481 "#{property.instance_variable_name}=#{value}"
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
482 end
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
483
484 "#<#{model.name} #{attrs.join(' ')}>"
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
485 end
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
486
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
487 # Hash of original values of attributes that have unsaved changes
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
488 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
489 # @return [Hash]
490 # original values of attributes that have unsaved changes
491 #
492 # @api semipublic
493 def original_attributes
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
494 @_original_attributes ||= {}
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
495 end
496
497 # Checks if an attribute has been loaded from the repository
498 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
499 # @example
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
500 # class Foo
501 # include DataMapper::Resource
502 #
503 # property :name, String
504 # property :description, Text, :lazy => false
505 # end
506 #
507 # Foo.new.attribute_loaded?(:description) #=> false
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
508 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
509 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
510 # true if ivar +name+ has been loaded
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
511 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
512 # @return [Boolean]
513 # true if ivar +name+ has been loaded
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
514 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
515 # @api private
516 def attribute_loaded?(name)
517 properties[name].loaded?(self)
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
518 end
519
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
520 # Checks if an attribute has unsaved changes
521 #
522 # @param [Symbol] name
523 # name of attribute to check for unsaved changes
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
524 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
525 # @return [Boolean]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
526 # true if attribute has unsaved changes
65c1174 @dkubb Updated Collection#update! and #destroy! to work with limited collect…
dkubb authored
527 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
528 # @api semipublic
529 def attribute_dirty?(name)
530 dirty_attributes.key?(properties[name])
45bbaf1 Group Resource#save and Resource#destroy near other persistence methods
Dan Kubb authored
531 end
532
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
533 # Hash of attributes that have unsaved changes
f132afb @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
534 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
535 # @return [Hash]
536 # attributes that have unsaved changes
f132afb @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
537 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
538 # @api semipublic
539 def dirty_attributes
540 dirty_attributes = {}
541
542 original_attributes.each_key do |property|
543 dirty_attributes[property] = property.value(property.get!(self))
544 end
545
546 dirty_attributes
e3ad4a2 Improved the transactional system greatly and introduced two-phase
Martin Kihlgren authored
547 end
548
5e7d549 @michaelklishin Improve documentation of DataMapper::Resource#reset
michaelklishin authored
549 # Reset the Resource to a similar state as a new record:
550 # removes it from identity map and clears original property
551 # values (thus making all properties non dirty)
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
552 #
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
553 # @api private
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
554 def reset
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
555 @_saved = false
8a1894d Updated specs to pass with all adapters, even the Yaml adapter
Dan Kubb authored
556 identity_map.delete(key)
8ca9812 @dkubb Renamed Resource#original_values as Resource#original_attributes
dkubb authored
557 original_attributes.clear
28321b3 @dkubb Refactored ManyToMany relationship
dkubb authored
558 self
3684f20 Minor Resource cleanup
Dan Kubb authored
559 end
560
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
561 # Returns the Collection the Resource is associated with
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
562 #
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
563 # @return [nil]
564 # nil if this is a new record
565 # @return [Collection]
566 # a Collection that self belongs to
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
567 #
568 # @api private
569 def collection
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
570 return @_collection if (@_collection && @_collection.query.conditions.matches?(self)) || new? || readonly?
cdb918f @dkubb Refactored SEL behavior of Collections
dkubb authored
571 collection_for_self
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
572 end
573
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
574 # Associates a Resource to a Collection
575 #
576 # @param [Collection, nil] collection
577 # the collection to associate the resource with
578 #
579 # @return [nil]
580 # nil if this is a new record
581 # @return [Collection]
582 # a Collection that self belongs to
583 #
584 # @api private
585 def collection=(collection)
586 @_collection = collection
587 end
588
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
589 protected
ec84ce4 @myabc Stripped whitespace with "sake strip"
myabc authored
590
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
591 # Method for hooking callbacks on resource creation
a108799 @dkubb Delegate Resource#save and #update to #save! and #update!
dkubb authored
592 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
593 # @return [Boolean]
594 # true if the create was successful, false if not
6186835 Stripped whitespace
Dan Kubb authored
595 #
dc22e45 @dkubb Updated ManyToMany::Collection#update! to act more like Collection#up…
dkubb authored
596 # @api private
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
597 def create_hook
598 _create
e58ed2e @sam Lots and lots of changes to move things over to the new Resource modu…
sam authored
599 end
15987f0 @david Merge branch 'master' of git@github.com:sam/dm-core
david authored
600
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
601 # Method for hooking callbacks on resource updates
ee967c0 @michaelklishin Document DataMapper::Resource#_update
michaelklishin authored
602 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
603 # @return [Boolean]
604 # true if the update was successful, false if not
c031e9f @michaelklishin Add returned value to documentation of DataMapper::Resource#_update
michaelklishin authored
605 #
dc22e45 @dkubb Updated ManyToMany::Collection#update! to act more like Collection#up…
dkubb authored
606 # @api private
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
607 def update_hook
608 _update
bc3dd47 Initial commit of new Many To Many Relationship
Dan Kubb authored
609 end
610
dc22e45 @dkubb Updated ManyToMany::Collection#update! to act more like Collection#up…
dkubb authored
611 private
612
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
613 # Initialize a new instance of this Resource using the provided values
614 #
ba3d0ca @dkubb Pass through arguments/block in Model#new to allow custom #initialize
dkubb authored
615 # @param [Hash] attributes
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
616 # attribute values to use for the new instance
617 #
ba3d0ca @dkubb Pass through arguments/block in Model#new to allow custom #initialize
dkubb authored
618 # @return [Hash]
619 # attribute values used in the new instance
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
620 #
621 # @api public
ba3d0ca @dkubb Pass through arguments/block in Model#new to allow custom #initialize
dkubb authored
622 def initialize(attributes = {}, &block) # :nodoc:
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
623 self.attributes = attributes
624 end
625
bb3b8ee @michaelklishin Document DataMapper::Resource#repository_name
michaelklishin authored
626 # Returns name of the repository this object
627 # was loaded from
628 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
629 # @return [String]
630 # name of the repository this object was loaded from
bb3b8ee @michaelklishin Document DataMapper::Resource#repository_name
michaelklishin authored
631 #
8a1894d Updated specs to pass with all adapters, even the Yaml adapter
Dan Kubb authored
632 # @api private
633 def repository_name
634 repository.name
635 end
636
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
637 # Gets this instance's Model's properties
77c0e33 Replaced "Array<Member, Classes>" type notation with "Array(Member, C…
Emmanuel Gomez authored
638 #
639 # @return [Array(Property)]
640 # List of this Resource's Model's properties
641 #
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
642 # @api private
643 def properties
8a1894d Updated specs to pass with all adapters, even the Yaml adapter
Dan Kubb authored
644 model.properties(repository_name)
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
645 end
646
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
647 # Gets this instance's Model's relationships
77c0e33 Replaced "Array<Member, Classes>" type notation with "Array(Member, C…
Emmanuel Gomez authored
648 #
649 # @return [Array(Associations::Relationship)]
650 # List of this instance's Model's Relationships
651 #
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
652 # @api private
653 def relationships
8a1894d Updated specs to pass with all adapters, even the Yaml adapter
Dan Kubb authored
654 model.relationships(repository_name)
06e66e6 Refactored Resource resetting code after destruction
Dan Kubb authored
655 end
656
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
657 # Returns the identity map for the model from the repository
4d319fb @michaelklishin Document DataMapper::Resouce#identity_map
michaelklishin authored
658 #
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
659 # @return [IdentityMap]
4d319fb @michaelklishin Document DataMapper::Resouce#identity_map
michaelklishin authored
660 # identity map of repository this object was loaded from
661 #
8a1894d Updated specs to pass with all adapters, even the Yaml adapter
Dan Kubb authored
662 # @api semipublic
663 def identity_map
664 repository.identity_map(model)
665 end
887befd Removed Hook - It has been moved to extlib
Carl Lerche authored
666
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
667 # Fetches all the names of the attributes that have been loaded,
668 # even if they are lazy but have been called
669 #
670 # @return [Array<Property>]
671 # names of attributes that have been loaded
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
672 #
673 # @api private
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
674 def fields
675 properties.select do |property|
676 property.loaded?(self) || (new? && property.default?)
677 end
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
678 end
679
6f57483 @dkubb Updated Resource#reload to clear non-key property and relationship ivars
dkubb authored
680 # Reset the key to the original value
681 #
682 # @return [undefined]
683 #
684 # @api private
685 def reset_key
686 properties.key.zip(key) do |property, value|
687 property.set!(self, value)
688 original_attributes.delete(property)
689 end
690 end
691
692 # Remove all the ivars for properties and relationships
693 #
694 # @return [undefined]
695 #
696 # @api private
697 def clear_subjects
698 model_properties = properties
699
700 (model_properties - model_properties.key | relationships.values).each do |subject|
701 next unless subject.loaded?(self)
702 remove_instance_variable(subject.instance_variable_name)
703 original_attributes.delete(subject)
704 end
705 end
706
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
707 # Lazy loads attributes not yet loaded
708 #
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
709 # @param [Array<Property>] properties
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
710 # the properties to reload
711 #
712 # @return [self]
713 #
714 # @api private
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
715 def lazy_load(properties)
716 eager_load(properties - fields)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
717 end
718
719 # Reloads specified attributes
6186835 Stripped whitespace
Dan Kubb authored
720 #
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
721 # @param [Array<Property>] properties
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
722 # the properties to reload
6186835 Stripped whitespace
Dan Kubb authored
723 #
43ce436 @emmanuel Updated Resource API docs to YARD format.
emmanuel authored
724 # @return [Resource]
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
725 # the receiver, the current Resource instance
6186835 Stripped whitespace
Dan Kubb authored
726 #
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
727 # @api private
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
728 def eager_load(properties)
729 unless properties.empty? || key.nil?
730 collection.reload(:fields => properties)
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
731 end
732
733 self
887befd Removed Hook - It has been moved to extlib
Carl Lerche authored
734 end
0ac6b42 Stripped whitespace with sake strip
Dan Kubb authored
735
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
736 # Gets a Query that will return this Resource instance
737 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
738 # @return [Query]
739 # Query that will retrieve this Resource instance
0ef5ad1 @michaelklishin Document DataMapper::Resource#lazy_load
michaelklishin authored
740 #
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
741 # @api private
c115888 @dkubb Changed Resource#to_query to #query to match conventions in Model and…
dkubb authored
742 def query
f0f8662 @dkubb Refactored Resource and Collection reloading
dkubb authored
743 Query.new(repository, model, model.key_conditions(repository, key).update(:fields => fields))
3684f20 Minor Resource cleanup
Dan Kubb authored
744 end
745
ca8aa59 @dkubb Resource#update and Resource#destroy should be idempotent
dkubb authored
746 # Return a collection including the current resource only
747 #
748 # @return [Collection]
749 # a collection containing self
750 #
751 # @api semipublic
752 def collection_for_self
753 Collection.new(query, [ self ])
754 end
755
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
756 # @api private
757 def parent_relationships
758 parent_relationships = []
759
760 relationships.each_value do |relationship|
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
761 next unless relationship.respond_to?(:resource_for) && relationship.loaded?(self) && relationship.get!(self)
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
762 parent_relationships << relationship
763 end
764
765 parent_relationships
766 end
767
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
768 # Returns loaded child relationships
cb2a5da @michaelklishin Document DataMapper::Resource#child_associations
michaelklishin authored
769 #
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
770 # @return [Array<Associations::OneToMany::Relationship>]
cb2a5da @michaelklishin Document DataMapper::Resource#child_associations
michaelklishin authored
771 # array of child relationships for which this resource is parent and is loaded
772 #
f0c4d00 Updated @api tags for Resource methods
Dan Kubb authored
773 # @api private
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
774 def child_relationships
775 child_relationships = []
9aa83de Refactored OneToMany and ManyToMany relationships
Dan Kubb authored
776
6faedbd @dkubb Updated child_associations to skip non-collection Relationship
dkubb authored
777 relationships.each_value do |relationship|
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
778 next unless relationship.respond_to?(:collection_for) && relationship.loaded?(self) && relationship.get!(self)
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
779 child_relationships << relationship
d54fbe5 @dkubb Updated ManyToMany::Collection#save to properly save intermediaries
dkubb authored
780 end
781
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
782 many_to_many, other = child_relationships.partition do |relationship|
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
783 relationship.kind_of?(Associations::ManyToMany::Relationship)
9aa83de Refactored OneToMany and ManyToMany relationships
Dan Kubb authored
784 end
785
2e1fd21 @dkubb Persist dirty parent resources when saving a Resource
dkubb authored
786 many_to_many + other
3684f20 Minor Resource cleanup
Dan Kubb authored
787 end
788
7ed6e37 @dkubb Updated Resource to be dirty when associations are dirty
dkubb authored
789 # @api private
790 def parent_resources
791 parent_relationships.map { |relationship| relationship.get!(self) }
792 end
793
794 # @api private
795 def child_collections
796 child_relationships.map { |relationship| relationship.get!(self) }
797 end
798
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
799 # Creates the resource with default values
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
800 #
801 # If resource is not dirty or a new (not yet saved),
802 # this method returns false
803 #
804 # On successful save identity map of the repository is
805 # updated
806 #
807 # Needs to be a protected method so that it is hookable
808 #
809 # The primary purpose of this method is to allow before :create
810 # hooks to fire at a point just before/after resource creation
811 #
812 # @return [Boolean]
813 # true if the receiver was successfully created
814 #
815 # @api private
816 def _create
817 # Can't create a resource that is not dirty and doesn't have serial keys
08df3a1 @dkubb Changed usage of !dirty? to clean? in Resource
dkubb authored
818 return false if new? && clean?
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
819
820 # set defaults for new resource
821 properties.each do |property|
822 unless property.serial? || property.loaded?(self)
823 property.set(self, property.default_for(self))
824 end
825 end
826
827 repository.create([ self ])
828
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
829 @_repository = repository
830 @_saved = true
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
831
832 original_attributes.clear
833
834 identity_map[key] = self
835
836 true
837 end
838
839 # Updates resource state
840 #
841 # The primary purpose of this method is to allow before :update
842 # hooks to fire at a point just before/after resource update whether
843 # it is the result of Resource#save, or using Resource#update
844 #
845 # @return [Boolean]
846 # true if the receiver was successfully created
847 #
848 # @api private
849 def _update
d85c0af @dkubb Updated Resource#assert_update_clean_only to include the class/method…
dkubb authored
850 dirty_attributes = self.dirty_attributes
851
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
852 if dirty_attributes.empty?
853 true
9aa8701 @dkubb Refactored key testing to use PropertySet#valid?
dkubb authored
854 elsif dirty_attributes.any? { |property, value| !property.valid?(value) }
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
855 false
856 else
857 # remove from the identity map
858 identity_map.delete(key)
859
ca8aa59 @dkubb Resource#update and Resource#destroy should be idempotent
dkubb authored
860 repository.update(dirty_attributes, collection_for_self)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
861
862 # remove the cached key in case it is updated
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
863 remove_instance_variable(:@_key)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
864
865 original_attributes.clear
866
867 identity_map[key] = self
868
869 true
870 end
871 end
872
1f9eed1 @dkubb Refactored Resource#save and Resource#dirty to handle circular depend…
dkubb authored
873 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
874 def _save(safe)
875 run_once(true) do
876 save_parents(safe) && save_self(safe) && save_children(safe)
877 end
6b9ab6d @dkubb A dirty sibling should not make a resource dirty
dkubb authored
878 end
879
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
880 # Saves the resource
881 #
882 # @return [Boolean]
883 # true if the resource was successfully saved
884 #
885 # @api semipublic
3f1c177 @dbussink Make safe the default if people call save_self directly
dbussink authored
886 def save_self(safe = true)
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
887 if safe
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
888 new? ? create_hook : update_hook
889 else
890 new? ? _create : _update
891 end
892 end
893
894 # Saves the parent resources
895 #
896 # @return [Boolean]
897 # true if the parents were successfully saved
898 #
899 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
900 def save_parents(safe)
901 run_once(true) do
902 parent_relationships.all? do |relationship|
903 parent = relationship.get!(self)
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
904
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
905 if parent.__send__(:save_parents, safe) && parent.__send__(:save_self, safe)
906 relationship.set(self, parent) # set the FK values
907 end
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
908 end
909 end
910 end
911
912 # Saves the children resources
913 #
914 # @return [Boolean]
915 # true if the children were successfully saved
916 #
917 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
918 def save_children(safe)
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
919 child_collections.all? do |collection|
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
920 collection.send(safe ? :save : :save!)
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
921 end
922 end
923
924 # Checks if the resource has unsaved changes
925 #
926 # @return [Boolean]
927 # true if the resource has unsaged changes
928 #
929 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
930 def dirty_self?
931 if original_attributes.any?
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
932 true
933 elsif new?
934 !model.serial.nil? || properties.any? { |property| property.default? }
935 else
936 false
937 end
938 end
939
940 # Checks if the parents have unsaved changes
941 #
942 # @return [Boolean]
943 # true if the parents have unsaved changes
944 #
945 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
946 def dirty_parents?
947 run_once(false) do
948 parent_resources.any? do |parent|
949 parent.__send__(:dirty_self?) || parent.__send__(:dirty_parents?)
950 end
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
951 end
952 end
953
954 # Checks if the children have unsaved changes
955 #
956 # @param [Hash] resources
957 # resources that have already been tested
958 #
959 # @return [Boolean]
960 # true if the children have unsaved changes
961 #
962 # @api private
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
963 def dirty_children?
964 child_collections.any? { |children| children.dirty? }
f5e8c5f @dkubb Updated saving and dirtyness internal methods to be private
dkubb authored
965 end
966
9c54f28 Added Query#update specs
Dan Kubb authored
967 # Return true if +other+'s is equivalent or equal to +self+'s
77c0e33 Replaced "Array<Member, Classes>" type notation with "Array(Member, C…
Emmanuel Gomez authored
968 #
969 # @param [Resource] other
970 # The Resource whose attributes are to be compared with +self+'s
b88cab2 Added Query semipublic specs
Dan Kubb authored
971 # @param [Symbol] operator
972 # The comparison operator to use to compare the attributes
973 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
974 # @return [Boolean]
77c0e33 Replaced "Array<Member, Classes>" type notation with "Array(Member, C…
Emmanuel Gomez authored
975 # The result of the comparison of +other+'s attributes with +self+'s
7d1befe Refactored equivalent property checks from Resource#eql? and Resource#==
Dan Kubb authored
976 #
d478c13 Minor documentation update in Resource
Dan Kubb authored
977 # @api private
9c54f28 Added Query#update specs
Dan Kubb authored
978 def cmp?(other, operator)
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
979 return false unless key.send(operator, other.key)
08df3a1 @dkubb Changed usage of !dirty? to clean? in Resource
dkubb authored
980 return true if repository.send(operator, other.repository) && clean? && other.clean?
0380616 Removed ManyToMany::Proxy (to be rebuilt)
Dan Kubb authored
981
05bae27 Refactoring to improve spec coverage
Dan Kubb authored
982 # get all the loaded and non-loaded properties that are not keys,
983 # since the key comparison was performed earlier
fe2efae @dkubb Removed most Uncommunicative Names from source
dkubb authored
984 loaded, not_loaded = properties.select { |property| !property.key? }.partition do |property|
4260cb7 Simplified Property and Resource
Dan Kubb authored
985 property.loaded?(self) && property.loaded?(other)
0380616 Removed ManyToMany::Proxy (to be rebuilt)
Dan Kubb authored
986 end
987
988 # check all loaded properties, and then all unloaded properties
fe2efae @dkubb Removed most Uncommunicative Names from source
dkubb authored
989 (loaded + not_loaded).all? { |property| property.get(self).send(operator, property.get(other)) }
7d1befe Refactored equivalent property checks from Resource#eql? and Resource#==
Dan Kubb authored
990 end
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
991
992 # Raises an exception if #update is performed on a dirty resource
993 #
f127bad @dkubb Minor cleanup to Resource lazy/eager loading logic
dkubb authored
994 # @param [Symbol] method
995 # the name of the method to use in the exception
996 #
997 # @return [undefined]
998 #
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
999 # @raise [UpdateConflictError]
1000 # raise if the resource is dirty
1001 #
1002 # @api private
d85c0af @dkubb Updated Resource#assert_update_clean_only to include the class/method…
dkubb authored
1003 def assert_update_clean_only(method)
fd88599 @dkubb Use Resource#dirty? to test for dirtyness prior to executing Resource…
dkubb authored
1004 if dirty?
d85c0af @dkubb Updated Resource#assert_update_clean_only to include the class/method…
dkubb authored
1005 raise UpdateConflictError, "#{model}##{method} cannot be called on a dirty resource"
1006 end
25ace54 @dkubb Modified Resource#update and #update! to raise an exception on modifi…
dkubb authored
1007 end
92e8a58 @dkubb Assert that Resource#save cannot be called on a destroyed resource
dkubb authored
1008
1009 # Raises an exception if #save is performed on a destroyed resource
1010 #
1011 # @param [Symbol] method
1012 # the name of the method to use in the exception
1013 #
1014 # @return [undefined]
1015 #
1016 # @raise [PersistenceError]
1017 # raise if the resource is destroyed
1018 #
1019 # @api private
1020 def assert_not_destroyed(method)
1021 if destroyed?
1022 raise PersistenceError, "#{model}##{method} cannot be called on a destroyed resource"
1023 end
1024 end
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
1025
1026 # Prevent a method from being in the stack more than once
1027 #
1028 # The purpose of this method is to prevent SystemStackError from
1029 # being thrown from methods from encountering infinite recursion
1030 # when called on resources having circular dependencies.
1031 #
1032 # @param [Object] default
1033 # default return value
1034 #
1035 # @yield The block of code to run once
1036 #
1037 # @return [Object]
1038 # block return value
1039 #
1040 # @api private
1041 def run_once(default)
1042 caller_method = caller(1).first[/`([^'?!]+)[?!]?'/, 1]
337f9d0 @dkubb Prefix all Resource internal ivars with an underscore
dkubb authored
1043 sentinel = "@_#{caller_method}_sentinel"
9115894 @dkubb Simplified SystemStackError prevention in saving and dirtyness testing
dkubb authored
1044 return instance_variable_get(sentinel) if instance_variable_defined?(sentinel)
1045
1046 begin
1047 instance_variable_set(sentinel, default)
1048 yield
1049 ensure
1050 remove_instance_variable(sentinel)
1051 end
1052 end
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataM…
myabc authored
1053 end # module Resource
1054 end # module DataMapper
Something went wrong with that request. Please try again.