Search

Chaps

Sweet sweet memories

Blather

Uptime verified by Wormly.com

29 August 2008

Waiting cursor during Prototype’s Ajax.Request

In your stylesheet:

body.waiting {
  cursor: wait;
}

In your script:

document.body.addClassName('waiting');
new Ajax.Request(uri, {
  onComplete: function() {
    document.body.removeClassName('waiting');
  }
});

You probably want to be careful to make sure it's in the onComplete method and not the onSuccess method. Even better might be to create a setTimeout("document.body.removeClassName('waiting')", 3000), so you don't break the cursor for the rest of the page visit.

You also might prefer the "progress" instead of the "waiting" cursor. For other cursors and their compatibility check out QuirksMode.

12 August 2008

Apache 2, mod_passenger and HTTP Authentication

Using Lighttpd and FastCGI for Rails you can use Lighty's HTTP Authentication to "protect" an application. But the equivalent doesn't work with Apache 2. Putting the Apache authentication stuff in a <Directory> block will protect all the styles and scripts but no the application itself. You need to use a <Location> block for that.

<Location /*>
    AuthType Basic
    AuthName "Beta Testing"
    AuthUserFile /path/to/htpasswd
    Require valid-user
</Location>

5 August 2008

Magic quotes and addslashes

I think I may have found a slightly nicer (and safer) solution than I've previously found to the problem of the PHP's magic_quotes_gpc. When you're converting old applications you don't want to just replace all the addslashes() with a conditional escaping method. Or just unquote all your form input on the assumption that the programmer was sensible. Your input won't necessarily come from forms or cookies, so that might reduce your security. You still want to escape everything that goes into the function, but maybe you want run stripslashes() on it first if you think it's probably GPC data and magic quoting is turned on.

<?php
function gpc_escape($str) {
    if(1 == get_magic_quotes_gpc()) {
        return mysql_escape_string(stripslashes($str));
    }
    else {
        return mysql_escape_string($str);
    }
}
?>

Then you can do something like:

$ find . -name *.php | xargs perl -pi -e 's/addslashes/gpc_escape/g'

28 July 2008

No HTTP methods allowed with Rails 2

ActionController::MethodNotAllowed
Only get, head, post, put, and delete requests are allowed.

I started getting this funny little error this morning. It is a funny error in the humorous sense, but possibly you need to have used REST to think so. There were a few people getting this problem and finding a few different solutions, but my problem was I had a map.namespace in my routes.rb file. map.namespace appears to be deprecated/abandoned. So I tried using map.resource instead of the map.namespace. Technically I'm looking for a namespace and not a singleton resource, but it worked for me and namespaces and singular resources provide pretty similar functionality in this case. Although I'm still struggling to fix my tests so they they figure out what URL to use.

Update: Singleton resources seemed to cause problems with the :collection option, so now I've rolled my own namespaces with :path_prefix.

25 July 2008

Nested Scopes

I've just replaced a whole stack of nasty hand-coded SQL with nested scopes. There is a lot you can do with them that you aren't quite able to do with the standard associations. The main benefit is that you don't lose find_in_collection which all the examples seem to neglect. It's pretty rare that you want everything in a table. You mostly want to sort it and slice it, or search through it. So finder_sql isn't useful for very much. It doesn't provide any value that a standard method with some custom SQL search doesn't provide.

class User
    def public_topics(*options)
        Topic.with_user_scope(self) { Topic.with_public_scope { Topic.find(*options) }
    end
end

I was able to replace a nasty SQL subquery with this. And even swiftier, you can give it your normal ActiveRecord::Base.find options. It's probably not clear why I couldn't just use normal associations here, but I really couldn't. There was a topic_relationships table which connected users to topics very oddly, which is what created all the headaches.

So the moral of the story is, with_scope is the probably best option when normal associations won't cut it.

23 July 2008

Problems with ActionController::MethodNotAllowed

I started getting exceptions like this without really being sure why:

 ActionController::MethodNotAllowed 
 (Only get, put, and delete requests are allowed.)

I think the version of Rails was probably updated and it became less forgiving of our pitiful custom form builder.

One of the frustrating things about custom form builders is the Rails form helpers seems to move faster than it's practical to keep up with. So you end up with a whole lot of old-fashioned form builder code lying around that is either bigger than it needs to be or totally broken.

The new Rails RESTful routes stuff uses the "put" method to update existing records. Which I think is slightly silly, but someone is convinced we need to apply the HTTP CRUD metaphor to web forms. So we use hacks like <input type="hidden" name="_method" value="put" /> because forms don't support proper HTTP puts.

But anyway, that's the way things are and as everyone learns with Rails, resistance is futile or at least far more pain than it's worth.

But this particular problem I've fixed. The form action for updates should be /object/1234, which accepts GET, PUT, DELETE. I was getting MethodNotAllowed errors because my form builder wasn't adding the hidden _method field. Rails was treating the update as a normal POST to /object/1234 instead of a PUT. So I got the form builder to add in the hidden field for existing records, and everything was sweet.

Someone else had the same problem for a different reason.

Unknown column in field list in Rails 2 fixtures

This is a problem I've come across a few times and I keep forgetting why it happens. It occurs when there is an runtime error in the model (script errors fail more loudly). This is typically a NameError, such as a bad library name or method call. The new rails fixtures need to look at the model associations to work out their magic - the mapping between association names and association foreign keys. But if the model code is bad it silently fails and the fixtures code can't work out what to do.

You'll get something like this:

$ rake db:fixtures:load
rake aborted!
Mysql::Error: Unknown column 'holiday_type' in 'field list': INSERT INTO `holiday_periods` (`holiday_type`, ...) VALUES ('school_holidays', ...)

I'd assumed it was a problem with the fixtures or the migrations. But in this case the problem was in the HolidayType class. Which is certainly not clear from the error, but on reflection not really so surprising.

9 July 2008

Unobtrusive Javascript

I've been reading a little about UJS lately, trying to figure out a nice way of building some AJAX back into the Rails project I'm working on. I had a look at the UJS plugin and tried out the Low Pro. But I'm not sure I'm convinced. PPK suggests that Javascript is to behaviour as CSS is to styling, but I disagree. CSS tends to apply to many elements in a site. Javascript is more likely to be specific to a page. Most of the benefit of CSS comes from classes and being apply to apply the same style to many things at once. It makes sense to keep something like that separate.

The is the "wrong" way to do it:

<a href="/event/new" onlick="AJAX.Request(...);return false;">Create event</a>

And this is the "right" way:

<a href="/event/new" id="create_event_link">Create event</a>
<script type="text/javascript">
//<![CDATA[
Event.addBehaviour({ '#create_event_link': Remote.Link }); // attach event listener to link
//]]>
</script>

Which is pretty verbose, and to truly do it properly you're meant to put that second block in a separate file. In a Rails application, that's going to be somewhere in public/javascripts/ which feels very much like the wrong place to put this sort of logic. The second solution will also break if the link is created dynamically after the page has loaded.

An event delegation solution might solve this particular problem. You could catch all links with the class "remote" for instance, and treat them as AJAX links. But it wouldn't be very configurable. Configurability isn't a big issue for CSS, but I think is an issue for Javascript.

I certainly understand the appeal of UJS, but I don't think the parallel between styling and behaviours is convincing. And for trivial behaviours like this I don't think duplication of code is a serious problem, either for download size or for maintenability.

16 June 2008

Apache again

I've finally ditched lighttpd + fastcgi and replaced it with Apache on smurf. Lighttpd was good, but fastcgi was a total dog. It broke all the time and it got to the point that I didn't want to host my friends sites anymore. Every time I went on holidays fastcgi seemed to fall over and all the sites would be down for a day or three.

So I've gone back to the stable world of Apache, although not on the important server. In all the years I used Apache and mod_php it gave me no problems at all. A total rock. I was seduced by lighty's memory footprint, but I was a fool.

I'll move the other server over to Apache as well at some point, the one with Thoughtful Foods and KSAsub.. I thought rewriting all the configuration files was going to be a pain, but it was actually really quick. RewriteCondition with -f is bloody marvellous.

31 May 2008

Sort by two object attributes in Ruby

This is a potentially ugly to solve, but you can actually compare two arrays. So it isn't so bad. If the first attributes are the same, it sorts by the second.

def <=>(other)
  [self.dtstart, self.dtend] <=> [other.dtstart, other.dtend]
end

27 May 2008

European Dates in Ruby on Rails

I found a solution to the problem of month/day ordering by overriding the autocasting code in ActiveRecord. However, that didn't solve the problem more generally. So I came up with a nicer solution that uses the existing Date::Format._parse_sla_eu method. It replaces the US year/month/day parsing method with the European one.

# Overrides the default Date::_parse() method for dates of format dd/mm/yyyy
# ParseDate does the typical American thing and assumes mm/dd/yyy and
# doesn't seem to be configurable

module Date::Format::EuropeanDates
  def self.included(base)
    base.class_eval do
      class << self
        alias_method :_parse_sla_us, :_parse_sla_eu
      end
    end
  end
end

Date.send(:include, Date::Format::EuropeanDates)

With thanks to Simon who showed me how to replace static methods. This is the kind of wacky stuff you could never do with PHP. Not that we should want to. It's kind of ridiculous.

13 May 2008

Changing human attribute labels in Rails validation messages

I've been frustrated by the lack of humanity in Rails so-called human names. So I wrote a little library, which was largely stolen from Change displayed column name in Rails validation messages. The library lets you do something a little like this...

require 'human_attributes'

class Puppy < ActiveRecord::Base
  humanize_attributes :breakfast => "Puppy's preferred breakfast"
  validates_presence_of :breakfast
end

It doesn't do anything very spectacular, but it took me a long time to work out.

# lib/human_attributes.rb

module ActiveRecord
  class Base
    # Humanize attributes
    def self.human_attribute_name(attr)
      @humanized_attributes ||= {}
      @humanized_attributes[attr.to_sym] || attr.humanize
    end

    def self.humanize_attributes(*args)
      @humanized_attributes = *args
    end
  end
end

ActiveRecord::Base#humanattributename is deprecated and will be replaced by proper string inflection. For those with fancy, modern humanizing Inflectors you might have to change it to something like this.

def self.humanize_attributes(*args)
  humanized_attributes = *args
  Inflector.inflections do |inflect|
    humanized_attributes.each do |attr, label|
      inflect.human attr.to_s, label
    end
  end
end

Although I couldn't get that to work, probably because my Rails isn't new enough.

4 February 2008

Yahoo vs Google

A few days ago I started using Yahoo as my Firefox quick search instead of Google. I am happier with it and am going to keep it. I've never used Yahoo for search, even back when it was big. Now I reckon it is better though.

15 December 2007

Now the DB

Amazon SimpleDB seems to mostly complete Amazon's nifty little setup. True to their word, it is very simple. But also rather handy. It's billed by the exact amount of machine utilisation and data transfer and lets you work out how much each transaction costs. You can imagine web services which are free up to some usage threshold after which you start paying for what you use plus 10%.

29 August 2007

Is the CIA using Plone?

CIA using Plone?

How cool would that be? What Plone may lack in goodness, it more than makes up for with open-sourceness.

17 August 2007

Goodbye Movable Type

I was just thinking to myself how good life has been since we all left Movable Type behind. What an arse of a blog system that was. Obviously much better than something like, say Blogger, but still pretty damn awful. I'm not wanting to suggest that Wordpress isn't a bit crap, because it is, but boy do I love it.

16 August 2007

XCache with PHP5 and Lighttpd on Ubuntu Dapper

PHP is been pretty slow for me since I left Apache 2 and the PHP code caching behind. I tried turck mmcache with PHP4 and it worked pretty badly. It sped things up, but lighttpd started freezing up every few hours. It was probably FastCGI screwing up and it might have been fixed with FastCGI since then. But I'm all PHP5 now, so I needed to use something else. The Lighttpd guys suggested (and maybe created) XCache so I tried it. It only took a few minutes to install and it's working sweet. Wordpress page loads are down from 300ms to 50ms. I just hope it doesn't screw other things up.

I used the XCache installation instructions but had to do things a bit differently.

  1. Downloaded the XCache source from http://xcache.lighttpd.net/

    ~/src $ wget http://... (the release url)
    ~/src $ tar -zxf xcache-*.tar.gz
    ~/src $ cd xcache
    
  2. You have to install php5-dev and make if you haven't got them

    ~/src $ sudo apt-get install php5-dev make
    
  3. Run the PHP/XCache installation stuff

    ~/src/xcache $ phpize
    ~/src/xcache $ ./configure --enable-xcache
    ~/src/xcache $ make
    ~/src/xcache $ sudo make install
    
  4. Edit the php.ini file to tell it where the xcache.so file is located. Mine was at /usr/lib/php5/20051025/xcache.so. You need to edit the xcache.size setting (I used 32M, but others use 64M) and the extension (or zend_extension) setting.

    ~/src/xcache $ find /usr -name xcache.so
    ~/src/xcache $ sudo vi /etc/php5/php.ini
    
  5. Check that it's working

    ~/src/xcache $ php-cgi -v
    
  6. Restart lighttpd

    ~/src/xcache $ sudo /etc/init.d/lighttpd restart
    

7 August 2007

Internet improves on Facebook

Kottke thinks that the internet is the new Facebook, and that one day the internet will surpass Facebook in users and functionality. The idea is that if Facebook is about networking, then the internet at large will do a far better job.

It's a good idea, but I have to disagree. Facebook's value isn't the network. As Kottke points out, we already have a network called the internet. Anyone can write applications for it. Any of those applications can talk to most of the other applications. But Facebook has still added enormous "value" over what existed. The value of Facebook is in the possibilities it restricts and not in the possibilities it provides. Its value is in the consistency it can offer. My impression of people is that they prefer to use a consistent application that gives them what they expect, more than they want optimal solutions to their needs.

Facebook didn't build any new infrastructure or overcome some technical barrier. It doesn't do anything that wasn't entirely possible 10 years ago. It has just taken that long to get a system that people want to use. Who knows if Facebook will still be around in 5 years? Even if it isn't, right now it is probably the best designed and maintained application of its kind. People don't want optimal networks - they want networks they can understand. The hard bit isn't creating the underlying network as much as presenting in to people in a nice way. Facebook is certainly sub-optimal from an engineering perspective, but that doesn't seem to have mattered.

Disclaimer: I have a Facebook account, but think the whole thing is pretty silly.

28 July 2007

Slices

Since moving this blog to SliceHost the page load time has dropped from over a second to 100-200ms. Sweet. I don't even have the cache turned on anymore.

15 July 2007

Wikileaks Domains

I am now the proud owner of two Wikileaks domains and Wikileaks Australia, a non-profit organisation dedicated to truth and democracy and all that jazz. If I am ever spontaneously assassinated by the CIA you'll know why.

6 July 2007

Twitter

OK. Fine. Twitter is dumb but cute. I always thought it was narcissistic and stupid. But it's actually narcissistic and gratifying. Like much narcissism.

It's like a microblog. If you label your assumption that other people will care about your life a "twitter" instead of a blog post you don't feel like such a muppet.

4 July 2007

Social Networking

I have decided to get a Facebook, Twitter and Myspace account. I tend to abuse them without really knowing what they do.

So far Facebook is good. It is well-designed and easy to use. Whether or not it's actually useful for anything I'm not sure.

Twitter is just dumb. But I'll try and use it.

I haven't actually held down the bile long enough to get the Myspace account yet. But I will.

26 June 2007

Last.fm Events

Last.fm has a pretty posh events setup these days. It will look at the music you like and find music events that you might like. It does a pretty good job too. All three of the gigs I'm actually going to in the next couple of months are on the list. And three more of the gigs I'd really like to go to are there too.

10 June 2007

Adobe Flex [2]

In my considered opinion and have examining the Adobe website for a good 10 minutes, I declar that Adobe Flex 2 is crap. Just like most Flash, it's trying to solve a non-problem, and solving it poorly. The open-source XMLiness of it is nice, but that doesn't make the whole thing any more necessary. Of course, I reserve the right to decide that it's actually brilliant in the future.

Library Catalogues

What is it about library catalogues that means that always have to be a dog's breakfast? I've never seen a good one. Is it because they are so complicated and the poor tech staff at libraries have to hack them up so much to get them to work properly? How can Flickr, with 10 or so guys, be so brilliant and easy to use, while library catalogues which, combined, probably have thousands of programmers and designers working on them are so painful? Is it because there is, and can only ever be, one library catalogue software provider and so there's no competition? All the sites seem to be basically the same and as bad as each other.

I'm sure they're difficult things to build, but those guys have had a long time to get it right. And it's not like there's no money in it. There must be pretty sweet economies of scale in that business.

Has anyone ever used a good system?

9 June 2007

Wikileaks Domain Owner

I'm now the owner of a Wikileaks domain. Let's hope doing that wasn't a bad idea. In the spirit of being transparent, let's also hope that putting my real name on everything was not as dumb as it feels.

8 June 2007

Wikileaks

I've been on the Wikileaks mailing list for a few months now, and it looks like things are starting to speed up. It's trying to create an anonymous database of of leaked documents, that can be reviewed and evaluated by the public. I reckon it's a fantastic idea and wish there was more I could do to help them.

The criticisms of it have been that people will just release random lies and propaganda. Except that kind of misses the point. Anyway can publish a lie on their website. A lie only has as much credibility as the website publishing it. If Wikileaks is never able to be able to distinguish between lies and leaks, then it will never gain any credibility. The idea is that it should be the public and not bureaucrats who decide if something is worth releasing to the public. You should have to convince a lot of people that they don't need to know something before you can prevent them from knowing it. That's the rather ridiculous paradox of government secrecy, but I think that the burden of that paradox should be placed on those who want to keep secrets.

The only real difference Wikileaks makes is that it attempts to break the link between leaks and resulting punishment. Organisations shouldn't be able to feel confident that their secrets are safe because they can threaten their employees with prison or violence in the event of a leak. They need to convince their employees that those secrets really deserve to remain secrets. If the people who clearly need to know this information can't be trusted to agree that it should be kept secret then who decides?

The Wikileaks folk seem to have a lot more nous than I'd originally thought. At the beginning it was all a bit confused, and unclear if anything was happening at al. I recently sent them an email with a few suggestions about random things in response to an email they'd sent out. They replied with "Thanks. But we've already thought of all that." Which is always very encouraging.

The idea conjures up dreams of a Cryptonomicon type haven and I wonder how many of the Wikileaks guys have read that. I'm not convinced that real anonymity is ever truly possible on the internet. Especially since for the people who need it the whole network surrounding them is controlled by the people wanting to know who they are. I don't think the internet has added a lot to the amount of information shuffling around China for instance.

6 June 2007

What is Facebook?

I don't understand it. Why would anyone want to use it? It seems like MySpace except maybe it does less in exchange for being less ugly. I read their little Facebook tour. It says you can meet friends. And post photos. And put notes on a wall. I don't know why people would need Facebook to do that. I would happily ignore it except that people I used to respect are all talking about it.

14 May 2007

Vox

Vox is what MySpace should have been. It's the same idea, but good.

Update: Just realised it's built by Six Apart. So it will probably start to suck soon.

8 May 2007

Yahoo Pipes + last.fm

Yahoo Pipes does last.fm

Really and truly, Yahoo Pipes is pure bliss. After a long period of loyal service from my modified version of Tijs's last.fm plugin I have found a nicer solution. I was waiting for last.fm to turn its charts into Atom or something, but I suppose it's the wrong paradigm. So I used Yahoo Pipes to convert the random last.fm XML into a normal RSS feed. Now I can use my plain RSS feed printer to do it.

25 April 2007

New Atomic Blogfeed

Blogfeed is now Atom-enabled. SimplePie is approximately four billion times better than PEAR fricking XML Feed Parser. And after a brief romance, I've concluded that PHP date() is much, much better than PEAR Date. If only PEAR wasn't so neatly integrated and standardised I'd abandon it altogether.

If anyone is wondering what all this means, it is that Tom, Steve and Anmol can now all come to the Blogfeed party.

0.531 seconds