General Genetic Algorithms for Ruby (gga4r) release 0.9

Posted about 7 years back at Spejman On Rails

General Genetic Algorithms for Ruby (gga4r) is a library for executing generic algorithms easily.

Only 3 steps are needed in order to work with gga4r:

  1. Choose a clase to evolve and define for her the fitness, combine and mutate methods.

  2. With an array of last defined class instances (initial population), create a GeneticAlgorithm object.

  3. Call GeneticAlgorithm's evolve method as many times as you want.


More info:

Kathy and Chris sitting in a tree...

Posted about 7 years back at Wood for the Trees

Really hot stuff this Kathy Sierra nonsense. Oh wait, a tasteless pun. Is everyone going to hate me now? Grow up!

I usually don’t wade into political debate because it is full of morons, but it’s the middle of the night and I’m really bored. In fact, annoyed. Like I was with Rails 1.2 (how’s that for continuity!)

Who I Sympathise With and Who I Support

I’ll give, frankly, my sympathy to Kathy (who is manic, slightly weak-willed, has some good ideas, some other ideas a little dodgy, and has all the traits of a modern American woman, for good or ill) but I give my serious support to those calling for uncommon sense. This situation is so cliched and yet has slipped passed a few people I respect that I’m going to kill some time here and point out that Dave Winer, who I never heard of before, is right to be skeptical. He made just one mistake: he wasn’t confident enough to spell out why others should be. Please, please stop fuelling the media. It’s just evil.

So, without further ado, the train of thought:

The gist of my view:

  • Threats and offensive comments on the internet are newsworthy, therefore not worth my time (unless I’m killing it).
  • Being a high-profile speaker in the IT world will have its share of ‘acerbic’ commentary
  • Being a blogger will get you the same
  • Putting your details online is just dumb
  • Men abuse each other using sexual language, but we’ve got used to it over the last five millenia and now think it’s kind of amusing

For example, the Bile Blog, which is an institution in slagging shit off. Thankfully it still exists. Poor Hani doesn’t get a BBC article because the Bile stays strictly asexual. But in a post-feminist, emasculated society, you can get really hated for saying anything remotely gender-specific. I’m sorry, but I don’t buy that. It’s proscriptive and - for the same reason I think I should be able to take a pie or bottle of water on a plane even at the risk of being blown up - molly-coddling. Anyone with some self-respect and decency should feel a little spineless and self-indulgent if they coddle Kathy. A mild dose of feminist support is fine, because I like women to be people rather than objects, but indulging in the mass opinion is, well, like getting a labotomy. Some of the points Kathy made were, of course, right: it’s pretty sick some of those things she cited. However, it’s not rocket science to see she is also over-reacting and taking the majestic ‘blogosphere’ with her. Her avid fans who want to hang her are most likely infantile, possibly autistic twits in the middle of nowhere, with the social graces of a louse.

What’s the truth?

The situation is as plain as a Bulgarian pin-up. Kathy takes the net seriously and flips out. Her readers, which are many, believe her. Others who see those believe her think the readers must be right because there are so many of them. A few people are skeptical and they are lampooned, making the case even stronger that Kathy is being persecuted. It goes to the media, which means it must be true!

Qualifications

Please realise that there are minorities of both idiots and intelligent people in the real world just as much as on the internet, with one slight difference: ‘law’ isn’t firmly established online. That’s quite literally fantastical, but true, and we should cherish that infinite freedom. I don’t want a jackboot in my face for telling someone online they can stick their ideas up their cuntflap or hang by their genitals, nor see a person cuffed and imprisoned for behaving as amorally as Sodom. Your morals and theirs may not mix, but that’s neither here nor there. Morality is for religion, not law and the internet is lawless.

All this lovely lawlessness is because of its anonymity. People use that anonymity out of cowardice (yes) but also safety. Uh huh, that’s right. The louse should be protected too, all the way up until he actually clubs Kathy over the head and brings her back to his cave. That’s real free speech. It’s not pleasant sometimes, but it’s very, very important to realise how extreme an idea it is (the original one, not the hashed up piece of shit served by ‘democracies’ around the world).

