Ignored By Dinosaurs 🦕

drupal

After reading the news about Fastcgi support landing in HHVM, I had to finally give it a try. I'll assume that you're at least familiar with HHVM and it's design goals, but if you aren't the HHVM wiki is a good place to start. In a nutshell, it's a new PHP runtime courtesy of Facebook that, if you can get it working, promises to run circles around any PHP interpreter currently on the market.

So I came into work on Wednesday fired up to give it a try. I wasn't expecting anything at all, since the sites I work with for my day job are pretty large and have a decent number of contrib modules installed. In case you're wondering, core Drupal is supposedly 100% on the HHVM now, but contrib is a different story.

The first thing you should know is that it only runs on 64-bit version of Ubuntu, so head over to Digital Ocean and fire one up. I prefer 12.04, so that's what I conducted this experiment on. The first link above gives instructions on how to install HHVM via apt, so that's the route I went. I first tried on the tiny little box that this site runs on, which is a 32-bit version of Ubuntu, and while the apt repo would update itself with the new HHVM repo, it wouldn't install. So, onto plan B, which involved a 1G box running a 64-bit version.

This one installed from the HHVM repo without a hitch — init script in /etc/init.d/ which pointed to some configs in /etc/hhvm. A quick perusal of that config script, which looked very much like an Nginx config, looked pretty straightforward. Installing Nginx and git and everything else I need to stand a site up was routine. Looking good. So sudo service hhvm start, and we're off to the races. top showed the hhvm process running as www-data so I hit the root URL. Page not found was the only feedback I got. curl -I gave me an x-something-something header that said HPHP, so I was puzzled. HipHop was listening on port 80 and was directly catching the web traffic, as opposed to standing behing Nginx and listening on port 9000.

It took me about 30 minutes of fiddling around, but the real clue was in the instructions for how to start HHVM on a system that doesn't have a repo installer.

cd /path/to/your/www/root
hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000

So, I took another look at the /etc/hhvm/server.hdf config file that the init script was pointing to and noticed that it was set to listen on port 80, not port 9000, and it was set inside of a Server {} block. That Server {} block that looked like the perfect place to put Type = fastcgi, so I did, and changed the port to 9000. The docs indicated that the process needs to be started from the root of your PHP app, but that might only apply to non-fastcgi HHVM. I started it from there anyway, and I finally had the thing working.

Standard “standing an existing Drupal site up on a new box” fiddling around with connections and file system settings and I actually got the thing to stand up after about 90 minutes of playing with it.

Thoughts

I'm a pretty good sysadmin for a front end developer, but I'm still just a front end developer. It was, however, very easy to find my way around the configs and start to get a sense of what HHVM does. I ended up upsizing the box to a 4G instance for a little bit after it started giving me some memory-related errors that I didn't have the skills to diagnose. I have no idea if that much RAM is needed, but it cost about $.20 to bump it up for a couple hours and find out.

