Class: Scriptorium::Post

Inherits:
Object
  • Object
show all
Includes:
Contract, Exceptions, Helpers
Defined in:
lib/scriptorium/post.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Contract

#assume, #check_invariants, enabled?, #invariant, #verify

Methods included from Helpers

#cf_time, #change_config, #clean_slugify, #copy_gem_asset_to_user, #copy_to_clipboard, #d4, #escape_html, #generate_missing_asset_svg, #get_asset_path, #get_from_clipboard, #getvars, #list_gem_assets, #make_dir, #make_tree, #need, #read_commented_file, #read_file, #see, #see_file, #slugify, #substitute, #system!, #view_dir, #write_file, #write_file!, #ymdhms

Methods included from Exceptions

#make_exception

Constructor Details

#initialize(repo, num) ⇒ Post

Returns a new instance of Post.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/scriptorium/post.rb', line 8

def initialize(repo, num)
  assume { repo.is_a?(Scriptorium::Repo) }
  assume { num.is_a?(Integer) || num.is_a?(String) }
  validate_initialization(repo, num)
  
  @repo = repo
  @num = d4(num.to_i)  # num is zero-padded string
  @id = num.to_i       # id is integer
  @meta = nil  # Explicitly initialize for clarity
  
  # Define invariants
  invariant { @id > 0 }
  invariant { @repo.is_a?(Scriptorium::Repo) }
  invariant { @num.match?(/^\d{4}$/) }
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



6
7
8
# File 'lib/scriptorium/post.rb', line 6

def id
  @id
end

#numObject (readonly)

Returns the value of attribute num.



6
7
8
# File 'lib/scriptorium/post.rb', line 6

def num
  @num
end

#repoObject (readonly)

Returns the value of attribute repo.



6
7
8
# File 'lib/scriptorium/post.rb', line 6

def repo
  @repo
end

Class Method Details

.read(repo, num) ⇒ Object

New class method to read metadata and initialize the Post



147
148
149
150
151
# File 'lib/scriptorium/post.rb', line 147

def self.read(repo, num)
  post = new(repo, num)
  post.
  post
end

Instance Method Details

#attrs(*keys) ⇒ Object

New method to access multiple attributes at once



142
143
144
# File 'lib/scriptorium/post.rb', line 142

def attrs(*keys)
    keys.map { |key| send(key) }
end

#blurbObject



46
47
48
# File 'lib/scriptorium/post.rb', line 46

def blurb
  meta["post.blurb"]
end

#deletedObject



126
127
128
# File 'lib/scriptorium/post.rb', line 126

def deleted
  meta["post.deleted"] == "true"
end

#deleted=(value) ⇒ Object



130
131
132
133
134
135
136
137
138
139
# File 'lib/scriptorium/post.rb', line 130

def deleted=(value)
  check_invariants
  assume { [true, false].include?(value) }
  
  meta["post.deleted"] = value ? "true" : "false"
  
  
  verify { meta["post.deleted"] == (value ? "true" : "false") }
  check_invariants
end

#dirObject



31
32
33
# File 'lib/scriptorium/post.rb', line 31

def dir
  repo.root/:posts/@num
end

#load_metadataObject

Additional method to load metadata explicitly, so it’s only called once



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/scriptorium/post.rb', line 166

def 
  check_invariants
  assume { File.exist?(meta_file) }
  
  @meta = {}
  @repo.tree("/tmp/tree.txt")
  read_file(meta_file, lines: true, chomp: true).each do |line|
    key, value = line.strip.split(/\s+/, 2)
    next if key.nil? || key.empty?
    @meta[key] = value
  end 
  
  verify { @meta.is_a?(Hash) }
  check_invariants
  @meta
end

#metaObject



153
154
155
156
# File 'lib/scriptorium/post.rb', line 153

def meta
  return @meta if @meta
  @meta = File.exist?(meta_file) ?  : {}
end

#meta_fileObject



35
36
37
38
39
40
41
42
# File 'lib/scriptorium/post.rb', line 35

def meta_file
  # Check if post is in deleted directory (with underscore prefix)
  deleted_meta = @repo.root/:posts/"_#{@num}"/"meta.txt"
  return deleted_meta if File.exist?(deleted_meta)
  
  # Otherwise use normal directory
  @repo.root/:posts/@num/"meta.txt"
end

#pubdateObject



58
59
60
# File 'lib/scriptorium/post.rb', line 58

def pubdate
  meta["post.pubdate"]
end

#pubdate_month_day_yearObject



108
109
110
# File 'lib/scriptorium/post.rb', line 108

def pubdate_month_day_year
  [meta["post.pubdate.month"], meta["post.pubdate.day"], meta["post.pubdate.year"]]
end

#save_metadataObject



183
184
185
186
187
188
189
190
191
192
193
# File 'lib/scriptorium/post.rb', line 183

def 
  check_invariants
  assume { @meta.is_a?(Hash) }
  assume { !@meta.empty? }
  
  lines = @meta.map { |k, v| sprintf("%-18s  %s", k, v) }
  write_file(meta_file, lines.join("\n"))
  
  verify { File.exist?(meta_file) }
  check_invariants
end

#set_pubdate(ymd, seconds: 0) ⇒ Object

Raises:

  • (TestModeOnly)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/scriptorium/post.rb', line 62

def set_pubdate(ymd, seconds: 0)
  check_invariants
  assume { Scriptorium::Repo.testing }
  assume { ymd.is_a?(String) }
  assume { seconds.is_a?(Integer) && seconds >= 0 }
  
  raise TestModeOnly unless Scriptorium::Repo.testing
  
  validate_date_format(ymd)
  
  yyyy, mm, dd = ymd.split("-")
  t = Time.new(yyyy.to_i, mm.to_i, dd.to_i, 0, 0, seconds)
  
  (t)
  
  
  verify { meta["post.pubdate"].is_a?(String) }
  check_invariants
end

#set_pubdate_with_seconds(ymd, seconds) ⇒ Object

Legacy method for backward compatibility - preserves 12:00 base time

Raises:

  • (TestModeOnly)


96
97
98
99
100
101
102
103
104
105
106
# File 'lib/scriptorium/post.rb', line 96

def set_pubdate_with_seconds(ymd, seconds)
  raise TestModeOnly unless Scriptorium::Repo.testing
  
  validate_date_format(ymd)
  
  yyyy, mm, dd = ymd.split("-")
  t = Time.new(yyyy.to_i, mm.to_i, dd.to_i, 12, 0, seconds)  # 12:00:XX for ordering
  
  (t)
  
end

#slugObject



54
55
56
# File 'lib/scriptorium/post.rb', line 54

def slug
  meta["post.slug"]
end

#tagsObject



122
123
124
# File 'lib/scriptorium/post.rb', line 122

def tags
  meta["post.tags"]
end

#titleObject



50
51
52
# File 'lib/scriptorium/post.rb', line 50

def title
  meta["post.title"]
end

#varsObject



158
159
160
161
162
163
# File 'lib/scriptorium/post.rb', line 158

def vars
  return @vars if defined?(@vars)
  @vars = Hash.new("")
  meta.each_pair {|k,v| @vars[k.to_sym] = v }
  @vars
end

#viewsObject



112
113
114
# File 'lib/scriptorium/post.rb', line 112

def views
  meta["post.views"]
end

#views_arrayObject



116
117
118
119
120
# File 'lib/scriptorium/post.rb', line 116

def views_array
  views_str = meta["post.views"]
  return [] if views_str.nil? || views_str.strip.empty?
  views_str.strip.split(/\s+/)
end