Module: ASModel::CRUD::ClassMethods

Defined in:
backend/app/model/ASModel_crud.rb

Instance Method Summary collapse

Instance Method Details

#add_enclosing_association(association) ⇒ Object

Record the association of the record that encloses this one. For example, an Archival Object encloses an Instance record because an Instance is a nested record of an Archival Object.



432
433
434
435
# File 'backend/app/model/ASModel_crud.rb', line 432

def add_enclosing_association(association)
  @enclosing_associations ||= []
  @enclosing_associations << association
end

#associations_to_eagerly_loadObject



497
498
499
500
501
# File 'backend/app/model/ASModel_crud.rb', line 497

def associations_to_eagerly_load
  # Allow subclasses to force eager loading of certain associations to
  # save SQL queries.
  []
end

#corresponds_to(jsonmodel) ⇒ Object



465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'backend/app/model/ASModel_crud.rb', line 465

def corresponds_to(jsonmodel)
  @jsonmodel = jsonmodel

  include(DynamicEnums)

  enums = []
  @jsonmodel.schema['properties'].each do |prop, defn|
    if defn["dynamic_enum"]
      enums << {:property => prop, :uses_enum => [defn['dynamic_enum']]}
    end
  end

  uses_enums(*enums)
end

#create_from_json(json, extra_values = {}) ⇒ Object

Create a new record instance from the JSONModel ‘json’. Also creates any nested record instances that it contains.



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'backend/app/model/ASModel_crud.rb', line 322

def create_from_json(json, extra_values = {})
  self.strict_param_setting = false
  values = ASUtils.keys_as_strings(extra_values)

  if model_scope == :repository && !values.has_key?("repo_id")
    values["repo_id"] = active_repository
  end

  values['created_by'] = RequestContext.get(:current_username)

  obj = self.create(prepare_for_db(json.class,
                                   json.to_hash.merge(values)))

  obj.apply_nested_records(json, true)

  fire_update(json, obj)

  obj.refresh
  obj
end

#def_nested_record(opts) ⇒ Object

Match a JSONModel object to an existing database association.

This linkage manages records that contain subrecords:

  • When storing a JSON blob in the database, the linkage indicates which parts of the JSON should be plucked out and stored as separate database records (with the appropriate associations)

  • When requesting a record in JSON format, the linkage indicates which associated database records should be pulled back and included in the JSON returned.

For example, this definition from subject.rb:

def_nested_record(:the_property => :terms, :contains_records_of_type => :term, :corresponding_to_association => :term)

Causes an incoming JSONModel(:subject) to have each of the objects in its “terms” array to be coerced into a Sequel model (based on the :terms association) and stored in the database. The provided list of terms are associated with the subject as it is stored, and these replace any previous terms.

The definition also causes Subject.to_jsonmodel(obj) to automatically pull back the list of terms associated with the object and include them in the response.



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'backend/app/model/ASModel_crud.rb', line 411

def def_nested_record(opts)
  opts[:association] = self.association_reflection(opts[:corresponding_to_association])
  opts[:jsonmodel] = opts[:contains_records_of_type]
  opts[:json_property] = opts[:the_property]

  opts[:is_array] = true if !opts.has_key?(:is_array)

  # Store our association on the nested record's model so we can walk back
  # the other way.
  ArchivesSpaceService.loaded_hook do
    nested_model = Kernel.const_get(opts[:association][:class_name])
    nested_model.add_enclosing_association(opts[:association])
  end

  nested_records << opts
end

#enclosing_associationsObject

If this is a nested record, return the list of associations that link us back to our parent(s). Top-level records just return an empty list.



439
440
441
# File 'backend/app/model/ASModel_crud.rb', line 439

def enclosing_associations
  @enclosing_associations || []
end

#fire_update(json, sequel_obj) ⇒ Object

(Potentially) notify the real-time indexer that an update is available.



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'backend/app/model/ASModel_crud.rb', line 350

def fire_update(json, sequel_obj)
  if high_priority?
    model = self

    uri = sequel_obj.uri

    # We don't index records without URIs, so no point digging them out of the database either.
    return unless uri

    record_id = sequel_obj.id
    repo_id = RequestContext.get(:repo_id)

    DB.after_commit do
      RequestContext.open(:repo_id => repo_id) do
        # if the record was created in a transaction that was rolled back
        # then it won't exist after the rollback, so we make sure it's there
        # before trying to fire the update
        record = model.any_repo.filter(:id => record_id).first
        if record
          hash = model.to_jsonmodel(record).to_hash(:trusted)
          RealtimeIndexing.record_update(hash, uri)
        end
      end
    end
  end
