begin ; require 'active_record' ; rescue LoadError ; end module Nanoc::DataSource::Database ########## Helper classes ########## begin class DatabasePage < ActiveRecord::Base set_table_name 'pages' end class DatabasePageDefault < ActiveRecord::Base set_table_name 'page_defaults' end class DatabaseTemplate < ActiveRecord::Base set_table_name 'templates' end class DatabaseLayout < ActiveRecord::Base set_table_name 'layouts' end class DatabaseCodePiece < ActiveRecord::Base set_table_name 'code_pieces' end rescue NameError end class DatabaseDataSource < Nanoc::DataSource ########## Attributes ########## identifier :database ########## Preparation ########## def up nanoc_require 'active_record' # Connect to the database ActiveRecord::Base.establish_connection(@site.config[:database]) end def down # Disconnect from the database ActiveRecord::Base.remove_connection end def setup # Create tables schema = ActiveRecord::Schema schema.verbose = false schema.define do create_table :pages, :force => true do |t| t.column :content, :text t.column :path, :string t.column :meta, :text end create_table :page_defaults, :force => true do |t| t.column :meta, :text end create_table :layouts, :force => true do |t| t.column :name, :string t.column :content, :text t.column :extension, :string end create_table :templates, :force => true do |t| t.column :content, :text t.column :name, :string t.column :meta, :text end create_table :code_pieces, :force => true do |t| t.column :name, :string t.column :code, :text end end # Create first page DatabasePage.create( :path => '/', :content => "I'm a brand new root page. Please edit me!\n", :meta => "# Built-in\n" + "\n" + "# Custom\n" + "title: \"A New Root Page\"\n" ) # Create page defaults DatabasePageDefault.create( :meta => "# Built-in\n" + "custom_path: none\n" + "extension: \"html\"\n" + "filename: \"index\"\n" + "filters_post: []\n" + "filters_pre: []\n" + "is_draft: false\n" + "layout: \"default\"\n" + "skip_output: false\n" + "\n" + "# Custom\n" ) # Create default layout DatabaseLayout.create( :name => 'default', :content => "\n" + " \n" + " <%= @page.title %>\n" + " \n" + " \n" + "<%= @page.content %>\n" + " \n" + "", :extension => '.erb' ) # Create default template DatabaseTemplate.create( :name => 'default', :content => 'Hi, I\'m a new page!', :meta => "# Built-in\n" + "\n" + "# Custom\n" + "title: \"A New Page\"\n" ) # Create default code piece DatabaseCodePiece.create( :name => 'default', :code => "def html_escape(str)\n" + " str.gsub('&', '&').str('<', '<').str('>', '>').str('\"', '"')\n" + "end\n" + "alias h html_escape\n" ) log(:high, "Set up database schema.") end ########## Loading data ########## def pages # Create Pages for each database object DatabasePage.find(:all).inject([]) do |pages, page| # Read metadata hash = (YAML.load(page.meta || '') || {}).clean if hash[:is_draft] # Skip drafts pages else # Get extra info extras = { :path => page.path, :uncompiled_content => page.content } # Add to list of pages pages + [ hash.merge(extras) ] end end end def page_defaults YAML.load(DatabasePageDefault.find(:first).meta) || {} end def layouts DatabaseLayout.find(:all).map do |layout| { :name => layout.name, :content => layout.content, :extension => layout.extension } end end def templates DatabaseTemplate.find(:all).map do |template| { :name => template.name, :content => template.content, :meta => template.meta } end end def code DatabaseCodePiece.find(:all).map { |p| p.code }.join("\n") end ########## Creating data ########## def create_page(path, template) # Make sure path does not start or end with a slash sanitized_path = ('/' + path + '/').gsub(/^\/+|\/+$/, '/') # Make sure the page doesn't exist yet unless DatabasePage.find_all_by_path(sanitized_path).empty? error "A page named '#{sanitized_path}' already exists." end # Create page DatabasePage.create( :path => sanitized_path, :content => "I'm a brand new page. Please edit me!\n", :meta => "# Built-in\n\n# Custom\ntitle: A New Page\n" ) log(:high, "Created page '#{sanitized_path}'.") end def create_layout(name) # Make sure the layout doesn't exist yet unless DatabaseLayout.find_all_by_name(name).empty? error "A layout named '#{name}' already exists." end # Create layout DatabaseLayout.create( :name => name, :content => "\n" + " \n" + " <%= @page.title %>\n" + " \n" + " \n" + "<%= @page.content %>\n" + " \n" + "", :extension => '.erb' ) log(:high, "Created layout '#{name}'.") end def create_template(name) # Make sure the layout doesn't exist yet unless DatabaseTemplate.find_all_by_name(name).empty? error "A template named '#{name}' already exists." end # Create template DatabaseTemplate.create( :name => name, :content => "Hi, I'm a brand new page!\n", :meta => "# Built-in\n\n# Custom\ntitle: A New Page\n" ) log(:high,"Created template '#{name}'.") end end end