Summary

Kathy thinks threats are equal to actions, for which she loses my support, though I still hope she pulls out of her mire of self-doubt and back into posting for her readers. Maybe during that period she should read some comforting Spinozan ideas on epistemology and semantics.

Resorting to qualified (that is, reasoned) support and sympathy is quite different from just jumping on the wagon of lynchers, to use Chris Locke’s own words.

Just as a reminder, this is where enforcing morality leads. BBC are really getting lazy; they’ve got two articles on mass hysteria. But they are the news and cater to the lowest common denominator. It’s quite different when respected, intelligent individuals are the cause of the stir. I only hope some of you will give it a little more consideration next time and do the intelligent thing: be as long-winded as I am. Then no journalist could bear reading it.

Kathy and Chris sitting in a tree...

Posted about 7 years back at Wood for the Trees

Really hot stuff this Kathy Sierra nonsense. Oh wait, a tasteless pun. Is everyone going to hate me now? Grow up!

I usually don’t wade into political debate because it is full of morons, but it’s the middle of the night and I’m really bored. In fact, annoyed. Like I was with Rails 1.2 (how’s that for continuity!)

Who I Sympathise With and Who I Support

I’ll give, frankly, my sympathy to Kathy (who is manic, slightly weak-willed, has some good ideas, some other ideas a little dodgy, and has all the traits of a modern American woman, for good or ill) but I give my serious support to those calling for uncommon sense. This situation is so cliched and yet has slipped passed a few people I respect that I’m going to kill some time here and point out that Dave Winer, who I never heard of before, is right to be skeptical. He made just one mistake: he wasn’t confident enough to spell out why others should be. Please, please stop fuelling the media. It’s just evil.

So, without further ado, the train of thought:

The gist of my view:

  • Threats and offensive comments on the internet are newsworthy, therefore not worth my time (unless I’m killing it).
  • Being a high-profile speaker in the IT world will have its share of ‘acerbic’ commentary
  • Being a blogger will get you the same
  • Putting your details online is just dumb
  • Men abuse each other using sexual language, but we’ve got used to it over the last five millenia and now think it’s kind of amusing

For example, the Bile Blog, which is an institution in slagging shit off. Thankfully it still exists. Poor Hani doesn’t get a BBC article because the Bile stays strictly asexual. But in a post-feminist, emasculated society, you can get really hated for saying anything remotely gender-specific. I’m sorry, but I don’t buy that. It’s proscriptive and - for the same reason I think I should be able to take a pie or bottle of water on a plane even at the risk of being blown up - molly-coddling. Anyone with some self-respect and decency should feel a little spineless and self-indulgent if they coddle Kathy. A mild dose of feminist support is fine, because I like women to be people rather than objects, but indulging in the mass opinion is, well, like getting a labotomy. Some of the points Kathy made were, of course, right: it’s pretty sick some of those things she cited. However, it’s not rocket science to see she is also over-reacting and taking the majestic ‘blogosphere’ with her. Her avid fans who want to hang her are most likely infantile, possibly autistic twits in the middle of nowhere, with the social graces of a louse.

What’s the truth?

The situation is as plain as a Bulgarian pin-up. Kathy takes the net seriously and flips out. Her readers, which are many, believe her. Others who see those believe her think the readers must be right because there are so many of them. A few people are skeptical and they are lampooned, making the case even stronger that Kathy is being persecuted. It goes to the media, which means it must be true!

Qualifications

Please realise that there are minorities of both idiots and intelligent people in the real world just as much as on the internet, with one slight difference: ‘law’ isn’t firmly established online. That’s quite literally fantastical, but true, and we should cherish that infinite freedom. I don’t want a jackboot in my face for telling someone online they can stick their ideas up their cuntflap or hang by their genitals, nor see a person cuffed and imprisoned for behaving as amorally as Sodom. Your morals and theirs may not mix, but that’s neither here nor there. Morality is for religion, not law and the internet is lawless.

