FCGI woes yield SCGI plugin

Posted by trevor Thu, 17 Nov 2005 05:01:00 GMT

FCGI hates me. It’s been hating me for quite a few days now. I finally took then hint, installed scgi_rails and everything works great.

Well, it’s not quite that simple. One issue I (and others, it would seem) had with Apache mod_scgi is that if you SCGIMount to ’/’ then you don’t get page caching – something that makes Typo hum along rather nicely.

A quick hack or two later and I have an easy-to-use plugin that makes page-caching possible with scgi.

The subversion repository for the plugin is here:

http://opensvn.csie.org/protocool/trunk/plugins/scgi_bin/

Everything you need to know is in the README file. If you’re going to use it with Typo you’ll need to pay special attention to the last section of the README file.

Update

I should point out that the page cache issue only seemed to affect me with Apache 2. Now I’m starting to wonder if there’s a bug in the Apache 2 mod_scgi.

Posted in code

Plugin Conventions Redux

Posted by trevor Mon, 31 Oct 2005 18:59:00 GMT

Last week Jamis responded to my post about plugin naming conventions.

If any of the rest of this post is going to make sense you’d better check out the above links first.

Anyhow, there’s been a bit more mailing-list to-ing and fro-ing about the fact that Jamis’ suggestion has problems, which I’ll write about today.

When is this an issue?

This is something that we should get out of the way here and now.

If your plugin is just mixing-in methods for a DSL (excellent link, by the way) like a new ActiveRecord ‘Acts’ – or you have some other situation where you only have have a couple of files to ‘require’, it’s a lot simpler and clearer to just require those files explicitly in your init.rb. For example:


plugins/enumerations_mixin/init.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/acts_enumerated.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/has_enumerated.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/virtual_enumerations.rb

My init.rb file will look like this:


require 'proto_cool/enumerations/acts_enumerated'
require 'proto_cool/enumerations/has_enumerated'
require 'proto_cool/enumerations/virtual_enumerations'
ActiveRecord::Base.class_eval do
  include ProtoCool::Enumerations::ActsEnumerated
  include ProtoCool::Enumerations::HasEnumerated
end

Complex Hierarchies

But what if your plugin has a lot of files to require? You may be tempted to organize your requires as Jamis suggested in his email. After all, it looks a lot like how rails organizes its own require calls. A stripped down example of a complex hierarchy might be:


lib/jamis
lib/jamis.rb
lib/jamis/buck
lib/jamis/buck.rb
lib/jamis/buck/my_module.rb
lib/jamis/buck/my_other_module.rb
lib/jamis.rb would contain: require 'jamis/buck'

and lib/jamis/buck.rb would contain:


require 'jamis/buck/my_module'
require 'jamis/buck/my_other_module'

The idea is that you could simply refer to Jamis::Buck::MyModule or Jamis::Buck::MyOtherModule without having to do any explicit require calls in the code that first references those modules. Rails will automagically “require 'jamis'” the first time you reference the Jamis module.

The problem with this approach is that once “require 'jamis'” has been called, all subsequent calls will have no effect, even if there are many jamis.rb files in the $LOAD_PATH. If Jamis releases another plugin that relies on automagic requires his full set of classes won’t be loaded.

Strategies

There are a number of strategies you can use to work around this. First of all, you can just use explicit requires in your init.rb file. You can still use Jamis’ method for everything in your module namespace that is unique to the current plugin though. Using the above example you’d just get rid of jamis.rb and in your init.rb file you’d have a single “require 'jamis/buck'”.

Another strategy would be to use load instead of require for all files that you (as a plugin author) know will appear in many places in the $LOAD_PATH. You could keep your jamis.rb file but in your init.rb you would simply say “load 'jamis.rb'”.

Pie in the Sky

There’s something slightly non-intuitive about the above strategies though. I had one of those “wouldn’t it be nice if…” moments and knocked together some code that allows this:

in lib/jamis.rb

module Jamis
  include Dependencies::AutoRequire
  auto_require 'buck'
end
in lib/jamis/buck.rb

module Jamis::Buck
  include Dependencies::AutoRequire
  auto_require 'my_module'
  auto_require 'my_other_module'
end
in init.rb

load 'jamis.rb'

There’s a couple of ‘nice’ features here. First of all, if you auto_require something, it will use the module name to construct the full require call. So “Jamis::Buck.auto_require 'my_module'” will result in a “require 'jamis/buck/my_module'” call.

