Class: Serum::Post

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/serum/post.rb

Constant Summary collapse

MATCHER =

Valid post name regex.

%r{
  ^(.+\/)*        # zero or more path segments including their trailing slash
  (\d+-\d+-\d+)   # three numbers (YYYY-mm-dd) separated by hyphens for the date
  -(.*)           # a hyphen followed by the slug
  (\.[^.]+)$      # the file extension after a .
}x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(site, source, dir, name) ⇒ Post

Initialize this Post instance.

site - The Site. base - The String path to the dir containing the post file. name - The String filename of the post file.

Returns the new Post.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/serum/post.rb', line 36

def initialize(site, source, dir, name)
  @site = site
  @base = source
  @dir = dir
  @name = name

  self.process(name)
  begin
    self.read_yaml(@base, name)
  rescue Exception => msg
    raise FatalException.new("#{msg} in #{@base}/#{name}")
  end

  # If we've added a date and time to the YAML, use that instead of the
  # filename date. Means we'll sort correctly.
  if self.data.has_key?('date')
    # ensure Time via to_s and reparse
    self.date = Time.parse(self.data["date"].to_s)
  end

  if self.data.has_key?('published') && self.data['published'] == false
    self.published = false
  else
    self.published = true
  end

  if self.data.has_key?('slug')
    self.slug = self.data['slug']
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object



173
174
175
176
177
178
179
# File 'lib/serum/post.rb', line 173

def method_missing(meth, *args)
  if self.data.has_key?(meth.to_s) && args.empty?
    self.data[meth.to_s]
  else
    super
  end
end

Instance Attribute Details

#contentObject

Returns the value of attribute content.



24
25
26
# File 'lib/serum/post.rb', line 24

def content
  @content
end

#dataObject

Returns the value of attribute data.



24
25
26
# File 'lib/serum/post.rb', line 24

def data
  @data
end

#dateObject

Returns the value of attribute date.



25
26
27
# File 'lib/serum/post.rb', line 25

def date
  @date
end

#dirObject

Returns the value of attribute dir.



25
26
27
# File 'lib/serum/post.rb', line 25

def dir
  @dir
end

#extObject

Returns the value of attribute ext.



24
25
26
# File 'lib/serum/post.rb', line 24

def ext
  @ext
end

#nameObject (readonly)

Returns the value of attribute name.



27
28
29
# File 'lib/serum/post.rb', line 27

def name
  @name
end

#outputObject

Returns the value of attribute output.



24
25
26
# File 'lib/serum/post.rb', line 24

def output
  @output
end

#publishedObject

Returns the value of attribute published.



25
26
27
# File 'lib/serum/post.rb', line 25

def published
  @published
end

#siteObject

Returns the value of attribute site.



23
24
25
# File 'lib/serum/post.rb', line 23

def site
  @site
end

#slugObject

Returns the value of attribute slug.



25
26
27
# File 'lib/serum/post.rb', line 25

def slug
  @slug
end

Class Method Details

.valid?(name) ⇒ Boolean

Post name validator. Post filenames must be like: 2008-11-05-my-awesome-post.textile

Returns true if valid, false if not.

Returns:

  • (Boolean)


19
20
21
# File 'lib/serum/post.rb', line 19

def self.valid?(name)
  name =~ MATCHER
end

Instance Method Details

#<=>(other) ⇒ Object

Compares Post objects. First compares the Post date. If the dates are equal, it compares the Post slugs.

other - The other Post we are comparing to.

Returns -1, 0, 1



96
97
98
99
100
101
102
# File 'lib/serum/post.rb', line 96

def <=>(other)
  cmp = self.date <=> other.date
  if 0 == cmp
   cmp = self.slug <=> other.slug
  end
  return cmp
end

#idObject

The UID for this post (useful in feeds). e.g. /2008/11/05/my-awesome-post

Returns the String UID.



145
146
147
# File 'lib/serum/post.rb', line 145

def id
  File.join(self.dir, self.slug)
end

#inspectObject

Returns the shorthand String identifier of this Post.



150
151
152
# File 'lib/serum/post.rb', line 150

def inspect
  "<Post: #{self.id}>"
end

#nextObject



154
155
156
157
158
159
160
161
162
# File 'lib/serum/post.rb', line 154

def next
  pos = self.site.posts.index(self)

  if pos && pos < self.site.posts.length-1
    self.site.posts[pos+1]
  else
    nil
  end
end

The full path and filename of the post. Defined in the YAML of the post body (optional).

Returns the String permalink.



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

def permalink
  self.data && self.data['permalink']
end

#previousObject



164
165
166
167
168
169
170
171
# File 'lib/serum/post.rb', line 164

def previous
  pos = self.site.posts.index(self)
  if pos && pos > 0
    self.site.posts[pos-1]
  else
    nil
  end
end

#process(name) ⇒ Object

Extract information from the post filename.

name - The String filename of the post file.

Returns nothing.



109
110
111
112
113
114
115
116
# File 'lib/serum/post.rb', line 109

def process(name)
  m, cats, date, slug, ext = *name.match(MATCHER)
  self.date = Time.parse(date)
  self.slug = slug
  self.ext = ext
rescue ArgumentError
  raise FatalException.new("Post #{name} does not have a valid date.")
end

#read_yaml(base, name) ⇒ Object

Read the YAML frontmatter.

base - The String path to the dir containing the file. name - The String filename of the file.

Returns nothing.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/serum/post.rb', line 73

def read_yaml(base, name)
  begin
    content = File.read(File.join(base, name))

    if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
      self.data = YAML.safe_load($1)
      self.content = $' # everything after the last match
    end
  rescue => e
    puts "Error reading file #{File.join(base, name)}: #{e.message}"
  rescue SyntaxError => e
    puts "YAML Exception reading #{File.join(base, name)}: #{e.message}"
  end

  self.data ||= {}
end

#urlObject

The generated relative url of this post. e.g. /2008/11/05/my-awesome-post.html

Returns the String URL.



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

def url
  return @url if @url

  url = "#{self.site.baseurl}#{self.id}"

  # sanitize url
  @url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
  @url += "/" if url =~ /\/$/
  @url
end