All this lovely lawlessness is because of its anonymity. People use that anonymity out of cowardice (yes) but also safety. Uh huh, that’s right. The louse should be protected too, all the way up until he actually clubs Kathy over the head and brings her back to his cave. That’s real free speech. It’s not pleasant sometimes, but it’s very, very important to realise how extreme an idea it is (the original one, not the hashed up piece of shit served by ‘democracies’ around the world).

Summary

Kathy thinks threats are equal to actions, for which she loses my support, though I still hope she pulls out of her mire of self-doubt and back into posting for her readers. Maybe during that period she should read some comforting Spinozan ideas on epistemology and semantics.

Resorting to qualified (that is, reasoned) support and sympathy is quite different from just jumping on the wagon of lynchers, to use Chris Locke’s own words.

Just as a reminder, this is where enforcing morality leads. BBC are really getting lazy; they’ve got two articles on mass hysteria. But they are the news and cater to the lowest common denominator. It’s quite different when respected, intelligent individuals are the cause of the stir. I only hope some of you will give it a little more consideration next time and do the intelligent thing: be as long-winded as I am. Then no journalist could bear reading it.

Sometimes It's The Little Things...

Posted about 7 years back at zerosum dirt(nap) - Home

With this latest RoR project, we decided for the first time to take a RESTful approach. It’s taken me much longer than it should have to come to terms with what that actually meant, but after suffering through the change of mindset, I really do have to say that it feels right. I’m down, you’ve won me over.

That said, there are always little implementation details that annoy the hell out of you. Little, trivial, stupid things. Things that you know you shouldn’t waste precious breath complaining about, things that you annoy your friends about until they ignore you. Things like the use of the damn semi-colon to delimit custom actions for resources in a URI, instead of our old friend the slash.

And then came Changeset 6485, which made everything once again right with the world. Thank gawd that’s over. Now I can get back to being productive :-).

Episode 11: Refactoring User Name Part 2

Posted about 7 years back at Railscasts

Testing and refactoring go hand in hand. Refactoring is all about improving code without changing its behavior. Testing is all about making sure you don't change the behavior while you are improving the code.

Second screencast posted in Flash

Posted about 7 years back at The Hobo Blog

A few folk seem to be having trouble with the audio in the second screencast. We’ve just posted a rough Flash version as a stop-gap solution. The quality is a bit naff but it’s better than not being able to hear anything!

If anyone can recommend a nice tool for converting QuickTime to a good quality backwards-compatible Flash movie, please let us know in the comments. Thanks!

Second screencast posted in Flash

Posted about 7 years back at The Hobo Blog

A few folk seem to be having trouble with the audio in the second screencast. We’ve just posted a rough Flash version as a stop-gap solution. The quality is a bit naff but it’s better than not being able to hear anything!

If anyone can recommend a nice tool for converting QuickTime to a good quality backwards-compatible Flash movie, please let us know in the comments. Thanks!

Episode 10: Refactoring User Name Part 1

Posted about 7 years back at Railscasts

Learn how to clean up your code through refactoring. This episode will show you how to move code from the view into the model to remove duplication and simplify the view.

Episode 9: Filtering Sensitive Logs

Posted about 7 years back at Railscasts

Are you accepting sensitive user data? Passwords, credit card numbers, etc. By default, Rails stores all submitted parameters in plain text in the logs. This episode will show you how to filter this sensitive input so it doesn't show up in the log file.

Is Mephisto Dead?

Posted about 7 years back at Mephisto - Home

Is Mephisto dead? I see much more Typo activity recently than Mephisto. It’s the same with most open-source Rails apps. Development is cyclothymic – people get excited in the beginning, then slow down (or completely stop) – probably work on some “for pay” project, then get excited again (when the paid project is completed maybe?), then slow down again and so on. Substruct, Collaboa, Typo, RadRails, Project RIDE-ME, Active Merchant and many others… I don’t see this happening in Java world and I miss the “die hard” Java enthusiasm in the Rails community. —Nikolay Kolev, comments on previous article

