Skip to content

The Anatomy of a Model

Julie Allinson edited this page Oct 20, 2017 · 3 revisions

The Anatomy of a Model

A model is a set of instructions and rules for constructing an object of a particular type. This is how a model is put together in DogBiscuits 🐶 🍪:

Thesis

module DogBiscuits
  class Thesis < Work
    include DogBiscuits::AddWorkBehaviour

    type << ::RDF::URI.new('http://purl.org/ontology/bibo/Thesis')

    def thesis?
      true
    end

    # Create single date field from all dates.
    def combine_dates
      self.date = []
      date << date_of_award
    end
  end
end
    
  • Thesis inherits from Work (Work inherits from ActiveFedora::Base).
  • DogBiscuits::AddWorkBehaviour is a concern that bundles together desired behaviours
  • DogBiscuits::AddThesisMetadata is a concern that bundles together all metadata properties for Thesis
  • Thesis has the rdf:type http://purl.org/ontology/bibo/Thesis
  • The thesis? method allows us to test that the object is a thesis.
  • Thesis has a custom ThesisIndexer class; this includes the DogBiscuits::IndexesThesis indexer
  • The combine_dates method and before_save callback is used across different models to combine different dates into a single property dc:date - this allows for a single date search in the calling application
  • Inherited from Work are DogBiscuits::ValidateLabel (to ensure a title is present) and DogBiscuits::CommonMetadata (a set of common metadata properties available to all Works a la Hyrax::BasicMetadata)

ThesisMetadata


module DogBiscuits
  module ThesisMetadata
    extend ActiveSupport::Concern
    include DogBiscuits::Abstract
    include DogBiscuits::Doi
    include DogBiscuits::Orcid
    include DogBiscuits::MainFile
    include DogBiscuits::Department
    include DogBiscuits::Qualification
    include DogBiscuits::Advisor
    include DogBiscuits::AwardingInstitution
    include DogBiscuits::DateOfAward
  end
end
    

Properties

These metadata property concerns make properties (and other code) available across multiple models using mixins. They are included in the Model that needs them.

module DogBiscuits
  module DateOfAward
    extend ActiveSupport::Concern

    included do
      property :date_of_award, predicate: ::RDF::Vocab::DC.dateAccepted, multiple: false do |index|
        index.as :stored_searchable, :facetable, :dateable
      end
    end
  end
end

Has and Belongs To Many [THIS PART MAY CHANGE]

Wherever the object of a predicate is another repository object (and the relationship is not covered by PCDM or Hydra::Works), use has_and_belongs_to_many (HABM). This is a bit misleading as really it's just has_many, but it is only possible to define a 'predicate' and restrict the object to being of a certain 'class' with has_and_belongs_to_many.

module DogBiscuits
  module AwardingInstitution
    extend ActiveSupport::Concern

    included do
      has_and_belongs_to_many :awarding_institution_resource,
                              class_name: 'DogBiscuits::Organisation',
                              predicate: ::RDF::Vocab::Bibframe.dissertationInstitution
    end
  end
end

So we'd do:

organisation_object = Organisation.new
thesis.awarding_institution_resource << organisation_object

and in fedora we'd get:

<thesis> <bf:dissertationInstitution> <organisation_object>

But how do we search for the creator if all we have is the id of the related creator objects?

By indexing info about the organisation into the solr document for the Work. Otherwise if a search for the awarding instituion name wouldn't get any results.

Do this with a custom indexer, like the one shown below.

Convention:

  • '_resource' for the name of the relationship to the object (eg. awarding_institution_resource)
  • '_label' for the name of the solr field for the 'preflabel' of the related object (eg.awarding_institution_tesim)
  • '_label_alt' for the variant names contained in the 'altlabel' field of the related object (eg. awarding_institution_value_alt_tesim)

Indexers

Additional fields can be indexed into solr with a custom indexer.

The patterns for custom indexers is as follows:

  • A common indexer has been created to deal with any HABM relations as described above:

  • Each model then has it's own Indexer that includes IndexesCommon

module DogBiscuits
  module ThesisIndexer
    include DogBiscuits::IndexesCommon

    included do
      def labels_to_index
        ['creator', 'advisor', 'department', 'awarding_institution']
      end

      def strings_to_index
        ['creator', 'advisor']
      end

def contributors_to_index
      ['advisor']
    end

      # Add any custom indexing into here. Method must exist, but can be empty.
      def do_local_indexing(solr_doc)
        # custom indexer
      end
    end
  end
end

  • The labels_to_index method should contain an array of any HABM fields to index, omitting the _resource part of the name.
  • The strings_to_index method should contain an array of any properties to be mixed into the _values solr field. For example, if there was a creator property with creator names in addition to creator HABM relations, both can be indexed into the creator_label_tesim solr field.
  • The contributors_to_index method should contain an array of properties that should be indexed additionally as contributor_combined (eg. advisor, editor) in order to create a single contributor field for facets in the search.
  • The do_local_indexing method can be used for any additional custom indexing, specific to the model.