module Card::Reference::All

Constants

PARTIAL_REF_CODE

Cards can refer to other cards in their content, eg via links and nests. The card that refers is the “referer”, the card that is referred to is the “referee”. The reference itself has its own class (Card::Reference), which handles id-based reference tracking.

Public Instance Methods

create_references_out() click to toggle source

interpret references from this card’s content and insert entries in reference table

# File lib/card/reference/all.rb, line 55
def create_references_out
  ref_hash = {}
  each_reference_out do |referee_name, ref_type|
    interpret_reference ref_hash, referee_name, ref_type
  end
  return if ref_hash.empty?

  Reference.insert_in_slices reference_values_array(ref_hash)
end
name_referers() click to toggle source

cards that refer to self by name (finds cards not yet linked by id)

# File lib/card/reference/all.rb, line 43
def name_referers
  Card.joins(:references_out).where card_references: { referee_key: key }
end
nestees() click to toggle source

cards that self includes

# File lib/card/reference/all.rb, line 33
def nestees
  referees_from_references references_out.where(ref_type: "I")
end
nesters() click to toggle source

cards that include self

# File lib/card/reference/all.rb, line 19
def nesters
  referer_cards_from_references references_in.where(ref_type: "I")
end
referees() click to toggle source

cards that self refers to

# File lib/card/reference/all.rb, line 28
def referees
  referees_from_references references_out
end
referees_from_references(references) click to toggle source
# File lib/card/reference/all.rb, line 37
def referees_from_references references
  references.map(&:referee_key).uniq.map { |key| Card.fetch key, new: {} }
end
referer_cards_from_references(references) click to toggle source
# File lib/card/reference/all.rb, line 23
def referer_cards_from_references references
  references.map(&:referer_id).uniq.map(&:card).compact
end
referers() click to toggle source

cards that refer to self

# File lib/card/reference/all.rb, line 14
def referers
  referer_cards_from_references references_in
end
swap_names(old_name, new_name) click to toggle source

replace references in card content

# File lib/card/reference/all.rb, line 66
def swap_names old_name, new_name
  cont = content_object
  cont.find_chunks(:Reference).each do |chunk|
    chunk.swap_name old_name, new_name
  end
  cont.to_s
end
update_references_out() click to toggle source

delete old references from this card’s content, create new ones

# File lib/card/reference/all.rb, line 48
def update_references_out
  delete_references_out
  create_references_out
end

Private Instance Methods

each_reference_out() { |referee_name, reference_code| ... } click to toggle source

invokes the given block for each reference in content with the reference name and reference type

# File lib/card/reference/all.rb, line 125
def each_reference_out
  content_object.find_chunks(:Reference).each do |chunk|
    yield chunk.referee_name, chunk.reference_code
  end
end
each_reference_type(ref_types, &block) click to toggle source
# File lib/card/reference/all.rb, line 117
def each_reference_type ref_types, &block
  ref_types.delete PARTIAL_REF_CODE if ref_types.size > 1
  # partial references are not necessary if there are explicit references
  ref_types.each(&block)
end
interpret_partial_references(ref_hash, referee_name) click to toggle source

Partial references are needed to track references to virtual cards. For example a link to virtual card [[A+*self]] won’t have a referee_id, but when A’s name is changed we have to find and update that link.

# File lib/card/reference/all.rb, line 134
def interpret_partial_references ref_hash, referee_name
  return if referee_name.simple?

  [referee_name.left, referee_name.right].each do |sidename|
    interpret_reference ref_hash, sidename, PARTIAL_REF_CODE
  end
end
interpret_reference(ref_hash, raw_referee_name, ref_type) click to toggle source

interpretation phase helps to prevent duplicate references results in hash like: { referee1_key: [referee1_id, referee1_type2],

referee2_key...

}

# File lib/card/reference/all.rb, line 81
def interpret_reference ref_hash, raw_referee_name, ref_type
  with_normalized_referee raw_referee_name do |name, key, id|
    ref_hash[key] ||= [id]
    ref_hash[key] << ref_type
    interpret_partial_references ref_hash, name unless id
  end
end
reference_values_array(ref_hash) click to toggle source

translate interpreted reference hash into values array, removing duplicate and unnecessary ref_types

# File lib/card/reference/all.rb, line 101
def reference_values_array ref_hash
  [].tap do |values|
    ref_hash.each do |referee_key, hash_val|
      referee_id = hash_val.shift
      each_reference_type hash_val.uniq do |ref_type|
        values << {
          referer_id: id,
          referee_id: referee_id,
          referee_key: referee_key,
          ref_type: ref_type
        }
      end
    end
  end
end
with_normalized_referee(referee_name) { |referee_name, referee_key, id| ... } click to toggle source
# File lib/card/reference/all.rb, line 89
def with_normalized_referee referee_name
  return unless referee_name # eg commented nest has no referee_name

  referee_name = referee_name.to_name
  referee_key = referee_name.key
  return if referee_key == key # don't create self reference

  yield referee_name, referee_key, Lexicon.id(referee_name)
end