Nope, it’s been on hold since the end of 2006. Mephisto has a tiny development team, and we’re both busy trying to launch a web service. We have 0 funding, so we’ve basically been devoting our “OSS project time” (and “sleep time”) towards Lighthouse instead.

I’ve found that most of the ‘successful’ open source projects have some source of real funding. Either there’s a company that needs the product enough to fund/hire the team, or they make enough through custom installs or commercial versions. Other than a handful of small consulting gigs and some donations, Mephisto has been purely a labor of love for us.

What’s going on right now:

  • I’m entertaining the idea of extending to the core team, but I don’t feel there’s been anyone that seems interested in devoting the time.
  • However, I’m thinking seriously of extracting a few things out as “official plugins” and opening up access on those small areas. The current candidate is XML-RPC support.
  • There’s a small 0.7.4 update with a few security issues and annoying bugs fixed
  • There’s an edge version with some notable new features (plugin admin, plugin support for RHTML/HAML templates, and soon: a multi-site admin)
  • Once Lighthouse goes out of beta, we’ll have an official bug tracker.
  • Core team doesn’t haven’t to mean “svn commit access” either. It could also mean “ticket overlord” or something.
  • DNS info is currently being transferred to moniker…

However, Justin and I are committed to keeping Mephisto true to its roots. We’re not going to turn it into another bloated CMS, or a community blogging tool. It’s also not a kickstart to your rails app development. It’s strictly going to remain a kick ass publishing tool. Further features/integration should be done through the power of hyperlinks or APIs (exposed through custom Liquid drops).

What belongs in the model?

Posted about 7 years back at The Hobo Blog

It’s a regular post-a-thon :-)

I just came across this old post on the Rails blog about Streamlined.

Of particular note:

I really like their approach of using separate UI classes instead of contaminating the model classes with administrative concerns.

That’s DHH, and I wholeheartedly agree. But then Hobo doesn’t have the “separate UI classes”. In fact Hobo does ask you to add extra metadata to your models which is then used in constructing the views.

Have I slipped up? I don’t think so…

Firstly Hobo doesn’t need “UI classes” because DRYML is powerful enough that we can configure everything to our hearts content in mark-up. As I said in my talk at the Skills Matter RoR exchange, it’s like the difference between an app with a preferences dialogue (UI classes where you set a bunch of options) and an app which is scriptable (DRYML).

Secondly, I don’t think I’ve added any metadata to the models that doesn’t belong there. Notice I say “think”. Coming across that post has made me think that I should really review this. So let’s do it – right now :-) fires up Hobo model extensions in trusty Emacs. Let’s make sure all the model extensions really belong there.

Before we start though, how do we decide what belongs in the model and what is merely an “administrative concern”. Is it a clear boundary or a grey one? I have a simple trick I sometimes use to help clarify this design challenge. When the coming Command Line Renaissance happens, and you’re building the fashionable new command-line interface for your app, will you still need this behaviour? If yes, it probably belongs in the model. If no it probably doesn’t. It’s an OO thing. Is this an innate part of the behaviour of the object you are modelling? Is it just something that you need to put this object on the web? Notice that this is a more subtle point than asking “is this a user-interface issue?”. Think about the models in a blog app. It’s all user-interface! The thing only exists in the first place because people want to read the blog!

Bottom line - there will always be grey areas. Some things will be absolutely not appropriate for the model, some will obviously belong in the model, some will be tricker.

OK so lets tour the Hobo model extensions and make some calls.

Permission system

You don’t have to do much coding with Hobo before you realise that modelling the permissions of your various objects is a very central and fundamental part of modelling your domain. To me this very clearly belongs in the model.

I guess you could say that Hobo makes the user model special, and in doing so extends the meaning of modelling to include modelling the rules governing what users are allowed to do to what. I think this has been a huge win and is an idea that could be taken a lot further.