Second, if you “auto_require 'buck'” and there is both a buck directory and a buck.rb file the require will be treated differently. The resulting require call guarantees your particular buck.rb file is loaded even if there is another buck.rb file in the $LOAD_PATH that has already had “require 'jamis/buck'” called against it.

You may be wondering why I didn’t just add the auto_require method to the Module class. I could have, but it makes me feel dirty.

The funny thing is, in order for this to be useful to me, I’ll either have to ship and… um… require a file that contains Dependencies::AutoRequire with each of my plugins – or I’ll have to convince the rails core team that Dependencies::AutoRequire would be beneficial to more than just me. Well, I think it’s funny…

Posted in code

Rails Plugins: Will somebody PLEASE think of the children?

Posted by trevor Wed, 26 Oct 2005 16:33:00 GMT

First of all, if plugins are new to you then you should definitely look at Jamis Buck’s guide to plugins before going any further.

Okay, so by now you know everything about plugins right?

So, I had one of those ‘uh-oh’ moments last night.

The Issue

I was worried that putting my acts_as_enumerated into ActiveRecord::Acts::Enumerated was a bad idea. I emailed Jamis and asked if plugin authors should avoid any rails module namespaces and he said:

That’s a really interesting question. I think I would answer “Yes”, but I’m not sure why. :)

It feels more natural to me if people follow a naming convention similar to how things are done in Javaland, where modules are namespaced by their vendor. So:

TrevorSquires::Acts::Enumerated

or something :)

He went on to point out that right now there are no guidelines or best practices.

Considering the number of plugins that have already been written it’s probably a good idea to start thinking about this now.

The Opinion

So here’s my opinion, presented in a way that I hope everyone from newbies (like me), to seasoned pros can understand. I’d appreciate feedback from others on this.

A plugin author has two namespaces to be concerned about:

  • $LOAD_PATH
  • Modules

The two namespaces kind-of overlap, but they don’t have to. I have a file called /lib/active_record/virtual_enumerations.rb that defines a ActiveRecord::VirtualEnumerations module and re-opens the ruby Module class. The name of the file doesn’t have to dictate its contents.

But the name of the file plays a role in being able to load your code in the first place – via the require keyword. If there are two plugins that have a /lib/chunky_bacon.rb file then require 'chunky_bacon' will load the first one found in $LOAD_PATH.

Now, as long as your init.rb does a require of all necessary files during initialization this won’t be an issue because during init your plugin’s /lib directory is the first one in $LOAD_PATH.

However, it may become an issue if you, or any other package that happens to require 'chunky_bacon', decide to defer require calls until a later time.

Even though for most people the $LOAD_PATH won’t be an issue, I believe plugin authors should be encouraged to use a directory structure, unique to themselves, within their /lib directory. Using someone else’s plugin for an example:


/lib/techno_weenie/acts_as_paranoid.rb

Not only does it solve potential $LOAD_PATH problems but it also serves as a reminder that you really ought to make your Module namespaces unique as well (as Jamis said above).

Comments?

Posted in code

Announcement: New Rails Plugin

Posted by trevor Tue, 25 Oct 2005 20:33:00 GMT

I’m pleased to announce the release of a new rails plugin for ActiveRecord, chock full o’goodness from:

  • acts_as_enumerated
  • has_enumerated
  • ActiveRecord::VirtualEnumerations

What is it?

As part of the work I’ve been doing at Site5.com (who have very graciously allowed me to release this code into the wild) I put together an extension to treat an ActiveRecord model as an enumeration. I.e.:


class BookingStatus < ActiveRecord::Base
  acts_as_enumerated, :order => 'position ASC'
end

booking.status = BookingStatus[:confirmed]

Values for acts_as_enumerated models are cached (reducing hits to the database) and you can define ‘virtual’ acts_as_enumeration classes, eliminating the need to clutter your models directory with classes that do nothing more than acts_as_enumerated.

The has_enumerated macro allows your models to refer to acts_as_enumerated instances without resorting to using belongs_to (which can require you to jump through hoops to avoid the database hit when retrieving the enumeration value).

I should point out that this isn’t the first time something like this has been done. Michael Shuerig sent a mail to the rails list a while back (when I was first looking at this feature) outlining how he was adding enumerations to his Boilerplate library.

