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.



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

def cached_relationships
  @cached_relationships
end

Class Method Details

.included(base) ⇒ Object



503
504
505
506
507
508
509
510
# File 'backend/app/model/mixins/relationships.rb', line 503

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

  base.extend(ClassMethods)
end

Instance Method Details

#assimilate(victims) ⇒ Object

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



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

def assimilate(victims)
  victims = victims.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, victims)
    end
  end

  DB.attempt {
    victims.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



530
531
532
533
# File 'backend/app/model/mixins/relationships.rb', line 530

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


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

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)


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

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



550
551
552
# File 'backend/app/model/mixins/relationships.rb', line 550

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’.



557
558
559
560
561
562
# File 'backend/app/model/mixins/relationships.rb', line 557

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



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
617
618
619
# File 'backend/app/model/mixins/relationships.rb', line 586

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



536
537
538
539
540
541
542
543
544
545
# File 'backend/app/model/mixins/relationships.rb', line 536

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



513
514
515
516
517
518
519
520
521
522
523
# File 'backend/app/model/mixins/relationships.rb', line 513

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