Class: OKF::Concept::File

Inherits:
Object
  • Object
show all
Defined in:
lib/okf/concept/file.rb

Overview

A single concept file on disk — the ActiveRecord-style handle over one .md. Wraps a pure OKF::Concept with load/save/delete/reload side effects. Part of the shell (it does I/O); the pure Concept knows nothing about it.

file = OKF::Concept::File.read(root: "docs", path: "tables/orders.md")
file.concept              # => OKF::Concept (pure)
file.concept.links        # interrogate it in memory
file.save                 # write concept.to_markdown back to disk
file.delete

NOTE: this class is named File, which shadows Ruby's File inside the OKF::Concept namespace — every filesystem call here uses ::File explicitly.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root:, path:, concept: nil) ⇒ File

Returns a new instance of File.



30
31
32
33
34
# File 'lib/okf/concept/file.rb', line 30

def initialize(root:, path:, concept: nil)
  @root = ::File.expand_path(root.to_s)
  @path = Path.normalize_relative!(path)
  @concept = concept
end

Instance Attribute Details

#conceptObject (readonly)

Returns the value of attribute concept.



18
19
20
# File 'lib/okf/concept/file.rb', line 18

def concept
  @concept
end

#pathObject (readonly)

Returns the value of attribute path.



18
19
20
# File 'lib/okf/concept/file.rb', line 18

def path
  @path
end

#rootObject (readonly)

Returns the value of attribute root.



18
19
20
# File 'lib/okf/concept/file.rb', line 18

def root
  @root
end

Class Method Details

.read(root:, path:) ⇒ Object

Read a concept file from disk into a handle.



21
22
23
# File 'lib/okf/concept/file.rb', line 21

def self.read(root:, path:)
  new(root: root, path: path).reload
end

.write(root:, concept:) ⇒ Object

Write a concept's markdown to disk under root and return the handle.



26
27
28
# File 'lib/okf/concept/file.rb', line 26

def self.write(root:, concept:)
  new(root: root, path: concept.path, concept: concept).save
end

Instance Method Details

#absolute_pathObject

Absolute on-disk path, guarded so it cannot escape the bundle root.



37
38
39
# File 'lib/okf/concept/file.rb', line 37

def absolute_path
  Path.join_under!(@root, @path)
end

#deleteObject



50
51
52
53
# File 'lib/okf/concept/file.rb', line 50

def delete
  ::FileUtils.rm_f(absolute_path)
  self
end

#reloadObject



55
56
57
58
59
60
# File 'lib/okf/concept/file.rb', line 55

def reload
  content = ::File.read(absolute_path, encoding: "UTF-8")
  frontmatter, body = Markdown::Frontmatter.parse(content)
  @concept = Concept.new(path: @path, frontmatter: frontmatter, body: body)
  self
end

#saveObject

Raises:



41
42
43
44
45
46
47
48
# File 'lib/okf/concept/file.rb', line 41

def save
  raise Error, "no concept to save" if @concept.nil?

  target = absolute_path
  ::FileUtils.mkdir_p(::File.dirname(target))
  ::File.write(target, @concept.to_markdown, encoding: "UTF-8")
  self
end