Boilerplate’s enumerations differ from this plugin in some pretty significant ways but Michael’s technique of hooking into Module.const_missing was the missing piece of the puzzle I needed to eliminate clutter in the models directory – I’m very grateful for that.

How is it installed?

Well, the new rails ‘plugins’ feature makes packaging and releasing extensions a lot more straight forward.

First of all, you need to be running a plugin-compatible version of rails (0.14 and above). Then you simply:


cd vendor/plugins
svn export http://svn.protocool.com/rails/plugins/enumerations_mixin/trunk \
   enumerations_mixin

The README_ENUMERATIONS file should be enough to get you started – when I manage to scrape together some spare time I’ll insert some (hopefully) more helpful rdoc.

What’s missing?

Well, proper documentation, for a start. Apart from that it’s fully functional.

Enjoy!

Update

Years later and this plugin is now hosted on github

Posted in code

Site5 Teaser

Posted by trevor Tue, 25 Oct 2005 20:29:39 GMT

The day is nearly upon us. A little teaser perhaps?

Getting off the ground with Flock

Posted by trevor Fri, 21 Oct 2005 21:33:35 GMT

Apologies for the title.  Not funny, I know.

I just had to try out Flock to see what the fuss was about.  I guess my biggest complaint so far is that the interface looks like a web page so I expect it to behave like one.

Having to double-click certain page elements just doesn’t naturally occur to me.

And when I say “save as draft”, that’s kind of what I meant to happen.  Publishing this entry was never my intention so it’s a bit disappointing that you’re reading this don’t you think?

And be really careful when clicking ‘delete this post’.

Okay, it is beta, no arguments there.  It sure does feel like a beta.

Anyhow, thanks to Tom Wilcoxen for sharing his method for getting flock to talk to typo.

A Little Timesaver

Posted by trevor Sat, 17 Sep 2005 04:04:42 GMT

It seems to happen every single time I run ./script/generate model

I open the newly minted fixtures file and go “damn, what are the database columns again?” And of course, even if I could accurately remember them, why should I have to type them all in by hand?

Well, no more. ActiveRecord knows what the columns are so ActiveRecord can just darn-well tell me.


./script/runner "puts MyModel.new().to_yaml" \ 
   >> test/fixtures/my_model.yml

It gives me a lovely list of attributes to play with. Joy.

confess "stupidity" if self.plank?

Posted by trevor Thu, 15 Sep 2005 19:52:50 GMT

Here’s something learned – the hard way.

There is a reason you aliased rm to rm -i. Automatically adding -f to every damn call kind of defeats the purpose, doesn’t it?

What a great way to flush hours worth of work down the bloody drain.

The hidden social toll of Deer Gangs

Posted by trevor Mon, 22 Aug 2005 16:40:00 GMT

It seems that one of the local Deer Gangs was initiating a new member on Saturday night.

These initiations normally involve the young buck proving his bravery by trying to steal the manufacturer’s Marque from the front of a car.

Often the initiation passes without incident: it usually doesn’t take long for the buck to realize, in the eerie sodium-light of a car park at 2AM, that he doesn’t have opposable thumbs and he will never have his prize.

Of course, for the older Deer in the gang, this is the whole point of the initiation – the big joke.

On Saturday night however, an initiation took a tragic turn for the worse.

A local buck-initiate, as stupid as he was brave, decided to impress the rest of the gang by trying this stunt on my wife’s car.

It would have been a lot less messy if he would have waited for the car to come to a complete stop first.

Back on VI - Oh Happy Day

Posted by trevor Wed, 03 Aug 2005 18:00:05 GMT

I’ve been back home on Vancouver Island for less than a week now. I was in the UK visiting family and friends during July and I have to say that I’m really glad to be home now.

Why? Well, it’s the little things. Okay it’s also the big things like we don’t tend to worry about being blown up or anything. But more-so it’s the little things like how you’re treated when you go into a shop.

Good god the people in the UK service industry seem to loath their jobs.

Here on my little island people are doing the same, seemingly pointless, things to earn money. Manning the checkout, stocking shelves, answering the same questions over and over again on the telephone.

And yet, they generally do it with a smile on their face and with a touch of personality. They seem determined to take an otherwise mundane job and add something special to it.

It’s as though everybody on the island was given a copy of Finding Flow after graduating high school or something.

Older posts: 1 2