The beautiful thing about it was that once I finally figured out how to stand it up correctly, my existing Nginx/FPM config (a derivative of Perusio's) worked out of the box with absolutely no other intervention. When I got stuck once by a cache clear that I suspect was the real cause of my memory issue, I shut HHMV down, brought FPM up and got unstuck. After I was stabilized again, I shut FPM back down and brought HHVM back up. It was seamless.

I finally gave up after a little bit because although it was working, the HHVM logs were full of notices, and I repeatedly hit a wall with some function, first in the gd lib and then in apachesolr, that didn't like the input it was being fed. I had to get back to “real work”, but I will dive back in very soon and hopefully be able to contribute some feedback. The maintainers are extremely friendly and active on IRC.

I'm very, very excited for the future of this project and would highly recommend giving it a try. I was amazed that I was able to get anything to load on it at all, and am salivating at the thought of actually getting the VM warmed up with a bunch of repeated requests. When it is ready for prime time across a wide variety of PHP apps, it's going to change the way people think about interpreted languages in general, and is going to single handedly contribute to a faster web. For this, we thank you Facebook.

#drupal #devops

Hi there, probably-front-end-dev-who's-met-and-used-Sass-and-likes-what-they-see. This is for you.

RubyGems

Sass is made out of Ruby – it's a very pleasant, general purpose programming language that's pretty easy to learn and like. Ruby has a package management system whereby libraries of Ruby code are bundled up into what's known as “Gems”. Sass is a gem. When you install it, you get a couple of new executables to play with in the terminal, namely sass and sass-convert. The latter of these will help get you started with Sass by converting your straight CSS to Sass. RubyGems inspired PHP's new-but-already-dominant package manager, Composer.

rbenv

If you are a Mac user, and you are using the version of Ruby that came with your Mac, you are using a version of Ruby that's actually beyond End Of Life. If all you're ever interested in is Sass, it'll keep working for a while longer but eventually you'll be left behind. A relic. This is the bad news. The good news is that the Ruby community has been working on this problem for a while.

[!info] Because Ruby 1.9 came out a while back and has a bunch of cool new stuff in the form of performance enhancements, syntactic polish, and overall love via it's contributors, and because 1.8 is in life's endzone, and because using outdated versions of open source software just isn't your preferred thing, you'll want to use 1.9. This is how.

The most commonly blogged about solution to this in the Ruby world is RVM. We're not going to talk about that. We're going to talk about a solution called rbenv. Rbenv is a more recent and lightweight solution to this multiple Ruby versions problem that doesn't require sudo to install and update Gems, and allows you to install almost any version of Ruby you desire (of which there are plenty, but that's more than you need to know right now).

Rbenv works on any *nix based system and installation is super simple

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

This installs rbenv, the version manager. Add rbenv to your $PATH -

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

(Zsh users put those two lines in ~/.zshrc).

You might as well go all the way and install the Ruby version installer, a separate tool – ruby-build.

git clone https://github.com/sstephenson/ruby-build.git \ ~/.rbenv/plugins/ruby-build

At this point, you'll reload your shell – exec $SHELL – and you're ready to rumble. Ruby 2.0.0 was released earlier this year, so unless you really like living on the edge, 1.9.3 is a safe bet.

rbenv install 1.9.3-p448 – (the most recent release as of this time, refer to changelog).

I almost forgot to mention rbenv rehash – probably the rbenv command you'll use the most. “rehash” basically tells rbenv to reload itself after you gem install any new gem that comes with an executable (like Sass). If you install a new gem and for some reason your computer acts like it has no idea, it's almost certainly this.

Incidentally, both of these tools were written by the same guy – Sam Stephenson. He works at 37 Signals, the home of Basecamp, the original Ruby on Rails app, created by a mystical figure known simply by his initials.

Matz/DHH

Super quick Ruby history lesson...


Ruby recently celebrated it's 20th birthday which, without doing any consultation of Wikipedia, makes it roughly the same age as PHP. Ruby's creator and spiritual leader is a guy named Yukihiro Matsumoto, or Matz for short. PHP obviously grabbed it's share of the market more quickly, and Ruby had scarcely gotten off of the island of Japan for about the first half of that until it was catapulted onto the world stage by one man – DHH.

DHH is a charismatic developer from northern Europe with a fondness for business and hair gel. DHH cast off his PHP chains when he found Ruby, created an honest to god framework out of it, open sourced it, and then ran with it. Much of Rails' rise to prominence coincided with the rise of Github and the two together are probably largely responsible for touching off Git's adoption in the greater marketplace.

Rails has impacted the design of almost every single web framework that has come since in any language, either directly borrowing from it's ideas or reacting to it's opinions. Sass came in it's wake, and here we are.

The Well Grounded Rubyist

If I can recommend one Ruby book to get, it's The Well Grounded Rubyist by David Black.

Black is one of the few western developers who has been doing Ruby since before Rails came along, and is a preeminent authority on the language. This book was my introduction to Ruby's version of OOP, which is indescribably more elegant, consistent, and to-the-point than PHP's, and reads almost like a great novel in the way that it builds in intensity from beginning to end and rewards repeated readings. No, I'm not shitting you.

#drupal #ruby #devops

