Class: Identifier

Inherits:
ApplicationRecord show all
Includes:
Housekeeping, Shared::DualAnnotator, Shared::IsData
Defined in:
app/models/identifier.rb

Overview

The information that can be use to differentiate concepts. Note this definition is presently very narrow, and that an identifier can in practice be used for a lot more than differentiation (i.e. it can often be resolved etc.).

In TW identifiers are either global, in which case they are subclassed by type, and do not include a namespace, or local, in which case they have a namespace.

!! Identifiers should always be created in the context of their parents see spec/lib/identifier_spec.rb for examples !!

Direct Known Subclasses

Global, Local, Unknown

Defined Under Namespace

Classes: Global, Local, Unknown

Constant Summary

SHORT_NAMES =
TODO:

this likely has to be refactored/considered

!! If there are inheritance issues with validation the position !! of this constant is likely the problem

{
  doi:                       Identifier::Global::Doi,
  isbn:                      Identifier::Global::Isbn,
  issn:                      Identifier::Global::Issn,
  lccn:                      Identifier::Global::Lccn,
  occurrence_id:             Identifier::Global::OccurrenceId,
  orcid:                     Identifier::Global::Orcid,
  uri:                       Identifier::Global::Uri,
  uuid:                      Identifier::Global::Uuid,
  gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
  morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
  catalog_number:            Identifier::Local::CatalogNumber,
  trip_code:                 Identifier::Local::TripCode,
  import:                    Identifier::Local::Import,
  otu_utility:               Identifier::Local::OtuUtility,
  accession_code:            Identifier::Local::AccessionCode,
  unknown:                   Identifier::Unknown
}

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Housekeeping

#has_polymorphic_relationship?

Methods included from ActiverecordUtilities

#trim_attributes

Instance Attribute Details

- (String) cached

The full identifier, for display, i.e. namespace + identifier (local), or identifier (global).

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

- (String) identifier

The string identifying the object. Must be unique within the Namespace if provided. Same as rs.tdwg.org/dwc/terms/catalogNumber, but broadened in scope to be used for any data.

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

- (String) identifier_object_id

The type of the identified object, used in a polymorphic relationship.

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

- (Integer) namespace_id

The Namespace for this identifier.

Returns:

  • (Integer)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

- (Integer) project_id

The project ID.

Returns:

  • (Integer)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

- (String) type

The Rails STI subclass of this identifier.

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/identifier.rb', line 41

class Identifier < ApplicationRecord

  acts_as_list scope: [:project_id, :identifier_object_id, :identifier_object_type]

  include Housekeeping
  include Shared::IsData
  include Shared::DualAnnotator

  after_save :set_cached

  # must come before SHORT_NAMES for weird inheritance issue
  belongs_to :identifier_object, polymorphic: :true
  belongs_to :namespace # only applies to Identifier::Local, here for create purposes

  # @todo this likely has to be refactored/considered
  # !! If there are inheritance issues with validation the position
  # !! of this constant is likely the problem
  SHORT_NAMES = {
    doi:                       Identifier::Global::Doi,
    isbn:                      Identifier::Global::Isbn,
    issn:                      Identifier::Global::Issn,
    lccn:                      Identifier::Global::Lccn,
    occurrence_id:             Identifier::Global::OccurrenceId,
    orcid:                     Identifier::Global::Orcid,
    uri:                       Identifier::Global::Uri,
    uuid:                      Identifier::Global::Uuid,
    gen_bank_accession_code:   Identifier::Global::GenBankAccessionCode,
    morphbank_specimen_number: Identifier::Global::MorphbankSpecimenNumber,
    catalog_number:            Identifier::Local::CatalogNumber,
    trip_code:                 Identifier::Local::TripCode,
    import:                    Identifier::Local::Import,
    otu_utility:               Identifier::Local::OtuUtility,
    accession_code:            Identifier::Local::AccessionCode,
    unknown:                   Identifier::Unknown
  }

  # Please DO NOT include the following:
  #   validates :identifier_object, presence: true
  #   validates_presence_of :identifier_object_type, :identifier_object_id
  validates_presence_of :type, :identifier

  # @todo test  - pendings are in the identifier_spec
  scope :of_type, -> (type) {where(type: Identifier::SHORT_NAMES[type].to_s)}
  scope :with_type_string, -> (base_string) {where('type LIKE ?', "#{base_string}")}

  def self.find_for_autocomplete(params)
    where('identifier LIKE ?', "#{params[:term]}%")
  end

  # @return [NoteObject]
  #   alias to simplify reference across classes
  def annotated_object
    identifier_object
  end

  def self.class_name
    self.name.demodulize.underscore.humanize.downcase
  end

  def klass_name
    self.class.class_name
  end

  def self.generate_download(scope)
    CSV.generate do |csv|
      csv << column_names
      scope.order(id: :asc).each do |o|
        csv << o.attributes.values_at(*column_names).collect {|i|
          i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
        }
      end
    end
  end

  def self.prototype_identifier(project_id, created_by_id)
    identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
    identifiers.empty? ? '12345678' : identifiers.last.identifier
  end

  protected

  def set_cached
  end

end

Class Method Details

+ (Object) class_name



96
97
98
# File 'app/models/identifier.rb', line 96

def self.class_name
  self.name.demodulize.underscore.humanize.downcase
end

+ (Object) find_for_autocomplete(params)



86
87
88
# File 'app/models/identifier.rb', line 86

def self.find_for_autocomplete(params)
  where('identifier LIKE ?', "#{params[:term]}%")
end

+ (Object) generate_download(scope)



104
105
106
107
108
109
110
111
112
113
# File 'app/models/identifier.rb', line 104

def self.generate_download(scope)
  CSV.generate do |csv|
    csv << column_names
    scope.order(id: :asc).each do |o|
      csv << o.attributes.values_at(*column_names).collect {|i|
        i.to_s.gsub(/\n/, '\n').gsub(/\t/, '\t')
      }
    end
  end
end

+ (Object) prototype_identifier(project_id, created_by_id)



115
116
117
118
# File 'app/models/identifier.rb', line 115

def self.prototype_identifier(project_id, created_by_id)
  identifiers = Identifier.where(project_id: project_id, created_by_id: created_by_id).limit(1)
  identifiers.empty? ? '12345678' : identifiers.last.identifier
end

Instance Method Details

- (NoteObject) annotated_object

Returns alias to simplify reference across classes

Returns:

  • (NoteObject)

    alias to simplify reference across classes



92
93
94
# File 'app/models/identifier.rb', line 92

def annotated_object
  identifier_object
end

- (Object) klass_name



100
101
102
# File 'app/models/identifier.rb', line 100

def klass_name
  self.class.class_name
end

- (Object) set_cached (protected)



122
123
# File 'app/models/identifier.rb', line 122

def set_cached
end