An interesting question though: are these permissions innate to the models themselves, or could we imagine having a different set of permissions for different contexts? Pluggable permissions. Hmmm. How about a concise yet powerful rule-based DSL for declaring permissions? Sheesh - so many ideas so little time…

Extended type declarations.

Hobo lets you say

set_field_type :content => :html

If you then do, e.g.

Post.find(:first).content.class
=> Hobo::HtmlString

(That’s just a pretty much empty subclass of String BTW.) OK this one’s easy. That’s a model concern. No question.

Default order

set_default_order "created_at desc"

That order will then be used in your index pages. There’s a kind of asymmetry in ActiveRecord here – you can specify the default order for has_many collections, but there’s no way to specify a default order for a top-level find(:all). So we’ve really just balanced things out. Model concern.

Never show

never_show :password

The word “show” immediately cries out “user-interface issue!”. In fact this declaration is just a short-hand for something you could do anyway with viewable_by?. So if the permission system belongs in the model, so does never_show.

Creator attributes

set_creator_attr :author

This tells Hobo that the author attribute should be automatically set to the user that creates the object. On the web this means the currently logged-in user for the session from which the object was created. In another context it might mean something else. Again this idea follows naturally from the decision to model users as something special. To me this does belong in the model.

Search columns

set_search_columns :title, :content

This tells Hobo which columns to include in the built-in search feature. This is a bit like writing custom find methods on your models. We already have the magic methods like find_all_by_title_and_content. What we’re doing here is highlighting a particular query as special in some way, which to be honest feels a bit dodgy. Special from what point of view? From the point of view of your web-app? I can see this possibly moving out of the model.

Display name

If your model has an attribute display_name, this is used as the default text for the object in links and such-like. It’s also very useful for logging, and for debugging, and would certainly get re-used in your command-line UI. My feeling is that a display-name is an innate part of a thing, and so this does belong in the model.

OK that’s about it. There are a few other extensions but they’re so obviously part of the model layer that they’re not worth mentioning. So it was only really set_search_columns that was called into question.

The overall feeling I’ve got from this exercise is that the decision to model users as something special, something that has permissions, has lead to a lot more stuff going into the model than might otherwise. I don’t think this is at all wrong, but in asking these questions, some lights have gone on and I can see some advantages of moving this stuff into a separate place. I just wish those ideas didn’t have to get pushed to the bottom of a veeery long to-do list…

What belongs in the model?

Posted about 7 years back at The Hobo Blog

It’s a regular post-a-thon :-)

I just came across this old post on the Rails blog about Streamlined.

Of particular note:

I really like their approach of using separate UI classes instead of contaminating the model classes with administrative concerns.

That’s DHH, and I wholeheartedly agree. But then Hobo doesn’t have the “separate UI classes”. In fact Hobo does ask you to add extra metadata to your models which is then used in constructing the views.

Have I slipped up? I don’t think so…

Firstly Hobo doesn’t need “UI classes” because DRYML is powerful enough that we can configure everything to our hearts content in mark-up. As I said in my talk at the Skills Matter RoR exchange, it’s like the difference between an app with a preferences dialogue (UI classes where you set a bunch of options) and an app which is scriptable (DRYML).

Secondly, I don’t think I’ve added any metadata to the models that doesn’t belong there. Notice I say “think”. Coming across that post has made me think that I should really review this. So let’s do it – right now :-) fires up Hobo model extensions in trusty Emacs. Let’s make sure all the model extensions really belong there.

Before we start though, how do we decide what belongs in the model and what is merely an “administrative concern”. Is it a clear boundary or a grey one? I have a simple trick I sometimes use to help clarify this design challenge. When the coming Command Line Renaissance happens, and you’re building the fashionable new command-line interface for your app, will you still need this behaviour? If yes, it probably belongs in the model. If no it probably doesn’t. It’s an OO thing. Is this an innate part of the behaviour of the object you are modelling? Is it just something that you need to put this object on the web? Notice that this is a more subtle point than asking “is this a user-interface issue?”. Think about the models in a blog app. It’s all user-interface! The thing only exists in the first place because people want to read the blog!

