doc.rb 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. module Docs
  2. class Doc
  3. INDEX_FILENAME = 'index.json'
  4. DB_FILENAME = 'db.json'
  5. class << self
  6. include Instrumentable
  7. attr_accessor :name, :slug, :type, :release, :abstract, :links
  8. def inherited(subclass)
  9. subclass.type = type
  10. end
  11. def version(version = nil, &block)
  12. return @version unless block_given?
  13. klass = Class.new(self)
  14. klass.name = name
  15. klass.slug = slug
  16. klass.version = version
  17. klass.links = links
  18. klass.class_exec(&block)
  19. @versions ||= []
  20. @versions << klass
  21. klass
  22. end
  23. def version=(value)
  24. @version = value.to_s
  25. end
  26. def versions
  27. @versions.presence || [self]
  28. end
  29. def version?
  30. version.present?
  31. end
  32. def versioned?
  33. @versions.presence
  34. end
  35. def name
  36. @name || super.try(:demodulize)
  37. end
  38. def slug
  39. slug = @slug || name.try(:downcase)
  40. version? ? "#{slug}~#{version.downcase.gsub('+', 'p').gsub(/[^a-z0-9\_\.]/, '_')}" : slug
  41. end
  42. def path
  43. slug
  44. end
  45. def index_path
  46. File.join path, INDEX_FILENAME
  47. end
  48. def db_path
  49. File.join path, DB_FILENAME
  50. end
  51. def as_json
  52. json = { name: name, slug: slug, type: type }
  53. json[:links] = links if links.present?
  54. json[:version] = version if version.present? || defined?(@version)
  55. json[:release] = release if release.present?
  56. json
  57. end
  58. def store_page(store, id)
  59. store.open(path) do
  60. if page = new.build_page(id) and store_page?(page)
  61. store.write page[:store_path], page[:output]
  62. true
  63. else
  64. false
  65. end
  66. end
  67. end
  68. def store_pages(store)
  69. index = EntryIndex.new
  70. pages = PageDb.new
  71. store.replace(path) do
  72. new.build_pages do |page|
  73. next unless store_page?(page)
  74. store.write page[:store_path], page[:output]
  75. index.add page[:entries]
  76. pages.add page[:path], page[:output]
  77. end
  78. if index.present?
  79. store_index(store, INDEX_FILENAME, index)
  80. store_index(store, DB_FILENAME, pages)
  81. true
  82. else
  83. false
  84. end
  85. end
  86. end
  87. private
  88. def store_page?(page)
  89. page[:entries].present?
  90. end
  91. def store_index(store, filename, index)
  92. old_json = store.read(filename) || '{}'
  93. new_json = index.to_json
  94. instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
  95. store.write(filename, new_json)
  96. end
  97. end
  98. def initialize
  99. raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated." if self.class.abstract
  100. end
  101. def build_page(id, &block)
  102. raise NotImplementedError
  103. end
  104. def build_pages(&block)
  105. raise NotImplementedError
  106. end
  107. end
  108. end