You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devdocs/lib/docs/core/doc.rb

163 lines
3.6 KiB

11 years ago
module Docs
class Doc
INDEX_FILENAME = 'index.json'
DB_FILENAME = 'db.json'
META_FILENAME = 'meta.json'
11 years ago
class << self
include Instrumentable
attr_accessor :name, :slug, :type, :release, :abstract, :links
11 years ago
def inherited(subclass)
subclass.type = type
end
def version(version = nil, &block)
return @version unless block_given?
klass = Class.new(self)
klass.name = name
klass.slug = slug
klass.version = version
klass.release = release
klass.links = links
klass.class_exec(&block)
@versions ||= []
@versions << klass
klass
end
def version=(value)
@version = value.to_s
end
def versions
@versions.presence || [self]
end
def version?
version.present?
end
def versioned?
@versions.presence
end
11 years ago
def name
@name || super.demodulize
11 years ago
end
def slug
slug = @slug || default_slug || raise('slug is required')
version? ? "#{slug}~#{version_slug}" : slug
end
def version_slug
return if version.blank?
slug = version.downcase
slug.gsub! '+', 'p'
slug.gsub! '#', 's'
slug.gsub! %r{[^a-z0-9\_\.]}, '_'
slug
11 years ago
end
def path
slug
end
def index_path
File.join path, INDEX_FILENAME
end
10 years ago
def db_path
File.join path, DB_FILENAME
end
def meta_path
File.join path, META_FILENAME
end
11 years ago
def as_json
json = { name: name, slug: slug, type: type }
json[:links] = links if links.present?
json[:version] = version if version.present? || defined?(@version)
json[:release] = release if release.present?
json
11 years ago
end
def store_page(store, id)
store.open(path) do
if page = new.build_page(id) and store_page?(page)
store.write page[:store_path], page[:output]
true
else
false
end
11 years ago
end
end
def store_pages(store)
11 years ago
index = EntryIndex.new
pages = PageDb.new
11 years ago
store.replace(path) do
new.build_pages do |page|
next unless store_page?(page)
store.write page[:store_path], page[:output]
index.add page[:entries]
pages.add page[:path], page[:output]
end
if index.present?
store_index(store, INDEX_FILENAME, index)
store_index(store, DB_FILENAME, pages)
store_meta(store)
true
else
false
end
11 years ago
end
end
private
def default_slug
return if name =~ /[^A-Za-z0-9_]/
name.downcase
end
def store_page?(page)
page[:entries].present?
end
def store_index(store, filename, index)
old_json = store.read(filename) || '{}'
new_json = index.to_json
instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
store.write(filename, new_json)
end
def store_meta(store)
json = as_json
json[:mtime] = Time.now.to_i
json[:db_size] = store.size(DB_FILENAME)
store.write(META_FILENAME, json.to_json)
end
11 years ago
end
11 years ago
def initialize
raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated." if self.class.abstract
end
def build_page(id, &block)
raise NotImplementedError
end
def build_pages(&block)
raise NotImplementedError
end
end
end