Ardekantur

Computer Science, Ruby, and Software Engineering.

Sinatra 0.9 and Pre-RSpec Modifications

I have no idea if this is the right way to do this, but it certainly works. Say you’re working in Sinatra 0.9, and have an application that subclasses Sinatra::Base. Call it AwesomeApp. What if you want to fiddle around with it — in my case, set application options — before RSpec starts running with it? Well, you do something like this:

spec_helper.rb

require 'rubygems'
require 'my_sinatra_app'
 
AwesomeApp.set :custom_option, "wopphta"
@app = Sinatra.new AwesomeApp

Then, you can make sure it exists:

awesome_app.rb

require 'rubygems'
require 'sinatra/base'
 
class AwesomeApp < Sinatra::Base
  get '/' do
    Sinatra::Application.custom_option
  end
end

It’s my fervent hope that I can use this abstract option-setting for individual instances of the AwesomeApp class in production mode. If that’s not the case, then oh well, but at least I have a way of setting test-specific options in the app.

Spaces Application Assignments are too Literal

2 by 3 Spaces

Here was my original configuration. Two columns of spaces, three rows. Note the application assignments. I’ve asked Mail.app to stay on Space 5.

3 by 3 Spaces

This is my new configuration. Three by three spaces. The application assignments haven’t changed, but they’ve changed in spirit. Where I was consigning Mail.app to the bottom left corner, it now sits right in the middle. Apple already has a plan for when the number of spaces are reduced – push everything from the removed ones onto the remaining ones. Shouldn’t there be a smarter way to handle the addition of spaces? If something’s in a corner, keep it there. If something’s on the top row, keep it there. I doubt there’s an intuitive way to both do this and keep the numbering system Leopard uses for designating spaces, but if anyone can do it, it’s Apple.

Canticore has Filters! Making Markdown Work for Us

I was going to create a new repo on GitHub to show off this awesomeness, but then I figured, why not just show everyone how to use the new filter functionality?

Minus all the cruft of being a gem, this is the only code you’ll write to create a Markdown plugin for your Canticore blog.

require 'canticore/plugin'
require 'rdiscount'
 
Canticore::PluginGem::Create 'markdown' do
  enhances :all
 
  def to_markdown_formatted_html data
    RDiscount.new(data).to_html
  end
 
  filter [:post, :body], :to_markdown_formatted_html
end

That filter command does exactly what you expect it to. Every time it comes across a post body, it sends it as the parameter to the function to_markdown_formatted_html! Simple as that.

Theme designers, take note: Filters are not applied automatically! The HAML line = post.body will still output the plain post body, and not spin up the filter function at all. The line = post.filtered(:body), however, will!

I haven’t yet decided if filters can be arbitrarily ordered. I think that’s needless complexity and I can’t think of a good reason to do so.

Interested in developing Canticore or for Canticore? There hasn’t been a better time to get started! Send a message to my GitHub profile if you’d like to contribute, and I’ll point you towards some thing that needs to be done. I have a fucking laundry list, here.

Canticore – A new look at blogging engines.

I’d like to talk about blogging for a bit. I know, it’s a horrible subject that’s been done to death, but I began working on a project recently that I hope will try to provide a clean, simple, robust solution for the next generation of bloggers and programmers.

It’s called Canticore. It’s written in Ruby, and has the features I want in it, but this feature list may be common to a lot of people.

  • (Multi)Markdown support
  • Aggressive Caching
  • Threaded comments
  • Multiple users
  • Painless upgrade
  • Rich RSS (by category, post, tag, comment)
  • Static pages
  • Support for common blogging APIs (Blogger, metaWeblog, Movable Type)
  • Syntax Highlighting
  • Trackbacks
  • Web administration

The most important feature is one that I think will make the difference. Plugins and themes are RubyGems. That’s it. That’s the killer thing. That’s what’s most important to me. I sat down and knew I wanted hooks and filters, themes, all that good stuff, but as I worked on the domain for those things, I realized RubyGems did everything I wanted my plugins and themes to do: simple versioning, metadata, easy installation and painless upgrading. So that became my new goal.

At this point, the codebase is a bit of an uncommented mess, but it has everything in place to make my goals work. This early announcement was pre-empted by two things: Matt’s removal of themes from wordpress.org, and GitHub’s announcement of their new feature, GitHub Pages: the former, because theme and plugin submissions on canticore.org will be provided with the ability to choose a license upon submission, and the latter because people might flock to that instead of looking for alternatives :-)

The repository is available at GitHub, along with the official website repository, some plugins to ensure certain functionality is baked in, and the first theme, called default.

I’ve secured a gorgeous place for people to upload gems that they create. I was considering creating a sub-reddit for this purpose, and not do any of this work, but I also wanted a demo server for people to try out themes that interest them. If you’re interested in contributing, or having a say in the next feature, or want to file bugs or tests, join the conversation! I want to make something exciting and beautiful, but I know I may not have the time to do it alone, anymore.

For people interested in how it works for plugin and theme developers, keep reading.

Plugins

Imagine being able to write a blog plugin with proper object-orientation! :-) Plugins have an extremely simple syntax that you can pick up just from reading a sample.

  require 'canticore/plugin'
 
  Canticore::Plugin::Create 'theme-changer' do
    enhances :index
    variable :before_text, 
      { :summary => "Dropdown Prefix Text", 
          :desc => "Text to display before the drop-down.",
          :default => "Change Theme: " }
 
    def output
      haml :output
    end
 
    hook :body, :output
 
  end

The #enhances block tells the blog what pages the plugin should be enabled on: :index just means it will be enabled on the landing page, and not archive pages, individual post pages, static pages, et cetera. You can also use enhances :all for a blanket enabling.

Each variable you want the user to change and be able to save to the database begins with a #variable function. Give it a name and a list of options.

Hooks are where you attach your functionality to Canticore. Right now there’s only a few, :body being one of them. The line hook :body, :output tells Canticore to attach the output of the function called :output to the body hook. You can use HAML for your plugins, in this case the function output looks for a file called views/output.haml in your plugin gem to render.

Filters are coming.

Themes

Themes are designed in HAML and can use SASS and plain old CSS. You need certain layout pages for your theme to be valid:

  • archive.haml for archive listings.
  • index.haml for the landing page of your blog.
  • layout.haml for the global layout.
  • page.haml for static page content.
  • post.haml for individual post pages.
  • _entry.haml for what a post will look like when displayed in a listing.

And that’s it! Static content goes in your gem under static, and stylesheets go under stylesheets, whether or not they’re SASS or CSS. Canticore is smart enough to figure it out. The name static/snapshot.png is reserved for the screenshot you want to take of your theme to display to users on canticore.org and in Canticore’s administration panel.

Looks Like Spammers Don’t Write Tests

Nicked from a spam harvest on my blog:

    =======================================================
    Report on Comment number 1 (id=2390)
    Comment Author: FIELD_NICKNAME
    Comment Content: 
    -----------------------------------------
    FIELD_MESSAGE_cnaroronoo