Class: MPS::Store
- Inherits:
-
Object
- Object
- MPS::Store
- Defined in:
- lib/mps/store.rb
Instance Method Summary collapse
-
#all_files ⇒ Object
All .mps files in storage, sorted by filename (chronological).
-
#append(type:, body:, tags: [], attrs: {}, date: Date.today) ⇒ Object
Appends a new element to today’s (or
date‘s) file. -
#files_since(since_date) ⇒ Object
Files whose date-stamp is >=
since_date. -
#find_file(date) ⇒ Object
First .mps file found for
date, or nil. -
#find_files(date) ⇒ Object
All .mps files matching
date(handles multiple files per day). -
#find_or_create_path(date) ⇒ Object
Existing file for
date, or a generated new path (file not yet created). -
#initialize(storage_dir) ⇒ Store
constructor
A new instance of Store.
-
#parse_date(date) ⇒ Object
Parsed elements hash for
date. -
#resolver_for(date) ⇒ Object
Returns a RefResolver built from the parsed elements for
date. -
#rewrite_element(ref_str, new_attrs, date: Date.today) ⇒ Object
Rewrites an element’s args bracket in-place and saves atomically.
-
#search(query, type_filter: nil, tag_filter: nil, since_date: nil) ⇒ Object
Full-text search across files.
Constructor Details
#initialize(storage_dir) ⇒ Store
Returns a new instance of Store.
5 6 7 8 9 10 11 12 13 |
# File 'lib/mps/store.rb', line 5 def initialize(storage_dir) @storage_dir = storage_dir @element_classes = Elements.constants .map { |k| Elements.const_get(k) } .select { |x| x.class == Class } @interpolator_classes = Interpolators.constants .map { |k| Interpolators.const_get(k) } .select { |x| x.class == Class } end |
Instance Method Details
#all_files ⇒ Object
All .mps files in storage, sorted by filename (chronological).
57 58 59 60 61 |
# File 'lib/mps/store.rb', line 57 def all_files Dir[File.join(@storage_dir, "*.#{Constants::MPS_EXT}")] .select { |f| File.basename(f) =~ Constants::MPS_FILE_NAME_REGEXP } .sort end |
#append(type:, body:, tags: [], attrs: {}, date: Date.today) ⇒ Object
Appends a new element to today’s (or date‘s) file. Returns the file path.
48 49 50 51 52 53 54 |
# File 'lib/mps/store.rb', line 48 def append(type:, body:, tags: [], attrs: {}, date: Date.today) args_parts = attrs.map { |k, v| "#{k}: #{v}" } + Array() args_str = args_parts.join(", ") path = find_or_create_path(date) File.open(path, "a") { |f| f.write("\n@#{type}[#{args_str}]{\n #{body}\n}\n") } path end |
#files_since(since_date) ⇒ Object
Files whose date-stamp is >= since_date.
64 65 66 67 |
# File 'lib/mps/store.rb', line 64 def files_since(since_date) since_str = since_date.strftime("%Y%m%d") all_files.select { |f| File.basename(f).slice(0, 8) >= since_str } end |
#find_file(date) ⇒ Object
First .mps file found for date, or nil.
16 17 18 |
# File 'lib/mps/store.rb', line 16 def find_file(date) find_files(date).first end |
#find_files(date) ⇒ Object
All .mps files matching date (handles multiple files per day).
21 22 23 24 25 26 |
# File 'lib/mps/store.rb', line 21 def find_files(date) date_str = date.strftime("%Y%m%d") Dir[File.join(@storage_dir, "#{date_str}*.#{Constants::MPS_EXT}")] .select { |f| File.basename(f) =~ Constants::MPS_FILE_NAME_REGEXP } .sort end |
#find_or_create_path(date) ⇒ Object
Existing file for date, or a generated new path (file not yet created).
29 30 31 |
# File 'lib/mps/store.rb', line 29 def find_or_create_path(date) find_file(date) || File.join(@storage_dir, Constants::MPS_NEW_FILE_NAME_GEN.call(date)) end |
#parse_date(date) ⇒ Object
Parsed elements hash for date. Returns {} when no file exists.
34 35 36 37 38 39 40 |
# File 'lib/mps/store.rb', line 34 def parse_date(date) path = find_file(date) return {} unless path Engines::Parser.parse_mps_file_to_elements_hash( path, @element_classes, interpolator_classes: @interpolator_classes ) end |
#resolver_for(date) ⇒ Object
Returns a RefResolver built from the parsed elements for date.
43 44 45 |
# File 'lib/mps/store.rb', line 43 def resolver_for(date) RefResolver.new(parse_date(date)) end |
#rewrite_element(ref_str, new_attrs, date: Date.today) ⇒ Object
Rewrites an element’s args bracket in-place and saves atomically.
ref_str may be an epoch ref (“20260428.1”) or a human ref (“task-1”). Human refs are resolved against date (defaults to today). new_attrs is a hash of attribute_name => new_value (symbol keys). Returns true on success, false if element not found or file unchanged.
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/mps/store.rb', line 92 def rewrite_element(ref_str, new_attrs, date: Date.today) epoch_ref, path = _resolve_ref_to_path(ref_str, date) return false unless epoch_ref && path elements = Engines::Parser.parse_mps_file_to_elements_hash(path, @element_classes) el = elements[epoch_ref] return false unless el return false if el.is_a?(Engines::Parser::Unknown) _rewrite_element_in_file(path, el, new_attrs) end |
#search(query, type_filter: nil, tag_filter: nil, since_date: nil) ⇒ Object
Full-text search across files. Returns [file:, date_str:].
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/mps/store.rb', line 70 def search(query, type_filter: nil, tag_filter: nil, since_date: nil) files = since_date ? files_since(since_date) : all_files files.flat_map do |file| date_str = File.basename(file).slice(0, 8) Engines::Parser.parse_mps_file_to_elements_hash( file, @element_classes, interpolator_classes: @interpolator_classes ) .values .reject { |e| e.is_a?(Elements::MPS) || e.is_a?(Engines::Parser::Unknown) } .select { |e| type_filter.nil? || e.class::SIGNATURE_STAMP == type_filter } .select { |e| tag_filter.nil? || e..include?(tag_filter) } .select { |e| query.nil? || e.body_str.downcase.include?(query.downcase) } .map { |e| { element: e, file: file, date_str: date_str } } end end |