hack

Building and planting a raised bed from largely reused material

Hacks are still hacks even if they don't involve code, right?

One of the reasons I don't blog here very often is that I'm one of the team of contributors behind the Sustainable Witney blog. This local group, of which I'm a committee member, organizes and promotes local sustainability projects, and offers advice on how to live more sustainably. Some of that advice is in the form of blogposts, which I help write and edit.

Now that I've come to the end of a (very) short series of blogposts about hacking together your own raised bed from waste wood, discarded plastic and homegrown compost, I thought it would be worth sharing the gist of the series here.

1. Dismantling a pallet into reusable wood planks

There's a knack to it, basically. There are lots of online guides, some better than others. The better ones show how you can use a lump hammer and claw hammer to essentially use the pallet's joints against themselves, bending the nails so everything falls apart. The worse ones use blocks of concrete....

But despite what all of them suggest, you'll also need:

  • a crowbar and/or prybar (if you can work out the difference you're a better man than I)
  • lots of patience, so you don't start rushing and split the wood.

This is because very few of the online guides cover unusual or less-than-perfect pallets. Mine was both of a different construction, and also wet and slightly decaying in places. Read here how I dismantled it to obtain all this wood:

Around eighteen metres of wood from one pallet

2. How to build a raised bed from pallet wood

Again, there are lots of online guides. What you're aiming for, especially if you want plenty of height, is rigidity. So start off by assembling four "fence panels" with uprights sawn to size. Then put two together, bracing them so you get as square a corner as possible.

Making do with the wood you have to hand complicates matters enormously: variable length (saw it down); variable width (pick your planks for a given "panel", so widths even out overall); variable thickness (use bits of stray wood from other projects as shims.)

Still, you can read more detail here about how I turned the planks above into this raised bed frame:

A sturdy if not particularly pretty wooden frame. But it should weather well.

3. Turning a raised bed frame into a vegetable garden

This last phase is the most fun, because there's fewer limitations on it. We still wanted to reuse as much as we could, so we lined the bed with plastic sacks from a woodfuel delivery; and the soil in the bed completely emptied our 200-litre compost bin before we resorted to purchasing compost and sand to mix in.

Above the bed itself, I assembled a frame from bamboo and old tennis balls. This will support fine netting, if we get pest problems; in the mean time, we're using it to mount wire mesh to prevent a very specific pest - our cat - from doing any mischief to our vegetables.

Finally, we laid down some fleece a few days in advance, to help warm the soil; now we've put some seeds in place, we'll leave the fleece down as it's meant to get cold in the next few days.

This was how we finished off our raised bed, and shortly afterwards started growing food in it!

The finished raised bed, with fleece and bamboo frame in situ

Summary

I can't recommend doing this enough, especially if you've got a small garden (but even simply to augment an allotment.) The project in total would probably have taken two or three working days for one person, but the result means that planting new crops has since become a five-minute job, of which three minutes is getting tools out of the shed and opening seed packets.

If you're interested in doing it yourself (and I can heartily recommend giving it a try!) you can read all the posts in full, linked above. And if you've any questions, then you're welcome to comment here or just ask me on Twitter!

Blog category:

RobotsTxt, robots.txt and /robots.txt

The RobotsTxt module effectively requires a hack to Drupal core in order to function. This is because core Drupal contains a static robots.txt file, and webservers like Apache are configured by Drupal’s .htaccess file to serve static files preferentially to asking Drupal for the content. Every time Drupal is upgraded (or you deploy the site to a new staging or development instance), that hack has to be repeated.

One solution which Johan hit upon a while ago was to patch Drupal’s core .htaccess file, to send any request beginning /robots.txt to Drupal rather than serving any file on disk. It still constitutes a hack to core, but as a patch file accessible at a URL it can be incorporated into e.g. drush make files, and applied automatically when Drupal core is upgraded.

The patchfile-based hack is a big improvement, but it still leaves the RobotsTxt module complaining that there’s a problem. This is because it checks for the robots.txt file on disk, not for the /robots.txt URL, which is the real acid test for whether the module is working properly. So now we’ve also added this patch for robotstxt_requirements(), which checks the URL instead.

Blog category:

Removing checked-in client data from a git repository - permanently

During a recent migration, we checked in some client data to the sites/default git repository. This was a mistake: not least because the client’s data was some four or five times the size of the rest of the rest of the codebase; but also because there were non-ASCII characters in some of their filenames (“Pannetoné”, anyone?) These were playing havoc when they were on folders shared between a Linux Vagrant box and a Mac OSX host.

Removing files permanently from version control means removing them not just from the current revision, but also rewriting every revisions in the repository so they’re not there either (otherwise Git keeps them hanging around in its object repository, in case those old revisions are ever checked out again.) While there are lots of fragments of solutions online, very few of them encompassed the full complexity of our requirements: many branches, many tags, all needing to be preserved, along with trialling the changes by pushing them all to a temporary remote repository.

Our solution to this problem has ended up a little more long-winded than some, but it’s safer and works harder to preserve the integrity of the version history; when we work on behalf of clients, that’s our biggest priority. And applying this to a 27MB repository clone reduced its size to under 6MB!

Blog category:

Git repositories through a squid proxy

It's now a legal requirement to summarize such blogposts with "Aiee! The squid! She no longer responds to mind control!"

(This is a quick one, because I couldn't find the answer to today's problem on Google.)

Happy new year to you all! Already back working hard, with the snow and Christmas with my parents a dim and distant memory, I've been playing with drush make and squid proxies.

You can speed up lots of local drush-making with the http_proxy environment variable (which seems to be a general solution to proxying, as it's obeyed by both cURL and wget. Downloading lots of project zipfiles from drupal.org over and over again is much faster when you're secretly downloading from a local development machine.

However, there's a problem. If your makefile references a git repository on, say, github, then drush make will just fail when trying to create a local clone. Running the git clone instruction on its own yields a slightly cryptic error:

jp@jp-laptop:~/workflowing$ http_proxy=http://192.168.1.220/ git clone http://\
github.com/jpstacey/Drupal-ConfWizard.git /tmp/confwizard
 
Initialized empty Git repository in /tmp/confwizard/.git/
 
error: Failed connect to github.com:1080; Operation now in progress 
while accessing ...

You can also set GIT_CURL_VERBOSE=1 before your command, and see the connections timing out, but it doesn't help much. But that "1080" is the clue. It's the registered port for SOCKS servers.

What's happening is that PHP's internal HTTP libraries have defaulted to port 80, which our squid proxy is listening on, but git's cURL libraries assume that a HTTP proxy will be listening on the registered SOCKS port. The solution is to make the port unambiguous in the URL: http://192.168.1.220:80. When we did this, downloads worked just fine.

Blog category:

Drupal for NGOs - first ever meet yesterday

More people use Drupal in UK NGOs than you think. And than was planned for at the first, full-to-bursting Drupal for NGOs meet-up.

Yesterday Neal, Tom and I wandered to London, where Rob Purdie was hosting the first ever Drupal for NGOs meeting at Amnesty International’s UK headquarters. It was a hot, dry evening, and Neal’s attempts to Brompton it over from Marylebone left him dry-mouthed enough to avoid the copious snacks that Rob and others had laid on for us.

It was clear after the first half hour or so that there were going to be far more people there than Rob had expected: I think in the end there were around 50 to 60 attendees. A brief, slightly confusing “speed-dating” session later, I also realised that there was a real cross-section of Drupal fans there. There were freelance theme developers, module coders, hardcore sysadmins, CSSers, end users, tech writers, Drupal beginners…. A well-rounded audience, that hopefully stopped the meeting being too focussed on one layer of the CMS.

The talk from Tracy Frauzel at Greenpeace, about their experience with Drupal, was really enlightening, as was the phoned-in discussion from Joel Bassuk of Oxfam International (new site going live, 3–4 weeks’ time). It’s good to hear of people enjoying their transition from other systems to Drupal (even if the imports tend—like all data imports—to be occasionally painful).

It was also interesting to see how far people would tend to go with contributed modules, tweaking the theme and hammering away at the admin config, rather than building their own modules or (shudder) hacking core. Oxfam’s experience with forking Plone shows the perils of hacking core; to avoid doing that in Drupal, Greenpeace had used the usual locale hack to translate core strings to their liking (I say “usual”: I hadn’t seen it in the wild before, so again it was nice to hear a success story).

I really look forward to where Drupal for NGOs will go from here—maybe collaborative/accretive online conversations and resources, but most importantly the next event. This one was a really smooth first event, and it bodes well for future ones. From my experiences with the OGNs, I’ve learnt that organizing a fairly straightforward event can be incredibly stressful, and when it all works perfectly then nobody notices all the effort you’re making: that’s sort of the point of the effort, but it’s incredibly infuriating that people think you’re kicking back and feeling chilled! All the contributors, everyone who spoke or who volunteered some information, contributed to a great evening. Cheers, everyone.

Variable assignment in Django templates, sort of

Use and abuse of the "with" programmatic statement to make your Django template code less mad.

Django’s templating language is intentionally quite restrictive. The idea is that you have to do all your data munging in the control-ish sublayer of the view layer, in the method registered as handling the view in urls.py. In principle this simplifies templates, but in practice it can make life for the developer more difficult: you have to really think ahead, and assemble your variables properly, so that the templating language can use simple iterative loops to prepare your HTML.

What if you want the same output for several different data structures? Let’s say we have three people, and we’d like to run the following include, saved as name.html, on all three:

<p>{{ person.firstname }} {{ person.surname }}</p>

Ideally you’d have the three people in a structure called people, and be able to run:

{% for person in people %}{% include “name.html” %}{% endfor %}

But what if the order matters? What if you need account_director to do different things in the template from project_manager? You’d want to send them through as separate data structures, and this:

{% include “name.html” %}
{% include “name.html” %}
{% include “name.html” %}

would just do nothing, because it references person and not account_director. An alternative is to turn name.html into a custom tag, taking arguments; but if the content of name.html were any more HTML-heavy then you might want to abstract it into the include nonetheless, and then you’d just be running a custom tag method, to pass variables to a template fragment, to render the fragment, to pass it back up to the template. It’d be nicer if we could do this with core functionality instead.

Using the latest development version of Django, we can implement basic variable assignment—getting person to reference whatever we want in the template layer—using the with template tag. This means that we can wrap each include tag to produce the required output:

{% with account_director as person %}
  {% include “name.html” %}
{% endwith %}
{% with project_manager as person %}
  {% include “name.html” %}
{% endwith %}
{% with lead_developer as person %}
  {% include “name.html” %}
{% endwith %}

It seems like overkill for our name.html example, but there are plenty of situations—I just found one, hence this post—where it makes sense to factor out code into an include: being able to fiddle with the template context before including it is a lightweight alternative to template tags and a tidy alternative to dumping the HTML right there in the primary template.

Insert any Javascript bookmarklet

As the natural extension of Gareth Rushgrove’s bookmarklets for inserting the Dojo or YUI Javascript toolkits mentioned by Simon, here’s a tidying-up of a bookmarklet I’ve been using to bring in any Javascript using user input via a popup prompt:

Insert-JS bookmarklet

javascript:void(function(){
  var%20s=document.createElement("script");
  s.src=prompt("Full%20URL:");
  document.getElementsByTagName("head")[0].appendChild(s);
}())

I was originally appending it to the body as an invisible div, making use of d.innerHTML to add both src and type attributes so as to make sure the browser won’t ignore it. The above based on Gareth’s seems to work fine, though.

Blog category:

Subscribe to RSS - hack