lib/nanoc/base/data_source.rb in nanoc-2.0.4 vs lib/nanoc/base/data_source.rb in nanoc-2.1

- old
+ new

@@ -1,17 +1,33 @@ module Nanoc + + # Nanoc::DataSource is responsible for loading data. It is the (abstract) + # superclass for all data sources. Subclasses must at least implement the + # data reading methods (+pages+, +page_defaults+, +layouts+, +templates+, + # and +code+); all other methods involving data manipulation are optional. + # + # Apart from the methods for loading and storing data, there are the +up+ + # and +down+ methods for bringing up and tearing down the connection to the + # data source. These should be overridden in subclasses. The +loading+ + # method wraps +up+ and +down+. + # + # The +setup+ method is used for setting up a site's data source for the + # first time. This method should be overridden in subclasses. class DataSource < Plugin - attr_reader :config - + # Creates a new data source for the given site. def initialize(site) @site = site @references = 0 end - # Preparation - + # Loads the data source when necessary (calling +up+), yields, and unloads + # the data source when it is not being used elsewhere. All data source + # queries and data manipulations should be wrapped in a +loading+ block; + # it ensures that the data source is loaded when necessary and makes sure + # the data source does not get unloaded while it is still being used + # elsewhere. def loading # Load if necessary up if @references == 0 @references += 1 @@ -20,34 +36,251 @@ # Unload if necessary @references -= 1 down if @references == 0 end - def up ; end - def down ; end + ########## Loading and unloading - def setup ; end + # Brings up the connection to the data. This is an abstract method + # implemented by the subclass. Depending on the way data is stored, this + # may not be necessary. This is the ideal place to connect to the + # database, for example. + # + # Subclasses may implement this method. + def up + end - # Loading data + # Brings down the connection to the data. This is an abstract method + # implemented by the subclass. This method should undo the effects of + # +up+. + # + # Subclasses may implement this method. + def down + end - def pages ; error 'DataSource#pages must be overridden' ; end - def page_defaults ; error 'DataSource#page_defaults must be overridden' ; end - def layouts ; error 'DataSource#layouts must be overridden' ; end - def templates ; error 'DataSource#templates must be overridden' ; end - def code ; error 'DataSource#code must be overridden' ; end + ########## Creating/updating - # Creating data + # Creates the bare minimum essentials for this data source to work. This + # action will likely be destructive. This method should not create sample + # data such as a default home page, a default layout, etc. For example, if + # you're using a database, this is where you should create the necessary + # tables for the data source to function properly. + # + # Subclasses must implement this method. + def setup + not_implemented('setup') + end - def create_page(name, template) - error 'DataSource#create_page must be overridden' + # Removes all data stored by this data source. This method undoes the + # effects of the +setup+ method. + # + # Subclasses must implement this method. + def destroy + not_implemented('destroy') end - def create_layout(name) - error 'DataSource#create_layout must be overridden' + # Updated the content stored in this site to a newer version. A newer + # version of a data source may store content in a different format, and + # this method will update the stored content to this newer format. + # + # Subclasses may implement this method. + def update end - def create_template(name) - error 'DataSource#create_template must be overridden' + ########## Pages + + # Returns the list of pages (represented by Nanoc::Page) in this site. + # This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def pages + not_implemented('pages') + end + + # Saves the given page in the data source, creating it if it doesn't exist + # yet and updating the existing copy otherwise. + # + # Subclasses must implement this method. + def save_page(page) + not_implemented('save_page') + end + + # Changes the path of the given page to the given new path. When changing + # a page's path, this method must be used (save_page will not work). + # + # Subclasses must implement this method. + def move_page(page, new_path) + not_implemented('move_page') + end + + # Removes the given page from the data source. + # + # Subclasses must implement this method. + def delete_page(page) + not_implemented('delete_page') + end + + ########## Assets + + # Returns the list of assets (represented by Nanoc::Asset) in this site. + # This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def assets + not_implemented('assets') + end + + # Saves the given asset in the data source, creating it if it doesn't + # exist yet and updating the existing copy otherwise. + # + # Subclasses must implement this method. + def save_asset(asset) + not_implemented('save_asset') + end + + # Changes the path of the given asset to the given new path. When changing + # a asset's path, this method must be used (save_asset will not work). + # + # Subclasses must implement this method. + def move_asset(asset, new_path) + not_implemented('move_asset') + end + + # Removes the given asset from the data source. + # + # Subclasses must implement this method. + def delete_asset(asset) + not_implemented('delete_asset') + end + + ########## Page defaults + + # Returns the page defaults (represented by Nanoc::PageDefaults) of this + # site. This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def page_defaults + not_implemented('page_defaults') + end + + # Saves the given page defaults in the data source. + # + # Subclasses must implement this method. + def save_page_defaults(page_defaults) + not_implemented('save_page_defaults') + end + + ########## Asset defaults + + # Returns the asset defaults (represented by Nanoc::AssetDefaults) of this + # site. This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def asset_defaults + not_implemented('asset_defaults') + end + + # Saves the given asset defaults in the data source. + # + # Subclasses must implement this method. + def save_asset_defaults(asset_defaults) + not_implemented('save_asset_defaults') + end + + ########## Layouts + + # Returns the list of layouts (represented by Nanoc::Layout) in this site. + # This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def layouts + not_implemented('layouts') + end + + # Saves the given layout in the data source, creating it if it doesn't + # exist yet and updating the existing copy otherwise. + # + # Subclasses must implement this method. + def save_layout(layout) + not_implemented('save_layout') + end + + # Changes the path of the given layout to the given new path. When + # changing a layout's path, this method must be used (save_layout will not + # work). + # + # Subclasses must implement this method. + def move_layout(layout, new_path) + not_implemented('move_layout') + end + + # Removes the given layout from the data source. + # + # Subclasses must implement this method. + def delete_layout(layout) + not_implemented('delete_layout') + end + + ########## Templates + + # Returns the list of templates (represented by Nanoc::Template) in this + # site. This is an abstract method implemented by the subclass. + # + # Subclasses must implement this method. + def templates + not_implemented('templates') + end + + # Saves the given template in the data source, creating it if it doesn't + # exist yet and updating the existing copy otherwise. + # + # Subclasses must implement this method. + def save_template(template) + not_implemented('save_template') + end + + # Changes the name of the given template to the given new name. When + # changing a template's name, this method must be used (save_template will + # not work). + # + # Subclasses must implement this method. + def move_template(template, new_name) + not_implemented('move_template') + end + + # Removes the given template from the data source. + # + # Subclasses must implement this method. + def delete_template(template) + not_implemented('delete_template') + end + + ########## Code + + # Returns the custom code (represented by Nanoc::Code) for this site. + # This is an abstract method implemented by the subclass. This can be code + # for custom filters, routers, and more, but pretty much any code can + # be put in there (global helper functions are very useful). + # + # Subclasses must implement this method. + def code + not_implemented('code') + end + + # Saves the given code in the data source. + # + # Subclasses must implement this method. + def save_code(code) + not_implemented('save_code') + end + + private + + def not_implemented(name) + raise NotImplementedError.new( + "#{self.class} does not override ##{name}, which is required for " + + "this data source to be used." + ) end end end