Whenever a new developer shows up in some online thread asking for advice on how to learn to code, the replies always include “find an open source project to help with”. The 5th birthday of the Macintosh that I bought to learn to code is any day now, and I've just now worked up the chops and the courage to follow that advice. Here's what I'd say to a younger me.

When people say that, it's usually really intimidating to think about. What project? How do I get involved? What if I suck and get laughed off the internet? Well..

Pick a big one. Pick Drupal. Drupal is a huge, beautiful mess of an open source project and Drupal developers are highly in demand right now. This means that there is lots to work on, and when you've got something to show you can get paid decently well to do it. The advice is always to “scratch your own itch”, and indeed that's what pretty much every developer in open source is doing. I just had my first patch applied to a project. It took me about 3 weeks from start to finish, but the majority of that wasn't actually writing code. It was learning about what the other code did that I was trying to patch so that I could write a feature that actually followed Drupal conventions. This was a very simple little feature, but what I learned between 3 weeks ago and now ties into a LOT of core Drupal principles that have totally enabled me to write this other module that I need for work and have it work as intended on the first try.

So, in summary – help out on an open source project. It'll make you a better developer faster than anything else.

#drupal #opensource

At my gig we host our sites on Acquia's dev cloud. The dev environment is pretty locked down, obviously, since you don't want multiple, publicly accessible copies of your sites floating around out there, especially when it could be in any state of brokenness at any given time. So the way we do it is to use .dev domains that aren't publicly routable via DNS. We have a big ole master hosts entry in the local network that takes any of those dev domains and routes them to the proper IP.

Today however, I go out and my car won't start. This means I'm working from home, and that I need to add these host entries on my local machine myself since I'm not on the company network. As I type this I realize I could VPN, but that's no fun and I'm already done with this method that I'm about to explain.

So, I go to Acquia's cloud panel thingy. They have a “servers” menu item, but it only gives you the names of your servers, not IP addresses. Oh, we also have a load balancer sitting in front of everything that I can't log in to to get the IP that way (via ifconfig, presumably). So, they do give you this really vague

The following tables show all of the servers and the services(s) they provide for each of your site's environments. Each server's full DNS name is server.prod.hosting.acquia.com.

So anyway, the answer is the dig command – more or less a DNS swiss army knife.

dig server.prod.hosting.acquia.com spits back a wealth of info at you, including the IP address of your load balancer, which you can then put into an entry in your /etc/hosts file.

Love this stuff...

#drupal #devops

WARNING! D6 code ahead!!

As improved as D7 is, they don't seem to have caught on to this one, so maybe this will help those of you as well.


The internet is surprisingly scarce on information about this topic. Maybe most people don't need to alter the password retrieval process, but I've got a client with a variety of different roles on their site. These different roles have different profiles via the Content Profile module. On account of numerous other account/profile management related modules that I've added – LoginToboggan, Auto Assign role, Invite – the whole process as well as the standard Drupal callbacks have gotten a little muddled.

By muddled I mean broken. For instance, the standard user/%uid%/edit page is broken to hell. I don't know why really except that there's some competing permissions/access thing that I just can't, for the life of me, find. Unfortunately this is the page that the stock Drupal password reset process brings you to to reset your password after logging in.

“No sweat!”, you might say. “Just call hook_password_reset() and be on your merry way!”

“I'd love to!”, I'd say in reply. “But there is no hook_password_reset()!”

After much digging I finally found a clue to look in the user.module in a file called user.pages.inc. Herein lies the function that handles this very process – user_pass_reset(). Reading through this function is pretty cool. It's very readable, but also feels kind of bloated and hackish in a way that makes me feel a little better about how shitty a programmer I actually am.

Down around line 111 is where the magic happens. Now, if you're reading this, you've probably tried everything I tried. I tried setting #redirect on the form, which doesn't work because Drupal will ignore #redirect on the form if #action is set. I tried unsetting #action on the form, which breaks the whole thing because Drupal relies on that very unique URL being submitted to validate the password reset. All that logic can be viewed in user_pass_reset, so there's no monkeying with that. All you want to do is change that stinking URL inside that drupal_goto() and the end of that function! Has noone encountered this use case before?!?

So I did what any desperate soul would do. I hacked core. I didn't respect myself afterward, but at least the process worked like my client needed it to.

