I have had a web site forever - but not really a blog. Guess it is
time to experiment with the date-driven style and see what I think. At
least with Octopress (or Jekyll), I don’t have to give up my beloved
emacs + git for an unwieldy CMS. (Confession: other than some tedium
remembering the not-quite-html tag syntax, I really love DocBook for
collecting my notes, how-tos, etc.)
Following the instructions on the Octopress setup page,
I cloned the repository from Github.
When I cd’ed into the directory, RVM asked me if I would approve the
.rvmrc file that required Ruby 1.9.2. I am trying to move all my
development to Ruby 1.9.3 so I would prefer not to install 1.9.2 if I
don’t have to. I looked around (esp. through the issues queue) to try
to see why the requirement is for 1.9.2 instead of just > 1.9.1. All I
could find was a ticket that said “just use RVM and install 1.9.2
already!” but didn’t enumerate any issues with 1.9.3. So I may end up
falling back but at least for the initial setup, I am going to push
ahead with 1.9.2-p194 which is the current stable patch level.
rvmgemsetcreateoctopressbundleinstallrakeinstall
All seems to have installed and run just fine - even the dependencies
like posix-spawn, fast-stemmer, ffi, and rdiscount which have native
extensions. So I updated my copy of the .rvmrc file with my ruby and
gemset.
Next I followed the instructions for setting up
rsync deployment -
putting my information in the Rakefile. And
configured a few options to
add my GitHub and Twitter feeds to show in the sidebar. (Still need to
figure out why the GitHub section still says “Status updating…”) and
then used the supplied rake task
to create the file for this post. The preview (rake preview)
looks great!
It remains to be seen if I am going to like markdown. Having to close
tags is tedious, but in the end, it is often less time consuming than
looking up the alternative syntax for the non-html markups. But looks
like I can use at least some regular html tags inside this markdown
file if I want to.
I have always started any project from the database perspective. The
whole test-first/behavior-driven-development movement has led me to
think I would be better off starting from the user interface and
throug the stack to the back end. But for me the data model layer is
always the easiest. And I actually kind of like SQL so the ORM claims
that “you’ll never have to write SQL again” were not a strong selling
point - at least not for me. For me the biggest selling point for
ActiveRecord (the first ORM I really used) was that I didn’t have to
write all the getters/setters in the Ruby side. That and the ease of
grabbing related objects and getting them as real objects - not as
rows containing attributes from both tables. All the Ruby
metaprogramming magic that gives you Foo.find_by_name is nice and
makes for very readable code, but that is merely a convenience for me,
not a necessity like the object creation feature.
My group at work is in the process of moving from a very simple home
grown…. I am not sure it is actually a full blown ORM… perhaps
automated query builder? We are a python shop and have decided to
adopt SQLAlchemy (currently version
0.7.2). I am in the process of reading the
tutorial for the
first time and wanted to record my initial impressions.
For starters, as you might expect from the difference in Ruby
vs. Python cultures, SQLAlchemy is more explicit than
ActiveRecord. SQLAlchemy has what is called a “declarative” mode where
you define your class and your table all at once (within a class that
inherits from SQLAlchemy’s declarative_base class). But you can also
explicitly create, edit, and inspect an explicit metadata object which
defines the table. Then you can define a Python class for your object -
and then use SQLAlchemy’s mapper to introduce the two.
Non-database attributes
How do the two ORMs deal with model attributes that do not have
corresponding database columns? For example, user models commonly ask
for a password and a password confirmation in a user form. But what is
generally stored in the database is an encrypted form of the password
(sometimes called encrypted_password). In Rails/ActiveRecord, you
generally create the database migration with the columns that should
be in the database, then add password and password_confirmation
attributes to the model using attr_accessible. And then
you create a "before_save" filter that encrypts the
password and stores it in the encrypted_password field. In SQLAlchemy,
you can create tables and model classes with different attributes. The
mapper step matches the attributes with the same names AND appears to
have added an "encrypted_password" attribute to the
python object - even though it was not defined in the python class.
Commit behavior
With SQLAlchemy it seems you always have to explicitly commit to get
changes written to the database. I have gotten used to ActiveRecord’s
mix of implicit and explicit writing to the
database. ClassName.create() automatically saves - but
ClassName.new() does not. Updates to an ActiveRecord
object usually need to be explicitly saved to write to the
database. There are some exceptions, for example, when you assign an
object to a has_one association, the parent object is automatically
saved (in order to update its foreign key). Reading the ActiveRecord
docs it sometimes sounds confusing, but in practice, it usually
behaves as I want it to. On the other hand, SQLAlchemy’s requirement
for an explicit session.commit() also means it is easier
to intervene with an explicit session.rollback() if you
decide you don’t want to persist the changes you have made to your
Python object.
Data Definition
SQLAlchemy has nice, explicit syntax for defining your schema but
still in a database agnostic way. Column('name', String(30))
is a pretty easy mental mapping from name varchar(30).
The ActiveRecord equivalent, t.string :name, :limit => 30,
isn’t bad but isn’t superior either.
Query syntax
The new Rails3 syntax - with chained method calls rather than a hash
of options - looks more like SQLAlchemy than it used to. And I suspect
they may behave more similarly too - building up a query from pieces
and then executing it. But just the fact that the SQLAlchemy tutorial
covers how to use subqueries shows that writing SQLAlchemy queries is
closer to real SQL than writing ActiveRecord is.
If you have a particularly tricky set of SQL, both ORMs let you create
your own SQL. In ActiveRecord this is done with the
find_by_sql method. In SQLAlchemy, it is done using
from_statement:
session.query(User).from_statement("SELECT * FROM users where name=:name").params(name='ed').all()
SQLAlchemy can return an iterator or an object or a list.
session.query(PythonClassName).filter(<conditions)
returns an iterator that will feed you instances of PythonClassName in
a loop. You can also return objects and list of objects by setting the
query to session.query and then calling query.one(),
query.first(), or query.all(). The query.one()
behaves rather like ActiveRecord’s ClassName.find()</code> in
that it wants exactly one result row and will throw and exception if
the return is not exactly one row.
Relationships
Both ORMs have syntax for defining relationships. The ActiveRecord
syntax is very English-like: has_one :foo, belongs_to :bar,
has_many :widgets. The SQLAlchemy syntax is not as streamlined
but it may make it easier to do some explicit joining. ActiveRecord
is fabulous - unless your schema doesn’t want to use its naming
conventions. There are, in theory, modifiers to the relationship
defining methods that are supposed to let you get around that. But in
practice, at least as of Rails 2.3, they don’t always work
consistently and you can get a ways into your code before discovering,
for example, that the cascading delete of related objects doesn’t work
because the generated sql is looking for the column “id” rather than
“foo_id”. In SQLAlchemy the syntax is:
Many to many relationships are supported in both ORMs and both make a
distinction between m-to-m relationships with boring association
tables (which only contain the 2 foreign key columns) and richer
associations where you store additional data on the association (for
example audit information about when it was created, and by whom). In
ActiveRecord, those two cases are :has_and_belongs_to_many and
:has_many_through. In SQLAlchemy, the simple case is
taken care of by adding "secondary="</code> to the
relationship definition. The richer case is taken care of by creating
an association object and then establishing relationships between each
object and the association object. The example in the association
documentation isn't super clear (I think calling the relationships
left and right make the names look like keywords). But [this example]
(http://www.preetk.com/node/sqlalchemy-part-2-declarative-bi-directional-association-classes/)
using a standard permission setup makes better sense.
Both ORMs support lazy loading of related objects by default but can
be asked to do eager loading if you ask it to using joinedload()
(SQLAlchemy) or .include() (ActiveRecord)
Web form building
Rails’ ActiveSupport provides form building helpers to take the tedium
out of building data entry forms. The equivalent in the
Python/SQLAlchemy world is provided by
FormAlchemy. I can’t say I
really like the way FormAlchemy does data validation. I found it
rather difficult to figure out how to do custom validations -
especially those where the requirements for one field depend on the
value in another field. In ActiveRecord this is straightforward.
Refinery’s Getting Started guide proceeds by telling you how to start
overriding views for your pages - but first, let’s see what I can do
just with CSS. First, what is the structure of the basic page?
That’s a pretty nice structure. There are some HTML5 semantic tags -
header, footer, section. The entire thing is wrapped into a div with
the id page_container. Content sections are delimited with sections
and divs with ids that should make it pretty easy to pick them out
with CSS selectors. The navigation is an unordered list that should be
easy to style into a list or a set of tabs. The out of the box page is
plain black and white but is laid out with two columns side by
side. So there must be some styling coming from somewhere. Let’s look
in the normal place for rails stylesheets:
$RAILS_ROOT/public/stylesheets/. The generator created 4
files in that directory: application.css formatting.css home.css
theme.css Very nice - but all they have are comments in them saying
how they should be used. For example, application.css should be used
to override front end styles while formatting.css will be included in
the front end styles AND in the WYSIWYG editor on the back end. That
sounds like a nice structure. But so far, I don’t see actual
CSS. Looking more closely, I see we are including styles from
/stylesheets/refinery/application.css. Where is that coming from? Ahhh
that comes from the refinery-core gem which, being an engine, has a
full rails application structure within the gem. The
public/stylesheets directory inside that gem is where all the backend
styling is coming from - as well as this one refinery/application.css
file.
Interesting. But can I change things? Yup. If I edit the
application.css file in my public/stylesheets/application.css
directory, I can affect the look if the site. I can set backgrounds,
override column widths, etc. The
guide even provides a
very basic set of tabbed navigation. So, for the sites where I already
have a design, it is a pretty straightforward matter of converting
their styles into CSS that matches the default page structure for the
RefineryCMS pages. If I had a particularly complicated design, I could
override the RefineryCMS views to fit with my CSS. But in the first
instance, the site I am converting uses a series of nested
tables , so changing the layout to something more modern is a
good idea anyway.
Refinery also claims to support SASS stylesheets - there is even a
section in the getting started guide
specifically about stylesheets. However after some confusion about
where to place the code in that guide, I discovered I really didn’t
need it - at least in development mode. All I needed to do was
add gem 'sass' to my Gemfile and rerun bundle
install. Some deep Rails magic automatically recompiles my SASS
templates at each page load which made modifying the design pretty
fast. However, I am still struggling to figure out how to make this
work out in production mode.
Refinery has an excellent set of
documentation. I am on a new server
but one with a very old ruby, so I had to start by installing
RVM, installing ruby 1.8.7 and creating a gemset to
use for my refinery projects. I chose 1.8.7 because of some of the
slow start up problems with rails on 1.9.2 - but later I found that
Heroku was recommending 1.9.2. Oh well, I’ll fix that later.
So following the Getting Started guide, I
did: gem install refinerycms and then refinerycms
refinerytest -d postgresql -u cnk -p sekrit The flags I used
were not in the getting started guide - but I found them
using refinerycms --help. I already have a Postgresql
database (9.0.4) installed and I have admin access to it. So using
those flags, I was able to specify Postgresql rather than SQLite,
configure it, and then the installer could run the migrations for
me. The one flag that appears to be missing is a host flag for the
database configuration. So the automatic database configuration and
migration only works if your database is available on localhost. If it
isn’t, no matter, the installer will tell you that you need to
complete the configuration and then run rake db:migrate.
(Note, a flag for host was added just a little while after I did this
setup.)
The installer finishes by suggesting you run rails server and look at
your site at http://localhost:3000. The installer did not create an
initial admin user in the migrations. That means there isn’t a
standard username and password - which is nice for security. To fix
this, the refinery server startup detects there isn’t an existing user
and prompts you to add one. Once you have created the initial user,
you are redirected to the refinery admin section where you can see the
recent activity (e.g. the addition of your admin user). At the top of
the page is a suggestion that you update the name of your site - and a
link to the settings editor where you can do that.
So far, I am really impressed. The install and setup process is quite
smooth and well documented - with well placed hints at strategic
points along the way. Very professional. My initial impression of the
admin interface is that it is clean, well organized, and pretty
intuitive. In the upper left hand corner is a link to view the public
version of the site…. Ugh!
The back end is nicely laid out and themed - good tabbed interface,
very professional looking. But the front end is completely unstyled
(or almost completely). That probably makes sense in the context that
Refinery was developed in - for a professional web consulting shop who
almost certainly has designers on retainer if not on staff. For my
current site conversion project the lack of styles is also probably a
good thing. But for some other projects I have in mind, the lack of
even basic styling means that the first thing I am going to have to do
is come up with a design. Not my favorite part about web work. In my
professional life I have mostly had the good fortune to work on teams
who had designers - really good designers - so it isn’t a skill I have
developed. I know from a previous experience with Radiant that it
comes out of the box looking pretty good.
The problem with content management systems is that everyone wants
something simple - but it also needs to have XYZ feature. And since
everyone’s ‘must have’ feature is different than someone else’s ‘must
have’, pretty soon you have a giant feature set and everyone is
complaining it isn’t simple any more. So for the last ten years, I
have been building custom content management systems in a variety of
languages. Most recently, I have been building and extending content
management systems in Ruby on Rails. Because of some specific
integration needs, I think that was a good choice for us at the time -
and may continue to be because of our installed base (35 groups and
counting). However I thought it might be nice, for my personal sites,
to evaluate some of the generally available options for modern Rails
CMSs.
About two and a half years ago, there was a series of quite insightful
blog posts comparing three Rails CMS offerings on a blog named
helpfully “Which Ruby CMS Should I Use”.
Youssef Chaker decided to build a basic conference registration site
with social media features in BrowserCMS, Radiant, and AdvaCMS and
blog about his experience. Ironically that site did not use any of the
CMSs under evaluation. Instead he used Jekyll,
the “blog aware, static site generator” written in ruby. Since I
have always maintained (or some might say neglected) my personal web
sites using emacs + version control, I may include Jekyll in my
evaluation just for fun.
While I may decide that Jekyll is the perfect tool for me, I don’t
think it will be a good choice for the project I have in mind:
transferring some friends’ professional web sites into a CMS so they
can edit them themselves instead of paying a web designer to make
simple content updates. Each of them has a current site with some
standard content - and then they are linking out to a blog
site. Originally I think the blog was intended as a blog. But it
evolved into the only place to get new information because it was the
only part of the site that the owner could update themself.
With that audience in mind, I am looking for a CMS that is:
Easy for the end user to update page content. If they change their
phone number, they should be able to hop into the admin interface, go to the
“Contact” page and change the phone number in 10 minutes or less.
They should be able to upload new pictures and place them into new or
existing pages.
It should be easy to embed YouTube videos in their pages if they want.
The blog should function as a basic blog (tags, reverse chronological
listings). I am not sure if they will want to take the time to manage
comments or not, so the comment feature should do some spam detection
OR allow moderation OR be configurable so it can be turned off
completely.
It should be easy for me to transfer their current site design to
the new site.
Easy for me to set up (this is a side project for me). This means it
should run a fairly recent version of Rails and not have any
particularly exotic dependencies.
Support for hosting on Heroku would be nice.
And the CMS should not get in the way of me adding custom features to
the site using standard Rails development techniques. I don’t
currently envision doing any custom development on these sites but I
don’t want to have to move them to something else if we do come up
with some cool idea - for example a distance learning tool.
Similarly, the tool shouldn’t get in the way if we want to integrate a
small e-commerce or donations component.
Looking around there are a couple of projects that look
interesting. Radiant has stood the test of
time but is still under active development. I like
RefineryCMS’s engine-based design. I was a
big fan of engines back in the Rails 1.1.6 days but gave up on them
when it became too difficult to move them forward to Rails 1.2. I was
really pleased when the Merb team championed the concept and got them
accepted into the Rails 3 rewrite. I am also interested in trying
AdvCMS - though I am a little concerned there
hasn’t been a new release since I last tried (and failed) to install it.
Update December 2020: A few years ago, I was transferred to a group
that primarily uses Python and a few years later, my boss discovered
Wagtail, a CMS built on top of Django. It has
been a great platform to use for work and I think it is also an
excellent choice for people to use building and maintaining their own
web sites - if they know how to host a web site. That is a very big
“if” and I am afraid that my current recommendation for most of my
non-tech friends would be to create something on
SquareSpace and go back to managing
their primary business.