Class: WritersRoom::StoryBible

Inherits:
Object
  • Object
show all
Defined in:
lib/writers_room/story_bible.rb

Overview

Auto-generated index mapping slugs/aliases to files. The story bible is the project's lookup table for quick name resolution.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_path) ⇒ StoryBible

Returns a new instance of StoryBible.



12
13
14
15
16
# File 'lib/writers_room/story_bible.rb', line 12

def initialize(project_path)
  @project_path = File.expand_path(project_path)
  @bible_path   = File.join(@project_path, "story_bible.yml")
  @data         = load_bible
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



10
11
12
# File 'lib/writers_room/story_bible.rb', line 10

def data
  @data
end

#project_pathObject (readonly)

Returns the value of attribute project_path.



10
11
12
# File 'lib/writers_room/story_bible.rb', line 10

def project_path
  @project_path
end

Instance Method Details

#element_countObject



83
84
85
# File 'lib/writers_room/story_bible.rb', line 83

def element_count
  @data.fetch("elements", {}).size
end

#elements_by_typeObject



87
88
89
90
# File 'lib/writers_room/story_bible.rb', line 87

def elements_by_type
  @data.fetch("elements", {}).group_by { |_, v| v["type"] }
    .transform_values { |entries| entries.map { |slug, info| { slug: slug }.merge(info) } }
end

#pin_version(slug, version_file) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/writers_room/story_bible.rb', line 65

def pin_version(slug, version_file)
  entry = @data.dig("elements", slug)
  return false unless entry

  entry["current"] = version_file
  save_bible
  true
end

#regenerateObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/writers_room/story_bible.rb', line 18

def regenerate
  @data = { "elements" => {}, "generated_at" => Time.now.to_s }

  medium = detect_medium
  medium.scaffolded_dirs.each do |dir_name|
    dir_path = File.join(@project_path, dir_name)
    next unless Dir.exist?(dir_path)

    collection = ElementCollection.new(dir_path, element_type: dir_name)
    collection.all.each do |element|
      slug = element.slug
      @data["elements"][slug] = {
        "name"     => element.name,
        "aliases"  => element.aliases,
        "type"     => dir_name,
        "path"     => element.path.sub("#{@project_path}/", ""),
        "status"   => element.status,
        "version"  => element.version,
        "current"  => "latest"
      }
    end
  end

  save_bible
  @data
end

#resolve(name_or_alias) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/writers_room/story_bible.rb', line 45

def resolve(name_or_alias)
  query = name_or_alias.to_s.downcase.strip

  # Exact match first
  @data.fetch("elements", {}).each do |slug, entry|
    return entry if slug == query
    return entry if entry["name"]&.downcase == query
    return entry if Array(entry["aliases"]).any? { |a| a.to_s.downcase == query }
  end

  # Substring match as fallback
  @data.fetch("elements", {}).each do |slug, entry|
    return entry if slug.include?(query)
    return entry if entry["name"]&.downcase&.include?(query)
    return entry if Array(entry["aliases"]).any? { |a| a.to_s.downcase.include?(query) }
  end

  nil
end

#unpin_version(slug) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/writers_room/story_bible.rb', line 74

def unpin_version(slug)
  entry = @data.dig("elements", slug)
  return false unless entry

  entry["current"] = "latest"
  save_bible
  true
end