Module: Shared::IsData

Extended by:
ActiveSupport::Concern
Included in:
AlternateValue, AssertedDistribution, Attribution, BiocurationClassification, BiologicalAssociation, BiologicalAssociationsBiologicalAssociationsGraph, BiologicalAssociationsGraph, BiologicalRelationship, BiologicalRelationshipType, CachedMap, CachedMapItem, CachedMapItemTranslation, CachedMapRegister, CharacterState, Citation, CitationTopic, CollectingEvent, CollectionObject, CollectionObjectObservation, CollectionProfile, CommonName, Confidence, Container, ContainerItem, Content, ControlledVocabularyTerm, Conveyance, DataAttribute, DatasetRecord, DatasetRecordField, Depiction, DerivedCollectionObject, Descriptor, Document, Documentation, Download, Extract, FieldOccurrence, Gazetteer, GeneAttribute, GeographicArea, GeographicAreaType, GeographicAreasGeographicItem, GeographicItem, Georeference, Identifier, Image, ImportDataset, Label, Language, Lead, LeadItem, Loan, LoanItem, Namespace, Note, Observation, ObservationMatrix, ObservationMatrixColumn, ObservationMatrixColumnItem, ObservationMatrixRow, ObservationMatrixRowItem, Organization, OriginRelationship, Otu, OtuPageLayout, OtuPageLayoutSection, OtuRelationship, Person, PreparationType, ProjectMember, ProjectSource, Protocol, ProtocolRelationship, RangedLotCategory, Repository, Role, Sequence, SequenceRelationship, Serial, SerialChronology, SledImage, Sound, Source, SqedDepiction, Tag, TaggedSectionKeyword, TaxonDetermination, TaxonName, TaxonNameClassification, TaxonNameRelationship, TypeMaterial
Defined in:
app/models/concerns/shared/is_data.rb

Overview

Shared code for a classes that are “data” sensu TaxonWorks (things like Projects, users, and preferences are not data).

!! This module must in included last !!

Defined Under Namespace

Modules: Annotation, ClassMethods, HasRoles, Levenshtein, Metamorphosize, Navigation, Pinnable, Scopes, Stripper

Instance Method Summary collapse

Instance Method Details

#errors_excepting(*keys) ⇒ Hash

Parameters:

  • keys (Symbol)

Returns:

  • (Hash)


259
260
261
262
263
264
265
# File 'app/models/concerns/shared/is_data.rb', line 259

def errors_excepting(*keys)
  valid?
  keys.each do |k|
    errors.delete(k)
  end
  errors
end

#full_error_messages_excepting(*keys) ⇒ Array

Parameters:

  • keys (Symbol)

Returns:

  • (Array)


295
296
297
# File 'app/models/concerns/shared/is_data.rb', line 295

def full_error_messages_excepting(*keys)
  errors_excepting(*keys).full_messages
end

#identicalScope

Returns:

  • (Scope)


282
283
284
285
286
287
288
289
290
291
# File 'app/models/concerns/shared/is_data.rb', line 282

def identical
  klass = self.class
  attr  = Stripper.strip_identical_attributes(klass, attributes)
  if id
    scope = klass.where(attr).not_self(self)
  else
    scope = klass.where(attr)
  end
  scope
end

#is_community?Boolean

Returns:

  • (Boolean)


244
245
246
# File 'app/models/concerns/shared/is_data.rb', line 244

def is_community?
  self.class < Shared::SharedAcrossProjects ? true : false
end

#is_destroyable?(user) ⇒ Boolean

Returns whether it is permissible to try to destroy the record based on its relationships to projects the user is in. I.e. false if it is related to data in a project in which they user is not a member. !! Does not look at :dependendant assertions

Parameters:

  • user (user_id or User)

    an id or User object

Returns:

  • (Boolean)

    true - there is at least some related data in another projects



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'app/models/concerns/shared/is_data.rb', line 177

def is_destroyable?(user)
  u = user
  u = User.find(user) if !user.kind_of?(User)
  return true if u.is_administrator?

  p = u.projects.pluck(:id)

  # TODO: !! replace with a simple wrapped transaction and roll it back

  self.class.reflect_on_all_associations(:has_many).each do |r|
    if r.klass.column_names.include?('project_id')
      # If this has any related data in another project, we can't destroy it
      #    if !send(r.name).nil?
      return false if send(r.name).where.not(project_id: p).any? # count(:all) > 0
      #     end
    end
  end

  self.class.reflect_on_all_associations(:has_one).each do |r|
    if is_community? # *this* object is community, others we don't care about
      if o = send(r.name)
        return false if o.respond_to?(:project_id) && !p.include?(o.project_id)
      end
    end
  end
  true
end

#is_editable?(user) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
208
209
210
211
# File 'app/models/concerns/shared/is_data.rb', line 205

def is_editable?(user)
  u = user
  u = User.find(user) if !user.kind_of?(User)
  return true if u.is_administrator? || is_community?
  return false if !is_in_users_projects?(u)
  true
end

#is_in_use?(exclude = [], only = []) ⇒ Boolean

!! provide only exclude or only

Returns:

  • (Boolean)


223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'app/models/concerns/shared/is_data.rb', line 223

def is_in_use?(exclude = [], only = [])
  if only.empty?
    self.class.reflect_on_all_associations(:has_many).each do |r|
      next if exclude.include?(r.name)
      return true if self.send(r.name).count(:all) > 0
    end

    self.class.reflect_on_all_associations(:has_one).each do |r|
      next if exclude.include?(r.name)
      return true if self.send(r.name).count(:all) > 0
    end
  else
    only.each do |r|
      return true if self.send(r.to_s).count(:all) > 0
    end
  end

  false
end

#is_in_users_projects?(user) ⇒ Boolean

Returns:

  • (Boolean)


213
214
215
# File 'app/models/concerns/shared/is_data.rb', line 213

def is_in_users_projects?(user)
  user.projects.pluck(:id).include?(project_id)
end

#metamorphosizeObject

TODO: reconcile with Shared::IsData::Metamorphosize

Returns:

  • (Object)

    the same object, but namespaced to the base class used many places, might be good target for optimization



252
253
254
255
# File 'app/models/concerns/shared/is_data.rb', line 252

def metamorphosize
  return self if self.class.descends_from_active_record?
  self.becomes(self.class.base_class)
end

#similarScope

Returns:

  • (Scope)


268
269
270
271
272
273
274
275
276
277
278
279
# File 'app/models/concerns/shared/is_data.rb', line 268

def similar
  klass = self.class
  attr  = Stripper.strip_similar_attributes(klass, attributes)
  # matching only those attributes from the instance which are not empty
  attr = attr.select{ |_kee, val| val.present? }
  if id
    scope = klass.where(attr).not_self(self)
  else
    scope = klass.where(attr)
  end
  scope
end