Step away, do some thinking. The comment at the top of the function says “menu callback for”...

Enter hook_menu_alter().

So obviously, the solution requires a custom module. In the absence of a hook_password_reset(), you have to move a little deeper down the chain. hook_menu_alter() is the backdoor into the club of elation that is having this project behind you. hook_menu_alter() lets you grab and alter any menu item in the whole process. Looking a little higher in the call chain on the User.module I take a peek inside user_menu().

$items['user/reset/%/%/%'] = array(
	'title' => 'Reset password', 
	'page callback' => 'drupal_get_form', 
	'page arguments' => array('user_pass_reset', 2, 3, 4), 
	'access callback' => TRUE, 
	'type' => MENU_CALLBACK, 
	'file' => 'user.pages.inc',
);

So let's copy that user_pass_reset() into our module (the sweet_module in this case) and rename it sweet_module_user_pass_reset(). Then let's define my_menu_alter() to be something like this -

function sweet_module_menu_alter(&$items) {
	$items['user/reset/%/%/%'] = array(
	'title' => 'Reset password',
	'page callback' => 'drupal_get_form',
	'page arguments' => array('sweet_module_user_pass_reset', 2, 3, 4),
	'access callback' => TRUE,
	'type' => MENU_CALLBACK,
}

Note the new function name for the callback, and the removal of the 'file' bit at the end. Flush your menu cache and you should now be hooking into that damn function finally.

What you do now is totally up to you, but you can hack away at the entire function until it behaves properly. In my case it was sending this type of user this way and that type of user that way. And nobody to the stock drupal user edit path. And you didn't hack core, and you can keep upgrading your site like you always did with the flick of a drush command without ever having to worry.

You're welcome.

#drupal

So here I go again.

I've written at length on this blog over the years about Drupal. It's a great tool for getting things done right now. It's seen a huge uptake over the last couple years among government agencies and educational institutions, so being versed in Drupal development is a good career bet at the moment, meaning over the next couple years.

In the longer term though, I see it as pretty shaky and here's why.

Drupal's raison d'etre is that non-technical users (meaning – people who aren't programmers) can build fairly complex sites without writing a lick of code. It has seen massive growth, mainly because the fact that websites are actually computer applications with which users interact is a fact that is really just dawning on the majority of people who use the internet and/or need a website for their business. Most people don't have CS degrees, but every business needs a website. Thus, they either turn to someone who knows how to build websites, or they hook up with GoDaddy and do a one-click install of Wordpress.

However...

I think the world at large is rapidly getting used to the idea of writing code, and the proportion of people out there who are at least somewhat comfortable enough with that idea to hack together their idea is growing. And their idea might not be a good candidate for a Drupal site. The other thing about Drupal is that whatever your idea is, you can probably get pretty close without writing code, but chances are high that it's not going to be exactly what you want without writing some code (or hiring someone to write some code). And at that point, you either settle for something that isn't what you want or you teach yourself to write some code. And after you get comfortable with writing code, you start to wonder why you are dealing with all of this Drupal overhead that you didn't ask for in the first place. And some time after that you might find a language like Ruby, that makes infinite more sense to me than PHP, and looks a hell of a lot prettier to boot. And soon after that you might find it hard to get excited about Drupal work, because overriding other people's code is way less fun than writing your own to begin with, and that's the vast majority of working with Drupal code, at least form the backend.

#drupal

This is the list I've spent a half hour hacking around in TextMate trying to figure out how to not manually build. Couldn't quite do it, so here it is, that you may find it and use it when building a Drupal form that has a select list of all 50 states and the District of Columbia.

'#options' => array(
 '' => t('Please Select'),
 'AL' => t('Alabama'),
 'AK' => t('Alaska'),
 'AZ' => t('Arizona'),
 'AR' => t('Arkansas'),
 'CA' => t('California'),
 'CO' => t('Colorado'),
 'CT' => t('Connecticut'),
 'DE' => t('Delaware'),
 'DC' => t('District of Columbia'),
 'FL' => t('Florida'),
 'GA' => t('Georgia'),
 'HI' => t('Hawaii'),
 'ID' => t('Idaho'),
 'IL' => t('Illinois'),
 'IN' => t('Indiana'),
 'IA' => t('Iowa'),
 'KS' => t('Kansas'),
 'KY' => t('Kentucky'),
 'LA' => t('Louisiana'),
 'ME' => t('Maine'),
 'MD' => t('Maryland'),
 'MA' => t('Massachusetts'),
 'MI' => t('Michigan'),
 'MN' => t('Minnesota'),
 'MS' => t('Mississippi'),
 'MO' => t('Missouri'),
 'MY' => t('Montana'),
 'NE' => t('Nebraska'),
 'NV' => t('Nevada'),
 'NH' => t('New Hampshire'),
 'NJ' => t('New Jersey'),
 'NM' => t('New Mexico'),
 'NY' => t('New York'),
 'NC' => t('North Carolina'),
 'ND' => t('North Dakota'),
 'OH' => t('Ohio'),
 'OK' => t('Oklahoma'),
 'OR' => t('Oregon'),
 'PA' => t('Pennsylvania'),
 'RI' => t('Rhode Island'),
 'SC' => t('South Carolina'),
 'SD' => t('South Dakota'),
 'TN' => t('Tennessee'),
 'TX' => t('Texas'),
 'UT' => t('Utah'),
 'VT' => t('Vermont'),
 'VA' => t('Virginia'),
 'WA' => t('Washington'),
 'WV' => t('West Virginia'),
 'WI' => t('Wisconsin'),
 'WY' => t('Wyoming'),
),

#drupal

I've recently begun a new contract for a rather large Drupal site. I was very excited to land this contract as it shall be my first bona fide “enterprise” contract and there's already a large amount of content on the site despite the company being rather young. There are a lot of forms on this site with leads being transferred to a backend system that I'll probably never have anything to do with. Anyway, I was excited to get a look in the back end of the Drupal portion of the site to see what the previous developers had been cooking up.

Imagine my intense surprise when it quickly became apparent that the previous developers weren't very learned in the Drupal way. Specifically, they committed some major Drupal rookie sins that a novice Drupal developer must know about.

  1. Modules don't belong in the modules directory. Themes don't belong in the themes directory.

There are many aspects of Drupal that are, politely speaking, counterintuitive to the new developer. Drupal by itself doesn't actually do a whole lot. The concept of the “lean core” means that the basic Drupal functionality is expected to be augmented to by community contributed modules. You'd be hard pressed to find a Drupal site out in the wild without at least half of those front page modules installed. I learned this on my second or third week of working with Drupal – the modules directory is reserved for Drupal core modules. All community or “contrib” modules go into a directory that doesn't even exists with a stock Drupal install – sites/all/modules. The same goes with themes – sites/all/themes.

When Drupal runs through it's “bootstrapping” process (a fancy name for when a request from someone's browser hits anywhere on a Drupal site), it looks in a number of different places to find code that may extend it's functionality or alter it's output to a request. Obviously, the modules directory is one of those places, that's why Drupal will run if you put contrib modules there. However, a big part of maintaining a Drupal site involves keeping on top of updates to those modules, not to mention updates to the Drupal core itself. Since the majority of Drupal lives in those modules, when Drupal core receives an update it becomes a much more muddlesome process to separate which files belong in which folder if they're all mixed together. More advance development tools like Drush make updating sites a total breeze, but not if the site structure is laid out wrong.

2. Use an admin theme.

Garland is a lovely theme (cough), but luckily the ecosystem has led to the evolution of some really useful admin themes that have big forms, big buttons and an intuitive layout by default. My personal favorite is Rubik, which requires also downloading Tao to function.

3. Speaking of updates, stay on top of them.

Part of the wonder of open source software is the knowledge that all over the world, thousands of developers with vastly differing skill sets and experiences are working together on one project. Such a model ensures that many sets of eyes are on the lookout for security holes (“exploits”) and that many hands are at work moving the project and it's features forward. The flipside to this rapid development pace is that updates to the software are released whenever they are ready, and this is often quite frequently on larger projects. It's a rare week when I don't have any sites that have some sort of update released on at least one module. Drupal maintenance is all about keeping on top of the Status Reports page – found under admin/reports/status and admin/reports/updates.

#drupal

Reasons for leaving Drupal, a preamble

I'd had this website on Drupal since some time in July. If you look through the archives, you'll notice a relative dearth of posts from this time period. Drupal just has a way of sucking all the fun out of blogging. It's very, very slow for one thing. I had a lot of trouble integrating the site with the Disqus comment system that handled all of my Wordpress comments before I made the move so I was forced to use Drupal's comment system. I'd written a couple of posts in the “didn't find much in Google about it, so I decided to become the authoritative voice on it” vein, and had a ton of comments on one of them. Those comments appear to be gone now, even though I devoted an entire day to exporting them out of Drupal into Disqus with a solution that someone came up with.

Basically, Drupal is a beast. If you have a project that you are trying to build that involves users with accounts, and different levels of access to the content based on those roles, go with Drupal. For anything else, anything simpler, stay away. Drupal gives the impression of being somehow more user friendly since you can configure these massively complex sites without actually coding much of anything, but is that really a good thing?? Drupal's inherent dependence on stashing so much configuration in the database will be the death of the project if it's not figured out, and I personally don't think anything short of a MAJOR rewrite is going to sort it out. The major Drupal rewrite that's about to drop on the world some time has taken 2 years to get even close to the door, and a rewrite that would effectively fix this particular issue would also effectively rewrite the entire philosophy of being able to build a site in the browser, arguably the whole reason for Drupal existence in the first place.

I haven't even gotten to the part about moving Drupal to Git. Why not put the whole thing up in GitHub? Have you heard of Rails? It's doing pretty well, and I'd wager that a large part of the reason for that is how easy it is to dive in and contribute to open source on GitHub. I've never once seen it even mentioned to move Drupal to GitHub.

anyway...

Reasons for migrating to Jekyll, regular ramble

First off, it really wasn't that hard, so skip ahead if you wish. I spent a good several hours on Github researching other sites that people had going on the platform out there. I've been studying a whole lot of Ruby lately, so it was down to Jekyll or a few other simple solutions. I started building a solution out of Sinatra, but decided that deployment was probably going to be more of a headache than I felt like dealing with.

I loved the idea of a static HTML site since one of my main gripes about Drupal was how many times I could count the little page load indicator going around on Chrome. This site is blazing fast now, so yay for that.

I love the idea that there are no security updates, no databases to backup, no crufty markup that comes from where exactly? Basically, there's very little tradeoff. It's mostly win. So, on to the show.

##Migrating from Drupal to Jekyll, the meat

One of the things that I didn't understand about Jekyll was that it doesn't really generate a site template for you (you get used to that when dealing with Ruby). You have to build that part or Jekyll won't do anything at all. It's easy enough to get started though, just Google or borrow from other GitHubbers. The tricky part was liberating my posts from Drupal, which was made vastly easier by this fellow having written a Drupal migrator only a few weeks ago.

I followed all of the instructions on this page for getting the migrators to work, but kept getting an error message that ruby couldn't find the specified file or something like that. So an hour or two of fiddling around with the migrator file in my Jekyll directory and finally changing the command to something like this -

ruby -r '~/PLAY/jekyll/_import/drupal' -e 'Jekyll::Drupal.process( "#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")'

where ~/PLAY/jekyll is the root of my jekyll install in order to get ruby to read the migrator file that was there instead of trying to find one that wasn't. I'm sure the instructions will work fine for someone who knows more than me, but hey it worked.

edit: it now occurs to me that if I wanted this to really work the correct way, I should've forked Matt Dipasquale's version of Jekyll and built my site that way, but I'm not sure how that plays with the RubyGem system and in any event I made it work. YMMV.

to give back unto the community...

TODO – add a bit into the Drupal migrator that also liberates the URL aliases from the DB, as the author of the current migrator apparently used the stock Drupal URL scheme (node/*). Jekyll has an easy facility for setting the permalinks for your posts, but going through every post to make sure they were right was needlessly tedious in hindsight.

#drupal #ruby