Module: Card::Set::All::References

Extended by:
Card::Set
Defined in:
tmpsets/set/mod001-core/all/references.rb

Constant Summary collapse

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.

"P".freeze

Instance Method Summary collapse

Methods included from I18nScope

#mod_name, #scope

Methods included from Loader

#clean_empty_module_from_hash, #clean_empty_modules, #extended, #pattern_and_modules_from_path, #process_base_modules, #register_set, #tmp_file_template, #write_tmp_file

Methods included from Helpers

#abstract_set?, #all_set?, #shortname

Methods included from Card::Set::AdvancedApi

#attachment, #ensure_set, #stage_method

Methods included from Format

#all_set_format_mod!, #define_on_format, #format, #register_set_format, #view

Methods included from Inheritance

#include_set, #include_set_formats

Methods included from Basket

#abstract_basket, #add_to_basket, #basket

Methods included from Trait

#card_accessor, #card_reader, #card_writer

Methods included from Event

#event

Instance Method Details

#create_references_outObject

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



69
70
71
72
73
74
75
76
# File 'tmpsets/set/mod001-core/all/references.rb', line 69

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?
  Card::Reference.mass_insert reference_values_array(ref_hash)
end

#delete_references_outObject

delete references from this card



79
80
81
82
# File 'tmpsets/set/mod001-core/all/references.rb', line 79

def delete_references_out
  raise "id required to delete references" if id.nil?
  Card::Reference.delete_all referer_id: id
end

#each_reference_outObject

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



128
129
130
131
132
133
# File 'tmpsets/set/mod001-core/all/references.rb', line 128

def each_reference_out
  content_obj = Card::Content.new raw_content, self
  content_obj.find_chunks(Card::Content::Chunk::Reference).each do |chunk|
    yield(chunk.referee_name, chunk.reference_code)
  end
end

#family_referersObject

cards that refer to self or any descendant



42
43
44
45
# File 'tmpsets/set/mod001-core/all/references.rb', line 42

def family_referers
  @family_referers ||= ([self] + descendants).map(&:referers).flatten.uniq
  # FIXME: could be much more efficient!
end

#includeesObject

cards that self includes



30
31
32
33
# File 'tmpsets/set/mod001-core/all/references.rb', line 30

def includees
  refs = references_out.where(ref_type: "I")
  refs.map { |ref| Card.fetch ref.referee_key, new: {} }
end

#includersObject

cards that include self



19
20
21
22
# File 'tmpsets/set/mod001-core/all/references.rb', line 19

def includers
  refs = references_in.where(ref_type: "I")
  refs.map(&:referer_id).map(&Card.method(:fetch)).compact
end

#interpret_partial_references(ref_hash, referee_name) ⇒ Object

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



104
105
106
107
108
# File 'tmpsets/set/mod001-core/all/references.rb', line 104

def interpret_partial_references ref_hash, referee_name
  [referee_name.left, referee_name.right].each do |sidename|
    interpret_reference ref_hash, sidename, PARTIAL_REF_CODE
  end
end

#interpret_reference(ref_hash, referee_name, ref_type) ⇒ Object

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



89
90
91
92
93
94
95
96
97
98
99
# File 'tmpsets/set/mod001-core/all/references.rb', line 89

def interpret_reference ref_hash, referee_name, ref_type
  return unless referee_name # eg commented nest has no referee_name
  referee_key = (referee_name = referee_name.to_name).key
  return if referee_key == key # don't create self reference

  referee_id = Card.fetch_id(referee_name)
  ref_hash[referee_key] ||= [referee_id]
  ref_hash[referee_key] << ref_type

  interpret_partial_references ref_hash, referee_name unless referee_id
end

#name_referersObject

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



37
38
39
# File 'tmpsets/set/mod001-core/all/references.rb', line 37

def name_referers
  Card.joins(:references_out).where card_references: { referee_key: key }
end

#refereesObject

cards that self refers to



25
26
27
# File 'tmpsets/set/mod001-core/all/references.rb', line 25

def referees
  references_out.map { |ref| Card.fetch ref.referee_key, new: {} }
end

#reference_values_array(ref_hash) ⇒ Object

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



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'tmpsets/set/mod001-core/all/references.rb', line 112

def reference_values_array ref_hash
  values = []
  ref_hash.each do |referee_key, hash_val|
    referee_id = hash_val.shift || "null"
    ref_types = hash_val.uniq
    ref_types.delete PARTIAL_REF_CODE if ref_types.size > 1
    # partial references are not necessary if there are explicit references
    ref_types.each do |ref_type|
      values << [id, referee_id, "'#{referee_key}'", "'#{ref_type}'"]
    end
  end
  values
end

#referersObject

cards that refer to self



14
15
16
# File 'tmpsets/set/mod001-core/all/references.rb', line 14

def referers
  references_in.map(&:referer_id).map(&Card.method(:fetch)).compact
end

#replace_reference_syntax(old_name, new_name) ⇒ Object

replace references in card content



48
49
50
51
52
53
54
55
56
57
58
59
# File 'tmpsets/set/mod001-core/all/references.rb', line 48

def replace_reference_syntax old_name, new_name
  obj_content = Card::Content.new raw_content, self
  obj_content.find_chunks(Card::Content::Chunk::Reference).select do |chunk|
    next unless (old_ref_name = chunk.referee_name)
    next unless (new_ref_name = old_ref_name.replace_part old_name, new_name)
    chunk.referee_name = chunk.replace_reference old_name, new_name
    refs = Card::Reference.where referee_key: old_ref_name.key
    refs.update_all referee_key: new_ref_name.key
  end

  obj_content.to_s
end

#update_references_outObject

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



62
63
64
65
# File 'tmpsets/set/mod001-core/all/references.rb', line 62

def update_references_out
  delete_references_out
  create_references_out
end