Module: Relationships

Defined in:
backend/app/model/mixins/relationships.rb

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#cached_relationshipsObject (readonly)

Store a list of the relationships that this object participates in. Saves looking up the DB for each one.



525
526
527
# File 'backend/app/model/mixins/relationships.rb', line 525

def cached_relationships
  @cached_relationships
end

Class Method Details

.included(base) ⇒ Object



500
501
502
503
504
505
506
507
# File 'backend/app/model/mixins/relationships.rb', line 500

def self.included(base)
  base.instance_eval do
    @relationships ||= {}
    @relationship_dependencies ||= {}
  end

  base.extend(ClassMethods)
end

Instance Method Details

#assimilate(merge_candidates) ⇒ Object

Find all relationships involving the records in ‘merge_candidates’ and rewrite them to refer to us instead.



564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
# File 'backend/app/model/mixins/relationships.rb', line 564

def assimilate(merge_candidates)
  merge_candidates = merge_candidates.reject {|v| (v.class == self.class) && (v.id == self.id)}

  self.class.relationship_dependencies.each do |relationship, models|
    models.each do |model|
      model.transfer(relationship, self, merge_candidates)
    end
  end

  DB.attempt {
    merge_candidates.each(&:delete)
  }.and_if_constraint_fails {
    raise MergeRequestFailed.new("Can't complete merge: record still in use")
  }

  trigger_reindex_of_dependants
end

#cache_relationships(relationship_defn, relationship_objects) ⇒ Object



527
528
529
530
# File 'backend/app/model/mixins/relationships.rb', line 527

def cache_relationships(relationship_defn, relationship_objects)
  @cached_relationships ||= {}
  @cached_relationships[relationship_defn] = relationship_objects
end


636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'backend/app/model/mixins/relationships.rb', line 636

def do_has_link_error(instances)
  # Abort the transfer and provide the list of top-level records that are preventing it from completing.
  exception = TransferConstraintError.new

  ASModel.all_models.each do |model|
    next unless model.associations.include?(:instance)

    model
      .eager_graph(:instance)
      .filter(:instance__id => instances)
      .select(Sequel.qualify(model.table_name, :id))
      .each do |row|
        exception.add_conflict(model.my_jsonmodel.uri_for(row[:id], :repo_id => self.class.active_repository),
                        {:json_property => 'instances',
                         :message => "DIGITAL_OBJECT_HAS_LINK"})
      end
  end

  raise exception
  return
end

#do_transferable?(do_id) ⇒ Boolean

Returns:

  • (Boolean)


619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
# File 'backend/app/model/mixins/relationships.rb', line 619

def do_transferable?(do_id)
  # ANW-151: Digital objects should not be transferable if they have instance links to other repository-scoped record types. If not transferrable, we throw an error and abort the transfer.
  do_relationship = DigitalObject.find_relationship(:instance_do_link)

  instances = do_relationship
  .select(:instance_id).filter(:digital_object_id => do_id)
  .map {|row| row[:instance_id]}

  if instances.empty?
    true
  else
    do_has_link_error(instances)
    false
  end
end

#my_relationships(name) ⇒ Object

Added to the mixed in class itself: return a list of the relationship instances involving this object



547
548
549
# File 'backend/app/model/mixins/relationships.rb', line 547

def my_relationships(name)
  self.class.find_relationship(name).find_by_participant(self)
end

Return all object instances that are related to the current record by the relationship named by ‘name’.



554
555
556
557
558
559
# File 'backend/app/model/mixins/relationships.rb', line 554

def related_records(name)
  relationship = self.class.find_relationship(name)
  records = relationship.who_participates_with(self)

  relationship.wants_array? ? records : records.first
end

#transfer_to_repository(repository, transfer_group = []) ⇒ Object



583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
# File 'backend/app/model/mixins/relationships.rb', line 583

def transfer_to_repository(repository, transfer_group = [])
  if transfer_group.empty?
    do_id = self.class == DigitalObject ? self[:id] : 0
  else
    do_id = transfer_group.first.class == DigitalObject ? transfer_group.first[:id] : 0
  end

  unless do_id == 0
    return unless do_transferable?(do_id)
  end

  # When a record is being transferred to another repository, any
  # relationships it has to records within the current repository must be
  # cleared.

  predicate = proc {|relationship|
    referent = relationship.other_referent_than(self)

    # Delete the relationship if we're repository-scoped and the referent is
    # in the old repository.  Don't worry about relationships to any of the
    # records that are going to be transferred along with us (listed in
    # transfer_group)
    (referent.class.model_scope == :repository &&
     referent.repo_id != repository.id &&
     !transfer_group.any? {|obj| obj.id == referent.id && obj.model == referent.model})
  }


  ([self.class] + self.class.dependent_models).each do |model|
    model.delete_existing_relationships(self, false, false, predicate)
  end

  super
end

#trigger_reindex_of_dependantsObject



533
534
535
536
537
538
539
540
541
542
# File 'backend/app/model/mixins/relationships.rb', line 533

def trigger_reindex_of_dependants
  # Update the mtime of any record with a relationship to this one.  This
  # encourages the indexer to reindex records when, say, a subject is renamed.
  #
  # Once we have our list of unique models, inform each of them that our
  # instance has been updated (using a class method defined below).
  self.class.dependent_models.each do |model|
    model.touch_mtime_of_anyone_related_to(self)
  end
end

#update_from_json(json, opts = {}, apply_nested_records = true) ⇒ Object



510
511
512
513
514
515
516
517
518
519
520
# File 'backend/app/model/mixins/relationships.rb', line 510

def update_from_json(json, opts = {}, apply_nested_records = true)
  obj = super

  # Call this before and after the change since relationships might have been
  # removed and the previously linked objects might need reindexing.
  trigger_reindex_of_dependants
  self.class.apply_relationships(obj, json, opts)
  trigger_reindex_of_dependants

  obj
end