Bottom line - there will always be grey areas. Some things will be absolutely not appropriate for the model, some will obviously belong in the model, some will be tricker.

OK so lets tour the Hobo model extensions and make some calls.

Permission system

You don’t have to do much coding with Hobo before you realise that modelling the permissions of your various objects is a very central and fundamental part of modelling your domain. To me this very clearly belongs in the model.

I guess you could say that Hobo makes the user model special, and in doing so extends the meaning of modelling to include modelling the rules governing what users are allowed to do to what. I think this has been a huge win and is an idea that could be taken a lot further.

An interesting question though: are these permissions innate to the models themselves, or could we imagine having a different set of permissions for different contexts? Pluggable permissions. Hmmm. How about a concise yet powerful rule-based DSL for declaring permissions? Sheesh - so many ideas so little time…

Extended type declarations.

Hobo lets you say

set_field_type :content => :html

If you then do, e.g.

Post.find(:first).content.class
=> Hobo::HtmlString

(That’s just a pretty much empty subclass of String BTW.) OK this one’s easy. That’s a model concern. No question.

Default order

set_default_order "created_at desc"

That order will then be used in your index pages. There’s a kind of asymmetry in ActiveRecord here – you can specify the default order for has_many collections, but there’s no way to specify a default order for a top-level find(:all). So we’ve really just balanced things out. Model concern.

Never show

never_show :password

The word “show” immediately cries out “user-interface issue!”. In fact this declaration is just a short-hand for something you could do anyway with viewable_by?. So if the permission system belongs in the model, so does never_show.

Creator attributes

set_creator_attr :author

This tells Hobo that the author attribute should be automatically set to the user that creates the object. On the web this means the currently logged-in user for the session from which the object was created. In another context it might mean something else. Again this idea follows naturally from the decision to model users as something special. To me this does belong in the model.

Search columns

set_search_columns :title, :content

This tells Hobo which columns to include in the built-in search feature. This is a bit like writing custom find methods on your models. We already have the magic methods like find_all_by_title_and_content. What we’re doing here is highlighting a particular query as special in some way, which to be honest feels a bit dodgy. Special from what point of view? From the point of view of your web-app? I can see this possibly moving out of the model.

Display name

If your model has an attribute display_name, this is used as the default text for the object in links and such-like. It’s also very useful for logging, and for debugging, and would certainly get re-used in your command-line UI. My feeling is that a display-name is an innate part of a thing, and so this does belong in the model.

OK that’s about it. There are a few other extensions but they’re so obviously part of the model layer that they’re not worth mentioning. So it was only really set_search_columns that was called into question.

The overall feeling I’ve got from this exercise is that the decision to model users as something special, something that has permissions, has lead to a lot more stuff going into the model than might otherwise. I don’t think this is at all wrong, but in asking these questions, some lights have gone on and I can see some advantages of moving this stuff into a separate place. I just wish those ideas didn’t have to get pushed to the bottom of a veeery long to-do list…

What's Next?

Posted about 7 years back at The Hobo Blog

Let’s not go so far as to call this a road-map, but I thought I’d just let you know what’s coming up.

The manual needs completing, so I’ll be chipping away at that and posting updates as I go. The manual is only the start of the documentation of course. We still need proper API docs and a decent tutorial. I’d also really like to see some kind of “How To” style docs, with things like “How to add a password reset feature.” “Hobo Recipes” I guess. Those things will have to wait for a while though. For now I’ll be putting my energy into finishing the existing manual.

Then there’s a couple of articles I’m intending to write on new features:

  • Inner Tags
  • Composite Models - there’s an interesting story behind these, and it’s about REST no less, so highly topical :-)

