Module: Parse::Core::Actions::ClassMethods
- Defined in:
- lib/parse/model/core/actions.rb
Overview
Class methods applied to Parse::Object subclasses.
Instance Attribute Summary collapse
- #raise_on_save_failure ⇒ Boolean
By default, we return `true` or `false` for save and destroy operations.
Instance Method Summary collapse
- #first_or_create(query_attrs = {}, resource_attrs = {}) ⇒ Parse::Object
Finds the first object matching the query conditions, or creates a new unsaved object with the attributes.
- #first_or_create!(query_attrs = {}, resource_attrs = {}) ⇒ Parse::Object
Finds the first object matching the query conditions, or creates a new saved object with the attributes.
- #save_all(constraints = {}) { ... } ⇒ Boolean
Auto save all objects matching the query constraints.
Instance Attribute Details
#raise_on_save_failure ⇒ Boolean
By default, we return `true` or `false` for save and destroy operations. If you prefer to have `Parse::Object` raise an exception instead, you can tell to do so either globally or on a per-model basis. When a save fails, it will raise a RecordNotSaved.
When enabled, if an error is returned by Parse due to saving or destroying a record, due to your `before_save` or `before_delete` validation cloud code triggers, `Parse::Object` will return the a RecordNotSaved exception type. This exception has an instance method of `#object` which contains the object that failed to save.
134 135 136 | # File 'lib/parse/model/core/actions.rb', line 134 def raise_on_save_failure @raise_on_save_failure end |
Instance Method Details
#first_or_create(query_attrs = {}, resource_attrs = {}) ⇒ Parse::Object
Finds the first object matching the query conditions, or creates a new unsaved object with the attributes. This method takes the possibility of two hashes, therefore make sure you properly wrap the contents of the input with `{}`.
150 151 152 153 154 155 156 157 158 159 160 | # File 'lib/parse/model/core/actions.rb', line 150 def first_or_create(query_attrs = {}, resource_attrs = {}) query_attrs = query_attrs.symbolize_keys resource_attrs = resource_attrs.symbolize_keys obj = query(query_attrs).first if obj.blank? obj = self.new query_attrs obj.apply_attributes!(resource_attrs, dirty_track: true) end obj end |
#first_or_create!(query_attrs = {}, resource_attrs = {}) ⇒ Parse::Object
Finds the first object matching the query conditions, or creates a new saved object with the attributes. This method is similar to #first_or_create but will also Parse::Core::Actions#save! the object if it was newly created.
173 174 175 176 177 | # File 'lib/parse/model/core/actions.rb', line 173 def first_or_create!(query_attrs = {}, resource_attrs = {}) obj = first_or_create(query_attrs, resource_attrs) obj.save! if obj.new? obj end |
#save_all(constraints = {}) { ... } ⇒ Boolean
You cannot use :updated_at as a constraint.
Auto save all objects matching the query constraints. This method is meant to be used with a block. Any objects that are modified in the block will be batched for a save operation. This uses the `updated_at` field to continue to query for all matching objects that have not been updated. If you need to use `:updated_at` in your constraints, consider using Querying#all or Querying#each
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | # File 'lib/parse/model/core/actions.rb', line 196 def save_all(constraints = {}) invalid_constraints = constraints.keys.any? do |k| (k == :updated_at || k == :updatedAt) || (k.is_a?(Parse::Operation) && (k.operand == :updated_at || k.operand == :updatedAt)) end if invalid_constraints raise ArgumentError, "[#{self}] Special method save_all() cannot be used with an :updated_at constraint." end force = false batch_size = 250 iterator_block = nil if block_given? iterator_block = Proc.new force ||= false else # if no block given, assume you want to just save all objects # regardless of modification. force = true end # Only generate the comparison block once. # updated_comparison_block = Proc.new { |x| x.updated_at } anchor_date = Parse::Date.now constraints.merge! :updated_at.on_or_before => anchor_date constraints.merge! cache: false # oldest first, so we create a reduction-cycle constraints.merge! order: :updated_at.asc, limit: batch_size update_query = query(constraints) #puts "Setting Anchor Date: #{anchor_date}" cursor = nil has_errors = false loop do results = update_query.results break if results.empty? # verify we didn't get duplicates fetches if cursor.is_a?(Parse::Object) && results.any? { |x| x.id == cursor.id } warn "[#{self}.save_all] Unbounded update detected with id #{cursor.id}." has_errors = true break cursor end results.each(&iterator_block) if iterator_block.present? # we don't need to refresh the objects in the array with the results # since we will be throwing them away. Force determines whether # to save these objects regardless of whether they are dirty. batch = results.save(merge: false, force: force) # faster version assuming sorting order wasn't messed up cursor = results.last # slower version, but more accurate # cursor_item = results.max_by(&updated_comparison_block).updated_at # puts "[Parse::SaveAll] Updated #{results.count} records updated <= #{cursor.updated_at}" break if results.count < batch_size # we didn't hit a cap on results. if cursor.is_a?(Parse::Object) update_query.where :updated_at.gte => cursor.updated_at if cursor.updated_at.present? && cursor.updated_at > anchor_date warn "[#{self}.save_all] Reached anchor date #{anchor_date} < #{cursor.updated_at}" break cursor end end has_errors ||= batch.error? end not has_errors end |