Class: TagSubstitution

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Model
Defined in:
app/models/tag_substitution.rb

Overview

A TagSubstitution may be used to replace tags in the event of accidental miss-tagging.

Examples:

Populating from an existing asset

mistagged_lane = Lane.find(1234)
TagSubstitution.new(tameplate_asset: mistagged_lane)

Swapping two tags in response to an RT ticket

TagSubstitution.new(
  user: User.find_by(login: 'ab12'),
  ticket: 'RT#12345',
  comment: 'Accidental tag swap',
  substitutions: [
    {
      sample_id: 100, libary_id: 10,
      original_tag_id: 20, substitute_tag_id: 21,
      original_tag2_id: 200, substitute_tag2_id: 201
    },
    {
      sample_id: 101, libary_id: 11,
      original_tag_id: 21, substitute_tag_id: 20,
      original_tag2_id: 201, substitute_tag2_id: 200
    }
  ]
).save #=> true

Defined Under Namespace

Classes: Substitution

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#commentString

Any additional comments regarding the substitution [optional]

Returns:

  • (String)

    free-text comment field


41
42
43
# File 'app/models/tag_substitution.rb', line 41

def comment
  @comment
end

#disable_clash_detectionBoolean

Disable tag-clash detection. Useful in cases where the substitutions only affect one of a pair of tags which is ensuring uniqueness, or where the updated aliquots are not part of a pool.

Returns:

  • (Boolean)

    indicates if clash detection is disabled


46
47
48
# File 'app/models/tag_substitution.rb', line 46

def disable_clash_detection
  @disable_clash_detection
end

#disable_match_expectationBoolean

Disable match-detection. Match detection flags a substitution as invalid if it cannot find aliquots matching the suggested substitution. This can be disabled in cases where this may be expected, such as in re-upload of library manifests. (As the aliquots in the library tubes themselves will have been updated by the manifest)

Returns:

  • (Boolean)

    indicates if match detection


53
54
55
# File 'app/models/tag_substitution.rb', line 53

def disable_match_expectation
  @disable_match_expectation
end

#nameObject


123
124
125
# File 'app/models/tag_substitution.rb', line 123

def name
  @name ||= 'Custom'
end

#substitutionsHash

Provide an array of hashes describing your desired substitutions

{
  sample_id: The id of the sample to change,
  libary_id: The corresponding library id,
  original_tag_id: The original tag id, [Required if substitute_tag_id supplied]
  substitute_tag_id: the replacement tag id, [Optional]
  original_tag2_id: The original tag2 id, [Required if original_tag2_id supplied]
  substitute_tag2_id: The replacement tag2 id [Optional]
}

Returns:

  • (Hash)

    the substitutions to perform


65
66
67
# File 'app/models/tag_substitution.rb', line 65

def substitutions
  @substitutions
end

#ticketString

The ticket number associated with the substitution, eg RT#123454. Gets recorded in the generated comment [optional]

Returns:

  • (String)

    ticket number


38
39
40
# File 'app/models/tag_substitution.rb', line 38

def ticket
  @ticket
end

#userUser

The user performing the substitution, gets recorded on the generated comments [optional]

Returns:

  • (User)

    the user performing the substitution


33
34
35
# File 'app/models/tag_substitution.rb', line 33

def user
  @user
end

Instance Method Details

#no_duplicate_tag_pairsObject


127
128
129
130
131
132
# File 'app/models/tag_substitution.rb', line 127

def no_duplicate_tag_pairs
  tag_pairs.each_with_object(Set.new) do |pair, set|
    errors.add(:base, "Tag pair #{pair.join('-')} features multiple times in the pool.") if set.include?(pair)
    set << pair
  end
end

#saveBoolean

Perform the substitution, add comments to all tubes and lanes and rebroadcast all flowcells

Returns:

  • (Boolean)

    returns true if the operation was successful, false otherwise


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/tag_substitution.rb', line 91

def save
  return false unless valid?

  # First set all tags to null to avoid the issue of tag clashes
  ActiveRecord::Base.transaction do
    @substitutions.each(&:nullify_tags)
    @substitutions.each(&:substitute_tags)
    apply_comments
  end
  rebroadcast_flowcells
  true
rescue ActiveRecord::RecordNotUnique => e
  # We'll specifically handle tag clashes here so that we can produce more informative messages
  raise e unless /aliquot_tags_and_tag2s_are_unique_within_receptacle/.match?(e.message)

  errors.add(:base, 'A tag clash was detected while performing the substitutions. No changes have been made.')
  false
end

#substitutions_valid?Boolean

Returns:

  • (Boolean)

76
77
78
79
80
81
82
83
# File 'app/models/tag_substitution.rb', line 76

def substitutions_valid?
  @substitutions.reduce(true) do |valid, sub|
    next valid if sub.valid?

    errors.add(:substitution, sub.errors.full_messages)
    valid && false
  end
end

#template_asset=(asset) ⇒ void

This method returns an undefined value.

Provide an asset to build a tag substitution form Will auto populate the fields on substitutions

Parameters:

  • asset (Receptacle)

    The receptacle which you want to base your substitutions on


116
117
118
119
120
121
# File 'app/models/tag_substitution.rb', line 116

def template_asset=(asset)
  @substitutions = asset.aliquots.includes(:sample).map do |aliquot|
    Substitution.new(aliquot: aliquot)
  end
  @name = asset.display_name
end