Skip to content

Instantly share code, notes, and snippets.

@rhyhann
Created November 30, 2008 19:04
Show Gist options
  • Save rhyhann/30503 to your computer and use it in GitHub Desktop.
Save rhyhann/30503 to your computer and use it in GitHub Desktop.
# Generations
%w(
rubygems dm-core
sinatra dm-aggregates
uv dm-is-paginated
ostruct dm-types
ritex dm-tags
maruku dm-validations
).each {|n| require(n)}
configure do
DataMapper.setup(:default, "sqlite3:///#{Dir.pwd}/db.sqlite3")
Blog = OpenStruct.new :title => 'My fancy blog!',
:subtitle => 'Some catchy subtitle',
:post_prefix => :post, # Singular because there is only one
:posts_dir => :posts, # Plural because there are a lot
:per_page => 20,
:theme => :pressurized,
:code_theme => :spacecadet,
:engine => :haml,
:track_code => :track_code
DataMapper.auto_migrate!
set :views => "#{Dir.pwd}/#{Blog.theme}",
:public => "#{Dir.pwd}/#{Blog.theme}/public"
end
# Model
class Post
include DataMapper::Resource
property :id ,Serial
property :slug ,Slug
property :name ,String
property :content,Text
has_tags_on :tags,
:categories
is_paginated
validates_is_unique :name
before :save, :define_slug
def define_slug()
attribute_set(:slug, @name)
end
# This function is an alias for <tt>Post.paginated</tt> (from
# dm-is-paginated) that sets the per_page argument to the Blog
# per_page attribute. You just have to give the page number.
def self.paged(page)
all.paginated :page => page.to_i,
:per_page => Blog.per_page
end
# This function returns the first slugged post which matches the
# given slug.
def self.slugged(slug)
all.each {|n| return(n) if n.slug == slug}
end
# Alias for <tt>Post.all_tags(:categories)</tt>
def self.categorized() all_tags(:categories) end
# Alias for <tt>Post.all_tags(:tags)</tt>
def self.tagged( ) all_tags(:tags ) end
# This is a function that saves me of a lack of dm-tags:
# it returns all of the tags of the given type (plural)
# *The second argument is _not_ one: it is meant to shorten
# the code*
def self.all_tags(type, elements = [])
all.each do |record|
record.send(
:"frozen_#{type.to_s.singular}_list"
).to_s \
.split(',') \
.each {|element| elements << element}
end; elements.uniq
end
end
# Controller
get '/' do
redirect '/1'
end
get '/*/*/:page' do
type = params[:splat][0]
tag = params[:splat][1]
@posts_count, @posts = Post.paged(
params[:page]
)
p @posts
@posts = @posts.tagged_with(tag, :on => type)
p @posts
send(Blog.engine, :posts)
end
get "/#{Blog.post_prefix}/:post" do
@post = Post.first(:slug => params[:post])
send(Blog.engine, :posts)
end
# Helpers
helpers do
# Alias for link_to(foo, "/#{Blog.post_prefix}/bar"), intended
# to automatically make the post link
def link_slug(*args)
args[1] = "#{Blog.post_prefix.to_s}/#{args[1]}"
link_to(*args)
end
# Generates a link from the name and the given url
def link_to(name, url, options = {})
"<a href='#{url}' #{
options.to_xml_attributes
}>#{name}</a>"
end
# Changes the given hash to xml attributes
# and their values like #=> key=''
def to_xml_attributes
self.map {|k,v| v = "#{k}='#{v.to_s}'"}
end
end
require 'blog.rb'
disable :run
include Sinatra::RenderingHelpers
include Sinatra::Erb
def tex(string = nil, &block)
Ritex::Parser.new.parse((string ? string : block.call))
end
def code(language, string = nil, &block)
Uv.parse( (string ? string : capture(&block)),
"xhtml",
language,
true,
Blog.code_theme)
end
def capture(&block)
block.call
end
# Model
class Post
public
def self.new_parsing(o) Post.new.parse(o) end
# Alias for <tt>self.modify(:update_attributes)</tt>
def update_parsing(r) self.parse(r) end
# This function takes a record, sends the given
# method to the class with the name and the content
# of the two arguments (Ostruct), updates the tag and the
# category list (with the same Struct) and saves it
def parse(variables, method = :update_attributes)
maybe = self.send(
method.to_sym, # The method
{ # The options
:name => variables.name,
:content => Maruku.new(::Sinatra::Erb.erb(variables.content)).to_html
}
) unless variables.is_a? Class
record = maybe == true ? self : maybe
record.tag_list = variables.tags
record.category_list = variables.categories
record.save
return record
end
end
# This module parses the Yaml files
# and returns an OpenStruct hash of them.
module PostUpdater
class << self
def run!
Post.all.each {|post| post.destroy}
Dir.glob("#{Blog.posts_dir}/**/*.yaml").each do |post|
puts "Parsing #{post}…"
post = parse_file(post)
found = Post.first(:name => post.name)
# TEST: Make this a function
found ? puts("Updated #{found.parse(post).name}"):
puts( "New post #{Post.new.parse(post).name}")
end
end
# This function creates a new struct by parsing the file.
# It will first load the Yaml variables and then
# <tt>OParser.treat</tt> the text.
def parse_file(file)
require 'yaml'
o = OpenStruct.new(YAML.load_file(file))
o.content = treat(file)
return o
end
# This function removes the annoying text from the
# file to show the content only
# api:: *private*
def treat(file)
regex = /^--- # P\w*(.*)--- # C[a-zA-Z]*\n/imo
return File.read(file).chomp.sub(regex, '')
end
end
end
PostUpdater.run!
--- # P
name: Foo
tags: bar, baz
categories: Morocco
--- # C
Chaft boun dakh *atzai*
**This does not work:**
<% tex do %>
\alpha^\beta
2 \times 2
<% end %>
** This does not work:**
<% code "ruby" do %>
def(a)
Class = b,c
end
<% end %>
** This works!**
<%= tex <<-'EOF'
\alpha^\beta
2 \times 2
EOF
%>
** This works!**
<%= code "ruby" <<-'EOF'
def(a)
Class = b,c
end
EOF
%>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment