Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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