I also want to do a post on the next ‘big’ feature that’s going into DRYML - local definitions. The idea with these is that you’ll be able to write a page like this:

<page>
  <:sidecol>
    <section>...</section>
  </:sidecol>

  <:maincol>
    <section>...</section>
  </:maincol>
</page>

and have that <section> tag produce entirely different HTML in each case. This is key to getting themes to work properly, and in moving towards the Holy Grail of the view layer: total separation of logical markup from physical presentation.

Then there’s a couple of unfulfilled promises WRT making it easier for you guys to get involved: adding tests to the Hobo code-base, and having all the outstanding things to do properly tracked as trac tickets. I have not forgotten!

I’m sure there’s a million other pressing things to do too… :-)

What's Next?

Posted about 7 years back at The Hobo Blog

Let’s not go so far as to call this a road-map, but I thought I’d just let you know what’s coming up.

The manual needs completing, so I’ll be chipping away at that and posting updates as I go. The manual is only the start of the documentation of course. We still need proper API docs and a decent tutorial. I’d also really like to see some kind of “How To” style docs, with things like “How to add a password reset feature.” “Hobo Recipes” I guess. Those things will have to wait for a while though. For now I’ll be putting my energy into finishing the existing manual.

Then there’s a couple of articles I’m intending to write on new features:

  • Inner Tags
  • Composite Models - there’s an interesting story behind these, and it’s about REST no less, so highly topical :-)

I also want to do a post on the next ‘big’ feature that’s going into DRYML - local definitions. The idea with these is that you’ll be able to write a page like this:

<page>
  <:sidecol>
    <section>...</section>
  </:sidecol>

  <:maincol>
    <section>...</section>
  </:maincol>
</page>

and have that <section> tag produce entirely different HTML in each case. This is key to getting themes to work properly, and in moving towards the Holy Grail of the view layer: total separation of logical markup from physical presentation.

Then there’s a couple of unfulfilled promises WRT making it easier for you guys to get involved: adding tests to the Hobo code-base, and having all the outstanding things to do properly tracked as trac tickets. I have not forgotten!

I’m sure there’s a million other pressing things to do too… :-)

rb-appscript is cool

Posted about 7 years back at The Hobo Blog

After a small typo in the Hobo manual was reported in the forum (thanks!), I decided I’d like to automate the process of updating the manual.

I had two awkward bits that I was doing manually - conversion from Markdown to HTML, and conversion from Markdown to PDF.

“Eh?” I hear you cry? Manually converting Markdown to HTML? Have you never heard of BlueCloth? Well, I chose not to use BlueCloth because it, er, didn’t work. It choked on my markup, which looks fine to me, and converts just fine in Textmate. But today I somehow stumbled across Maruku which works great, and even has some nifty markdown extensions which I’m sure I’ll use.

One down, one to go - conversion to PDF. The trick here was that I really wanted a solution that allowed me to customise the style of the generated PDF. I really wanted to get to PDF via HTML+CSS. I thought I’d try and ask Safari to do the job for me via AppleScript. It worked!

Of course, I wouldn’t dream of trying to actually code AppleScript. If you’re on MacOS, go have a play with rb-appscript. It’s good stuff. The cool part is that because it’s all Ruby, you can fire it up in irb and make all your desktop apps jump around at your interactive command.

In order to get Safari to save a PDF at my slightest whim, there was one more trick required - I needed a “PDF File” printer (there’s no way to access the “save a pdf file” feature from AppleScript). I eventually found cups-pdf for Mac which works great. All my apps now see “PDF File” as a virtual printer.

Here’s the Ruby code that gets Safari to do the needful:

require 'rubygems'
require 'appscript'
safari = Appscript.app('Safari')
safari.open_location("file://#{Dir.getwd}/manual.html")
safari.documents[0].print(:with_properties => {:target_printer => "PDF File"})
safari.documents[0].close

That documents[0] looks a bit dodgy, but I couldn’t figure out how to say “the document I just loaded”.

So bring on your typos! I’ve so got it covered.