end

#get_nested_graphObject



444
445
446
447
448
449
450
451
# File 'backend/app/model/ASModel_crud.rb', line 444

def get_nested_graph
  Hash[nested_records.map {|nested_record|
         model = Kernel.const_get(nested_record[:association][:class_name])
         association = nested_record[:corresponding_to_association]

         [association, model.get_nested_graph]
       }]
end

#get_or_die(id) ⇒ Object



454
455
456
457
458
459
460
461
462
# File 'backend/app/model/ASModel_crud.rb', line 454

def get_or_die(id)
  obj = if self.model_scope == :repository
          self.this_repo[:id => id]
        else
          self[id]
        end

  obj or raise NotFoundException.new("#{self} not found")
end

#handle_delete(ids_to_delete) ⇒ Object



532
533
534
# File 'backend/app/model/ASModel_crud.rb', line 532

def handle_delete(ids_to_delete)
  self.filter(:id => ids_to_delete).delete
end

#has_jsonmodel?Boolean

Does this model have a corresponding JSONModel?

Returns:

  • (Boolean)


482
483
484
# File 'backend/app/model/ASModel_crud.rb', line 482

def has_jsonmodel?
  !@jsonmodel.nil?
end

#high_priority?Boolean

Returns:

  • (Boolean)


344
345
346
# File 'backend/app/model/ASModel_crud.rb', line 344

def high_priority?
  RequestContext.get(:is_high_priority)
end

#is_relationship?Boolean

Returns:

  • (Boolean)


563
564
565
# File 'backend/app/model/ASModel_crud.rb', line 563

def is_relationship?
  false
end

#my_jsonmodel(ok_if_missing = false) ⇒ Object

Return the JSONModel class that maps to this backend model



488
489
490
# File 'backend/app/model/ASModel_crud.rb', line 488

def my_jsonmodel(ok_if_missing = false)
  @jsonmodel or (ok_if_missing ? nil : raise("No corresponding JSONModel set for model #{self.inspect}"))
end

#nested_recordsObject



378
379
380
# File 'backend/app/model/ASModel_crud.rb', line 378

def nested_records
  @nested_records ||= []
end

#repo_unique_constraint(property, constraints) ⇒ Object



557
558
559
560
# File 'backend/app/model/ASModel_crud.rb', line 557

def repo_unique_constraint(property, constraints)
  @repo_unique_constraints ||= []
  @repo_unique_constraints << constraints.merge(:property => property)
end

#repo_unique_constraintsObject



552
553
554
# File 'backend/app/model/ASModel_crud.rb', line 552

def repo_unique_constraints
  Array(@repo_unique_constraints)
end

#sequel_to_jsonmodel(objs, opts = {}) ⇒ Object



493
494
495
# File 'backend/app/model/ASModel_crud.rb', line 493

def sequel_to_jsonmodel(objs, opts = {})
  NestedRecordResolver.new(nested_records, objs).resolve
end

#to_jsonmodel(obj, opts = {}) ⇒ Object



504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'backend/app/model/ASModel_crud.rb', line 504

def to_jsonmodel(obj, opts = {})
  is_id_query     = obj.is_a?(Integer)
  is_string_query = obj.is_a?(String) && opts[:query]

  if is_id_query || is_string_query
    ds = if self.model_scope == :repository
           self.this_repo
         else
           self
         end

    # An ID.  Get the Sequel row for it.
    if is_id_query
      obj = ds.eager(get_nested_graph).filter(:id => obj).all[0]

    # If we have a string and query option, attempt to look up by querying string value against column name.
    elsif is_string_query
      obj = ds.eager(get_nested_graph).filter(opts[:query].to_sym => obj).all[0]
    end

    raise NotFoundException.new("#{self} not found") unless obj
    obj.eagerly_load!
  end

  sequel_to_jsonmodel([obj], opts)[0]
end

#update_mtime_for_ids(ids) ⇒ Object



544
545
546
547
548
549
# File 'backend/app/model/ASModel_crud.rb', line 544

def update_mtime_for_ids(ids)
  now = Time.now
  ids.each_slice(1000) do |subset|
    self.dataset.filter(:id => subset).update(:system_mtime => now)
  end
end

#update_mtime_for_repo_id(repo_id) ⇒ Object



537
538
539
540
541
# File 'backend/app/model/ASModel_crud.rb', line 537

def update_mtime_for_repo_id(repo_id)
  if model_scope == :repository
    self.dataset.filter(:repo_id => repo_id).update(:system_mtime => Time.now) if self.dataset.columns.include? :repo_id
  end
end