sidcom.me.uk
The Site
I have a young relative who draws a lot of comic strips, and thinking it would be nice if he could publish them, I looked around for an Open Source system.
I wanted something that was as near to XKCD as possible - latest comic, next/previous and random.
Not finding anything that was both pretty and ultra-simple, I decided to write my own.
The version for my relative is here - the system will be up on GitHub as soon as I finish making it configurable.
Technologies
Web Framework
If you've read the title of this post, you won't be surprised to read that I chose Sinatra.
Database
I decided to use DataMapper as the ORM.
I'm also using SQLite for both development and production.
HTML and CSS
As will be clear from the example site, I didn't work over hard on making a fresh graphic look -
all I did was strip out a lot of HTML that was there to make rounded corners,
and replaced it with Mozilla and WebKit specific rounding.
I then translated the HTML into HAML and
the CSS into SASS (SCSS).
Development
Documentation for Sinatra, DataMapper, HAML and SASS is quite good, so things went quite smoothly.
What follows is a list of the phases I went through while developing (on Ubuntu), and especially the bits I had trouble with.
DataMapper
Installation
$ sudo gem install dm-core
$ sudo gem install data_objects
$ sudo gem install data_mapper
$ sudo gem install do_sqlite3
Using DataMapper in Code
require 'dm-core'
require 'data_mapper'
DataMapper.setup({
:adapter => 'sqlite3',
:host => 'localhost',
:username => '',
:password => '',
:database => 'db/sidcom_development'
})
class Comic
include DataMapper::Resource
property :title, :text
property :permalink, :text
property :created_at, :datetime
property :updated_at, :datetime
end
Comic.auto_upgrade!
The 'Comic.auto_upgrade!
' bit handles migrations -
at startup, table columns are adjusted to match the declaration in the equivalent class.
Rack
Authentication
This application has a 'public' and an 'admin' area, so I actually created two Sinatra Apps, wrapping one in Rack::Auth::Digest::MD5.
A local settings file holds user names and hashed (kinda salted) passwords.
Sinatra
Sinatra apps have access to a number of globals, I used:
params
Helpers
This app being a little more complex than my first, I decided to implement some Rails-like helpers.
The most important helper is url_for
.
Sinatra - by design - includes routing in the structure of an app, so it cannot provide pre-cooked methods of the sort.
HAML
I found HAML very easy to start using, what I didn't immediately understand was:
how to interpolate variables,
how to call functions,
and how to include partials.
These are actually all the same problem, but it took me a while to realize that!
In HAML, you can interpolate the Ruby way (with '#{...}
') or the HAML way (with '=
').
Variable Interpolation
Just use Ruby String interpolation:
%h1 Hello #{ @name }!
Calling Functions
Use HAML evaluation syntax:
%h1
= @name
!
HAML partials
Again, these can be evaluated as above:
= haml(:_my_partial, :layout => false)
SASS
Generating CSS
I chose to keep my SCSS files in a subdirectory under my views directory, and generate CSS from them under the static path.
During development, you need to keep the static versions up to date, and to do so, you just need to keep a process running as follows:
$ sass --watch views/stylesheets:static/stylesheets
Conclusion
Sinatra handles small sites very well.
The code can be kept DRY, and if you decide to, Sinatra projects can be quite easily transformed into Rails projects.
Actually, I have doubts whether it was worth doing this project in Sinatra -
a stripped-down Rails 3 project would have been just as lightweight and easy to develop.
But, then again, it's useful to run a system through its paces, to have an idea what areas it can usefully be applied to.