New Blog

Posted by James Brooks Mon, 26 May 2008 21:57:00 GMT

I've got a new blog, at a different URL (I'll remove this URL shortly and have it redirect to the new site). For now, head on over to JamesBrooks.net (or .name / .info) for maximum awesome*.

Disclaimer: * Maximum Awesome implies that I don't yet have an implemented post commenting system, hell, posts are pretty much the only things going (apart from the awesome tagging). You can't subscribe to _just_ posts yet, but that'll be coming very soon with the inclusion of 'super tags' (pending better name) ;)

Intermittent PHP Sessions on Zeus Web Servers

Posted by James Brooks Tue, 08 Apr 2008 03:38:00 GMT

This morning I've been trying to work out some intermittent issues with a fairly small PHP application I was trying to deploy to a particular client's hosting (They're with NetRegistry). After a bit of tinkering and enabling some session and cookie debugs I discovered that information in the session seemed to vanish every second page load (wtf! this does not happen on my development machine).

I may be jumping to incorrect conclusion simply saying that Zeus Web Servers (or more likely, NetRegistry's configuration of them) are to blame. What I will do is outline my solution to this problem. Just use sessions in file store mode.

ini_set('session.save_handler', 'files');
session_save_path('/var/www/application/sessions');

Just set the location of the sessions to be outside of htdocs (or where-ever you have your web servers accessable root to be).

Our new place

Posted by James Brooks Wed, 19 Mar 2008 00:31:00 GMT

Liz and I have just got a new place, it's awesome. I've attached a map of where it is below (I'd put up some pictures as well but the online listing isn't available anymore and I don't have pictures). I'll add some soon when we're in :)


View Larger Map

Web Perfect PNGs, Embedded Colour Profiles and Pain

Posted by James Brooks Fri, 14 Mar 2008 01:32:00 GMT

While doing a lot of visual design implementation for a page I take a Photoshop file (PSD), break up the components, separate parts which are perfect for CSS and those which I'll have to keep as images. A lot of these design will incorporate images with alpha-transparencies forcing me to use a 24bit PNG (I'd be using PNGs anyway unless I need animation for something like a spinner).

Exporting PNGs from Photoshop can lead to adverse affects in terms of embedded colour information (depending on the working colour profile and the colour profile of the Photoshop file you're working with). This embedded colour information can cause the colour of PNGs to render differently to colours coming from stylesheets (I've struggled with these issues before).

Step in a utility like PNGOUT, which not only 'compresses' the size of PNGs, 'lossless compression' for most of it.. or so I thought. Earlier I discovered that in IE a few transparent PNGs weren't looking too fantastic. Interestingly enough when I opened the PNGs up in Photoshop they looked even worse, so what had happened.

After a bit of tinkering around I found that these images had a low amount of colours and in a attempt to compress these PNGs futher, PNGOUT had dropped the number of colours down (making the image no longer a 24bit PNG). Which resulted in some strange rendering issues in IE, Photoshop and who knows what else (Firefox and Safari seemed fine, but it was most concerning that they looked bad in Photoshop).

The New Solution: Don't let PNGOUT reduce the number of colours! How? Tell it the output colour type as follows:

pngout -c6 image.png

Sidenote: Another little issue I personally had with PNGOUT was that it didn't overwrite the original PNG if the resulting PNG was going to be larger (which is fair enough). In these cases I wouldn't have the colour profile stripped, so I decided to live with slightly larger PNGs (and had to force PNGOUT to produce these), as follows:

pngout -c6 -force image.png

Now I'm back to generating Web Perfect PNGs :)

How to check if a table exists in MySQL

Posted by James Brooks Thu, 21 Feb 2008 00:02:00 GMT

I've been google'ing around for a MySQL solution to check if a given table exists in a database (using PHP for example sakes). Solutions I've found so far seem too long and involve performing a show tables query and interating over the resulting rows to check if the table exists (this is a clean and sure way to do it, it just takes too long!).

A one liner I put together after reading a few posts looks a little something like this:

  function has_table($name) {
    return mysql_query("SELECT * FROM $name LIMIT 0") ? true : false;
  }

This query runs very very quick (and I can write it in one line of code). If anyone knows of a more elegant way of doing this, please drop me a comment :P

Rails' has_many with models over different databases 2

Posted by James Brooks Tue, 29 Jan 2008 23:35:00 GMT

In a current project there has been a need to access data off of an external database, so we've got our local read/write database running the application and a remote read-only database which we need to retrieve information for.

Let's say the example setup looks like this:

# users table is on our primary database server
class User < ActiveRecord::Base
  # messages are on the external database server
  has_many :messages
end

I quickly encountered problems using Rails' has_many over the database boundary using an establish_connection call in the Message model. I tried fiddling around with writing a custom AssociationProxy (a, has_many_remotely if you will) to handle this case as establish_connection didn't seem to be doing the trick.

Well, it turns out that Rails handles this border case quite well (never under-estimate Rails!) and I didn't have it set up quite right, so here's how I've got it set up now with great success:

User.rb
class User < ActiveRecord::Base
  has_many :messages
end
Message.rb
class Message < RemoteModel
  belongs_to :user
end
RemoteModel.rb
class RemoteModel < ActiveRecord::Base
  self.abstract_class = true  # This isn't a model itself
  self.establish_connection :remotedb  # The remote database connection
end
database.yml
remotedb:
  adapter: mysql
  username: username
  password: password
  database: database
  host: mysql.awesomeness.net

That seems to be it, I can now use the messages proxy on a user instance quite successfully!

First impressions of the facebooker plugin for rails

Posted by James Brooks Sun, 27 Jan 2008 13:55:00 GMT

I've recently decided to go ahead and finally write that Facebook application that I've always planned to write (which has had two-half-but-not-complete copies written previously, I'd like to think of it as incremental development).

I decided to have a look at facebooker, a plugin for Ruby on Rails which is a wrapper over Facebook's REST API. After following the simple instructions on the project page I came to a halt, there wasn't any documentation of where to go from there (there was an example provided, but it doesn't directly related to a Rails application). The 'Rails example' provided also appears to be a freshly generated Rails application with no content.. wtf! Tip: check facebook_session / @facebook_seesion

After that initial problem of not knowing where the plugin assigned params sent in through facebook, it was pretty much writing a normal Rails application (as it should be!).

One little problem I've come across so far is with Routing. Facebooker provides a facebook_resources to generate named routes whose conditions are all :method -> :post (as per facebook requirements). This broke instantly when trying to wrap it inside an with_options or namespace block.

The solution was pretty easy, if you've got time head on over to the tracker and verify my fix ;)

Index: lib/facebooker/rails/routing.rb
===================================================================
--- lib/facebooker/rails/routing.rb (revision 155)
+++ lib/facebooker/rails/routing.rb (working copy)
@@ -30,10 +30,10 @@
         #  update_profile POST /profiles/:id/update  {:controller=>"profiles", :action=>"update"}
         # destroy_profile POST /profiles/:id/destroy {:controller=>"profiles", :action=>"destroy"}
         #
-        def facebook_resources(name_sym)
+        def facebook_resources(name_sym, options={})
           name = name_sym.to_s
 
-          with_options :controller => name, :conditions => { :method => :post } do |map|
+          with_options({:controller => name, :conditions => { :method => :post }}.merge(options)) do |map|
             map.named_route("new_#{name.singularize}",     "#{name}/new",         :action => 'new')
             map.named_route(name,                          "#{name}/index",       :action => 'index')
             map.named_route("show_#{name.singularize}",    "#{name}/:id/show",    :action => 'show',    :id => /\d+/)

ruby's method_missing equivalent for php?

Posted by James Brooks Tue, 22 Jan 2008 02:13:00 GMT

ruby's method_missing is a wonderful little method which can be used to catch method calls for undefined methods, providing both the name of the method and the passed arguments. This can be useful for 'adding' dynamic methods, such as the dynamic finds found in Rails' ActiveRecord::Base.

While starting development on a minimalist PHP framework, ToyTrain (TBA, which I hope to make life a little easier at work for those times where I have to use PHP and the app isn't going to take more then a few days to write), I had hoped to use a PHP equivilent method_missing idiom to implement dynamic finders in my Active Record implementation.

It took quite a bit of googling to find anything close to what I was after, and eventually I stumbled upon one of the 'magical' PHP functions, __call. Classes can implement call to handle calls to functions to instances of classes, such as in the following:

class Ninja {
  function hide() {
    print "This ninja is now hidden";
  }
  
  function __call($name, $args) {
    print "This ninja isn't sure about $name, but they'll try!";
  }
}

$larry = new Ninja();
$larry->hide();
$larry->assassinate();

In the above we define a Ninja class, which can do many fantastic things (all our ninja's can current do is hide). In the calls following, we create a new Ninja instance and call hide() (this works as expected, and results in "This ninja is now hidden". The new call though, assassinate() isn't defined by the Ninja class. Instead of falling on it's head and throwing a 'PHP Fatal error: Call to undefined function assassinate()', PHP delegates the call through __call and we yield the result "This ninja isn't sure about assassinate, but they'll try!".

Fantastic, so we've got what we need to implement dynamic finders, right? sorta...

in our class above we've defined 'function __call', which occurs when a missing function is called on particular object instance. What happens if we just wanted to call the class method, Ninja::gather()?. We can't define a static function __call, as static functions calls are resolved at compile time (boo!).

Looks like __call isn't going to work if we want to have nice syntax for dynamic finders (e.g. class function calls, rather then creating an dummy instance and then making the function call to be caught by __call).

From what I can gather that's what we're stuck with until we all upgrade to PHP 6 (and hopefully, the functionality will be backported into PHP 5), as that's when we'll get __staticCall (gathered from http://bugs.php.net/bug.php?id=26739).

Country Codes Rails Plugin 19

Posted by James Brooks Mon, 17 Dec 2007 09:52:00 GMT

I've written my first rails plugin (yay!). It's not anything long or impressive, just something that I needed which I couldn't find a suitable existing solution to.

The Country Codes plugin finds and converts between country information as described in ISO 3166-1 (wikipedia): ISO 3166-1, as part of the ISO 3166 standard, provides codes for the names of countries and dependent territories, and is published by the International Organization for Standardization (ISO). The official name of the standard is Codes for the representation of names of countries and their subdivisions .

Lets install the plugin and have a look, in your rails application root type:

./script/plugin install http://opensvn.csie.org/country_codes/trunk/

Inside the rails application (let's use the console here to do this quickly) we can now perform the following actions using the CountryCodes module:

CountryCodes.find_by_name('Australia')
{:numeric=>36, :name=>"Australia", :a2=>"AU", :a3=>"AUS"}

That gives us a nice hash back from which we can access either of the following ISO 3166-1 information: Country Name (name), Alpha-2 code (a2), Alpha-3 code (a3) or the Numeric Code (numeric). We can also search by any of these attributes, as seen in the following:

CountryCodes.find_by_a2('JP')
{:numeric=>392, :name=>"Japan", :a2=>"JP", :a3=>"JPN"}

CountryCodes.find_by_numeric(32)
{:numeric=>32, :name=>"Argentina", :a2=>"AR", :a3=>"ARG"}

Additionally, you can request which attribute you'd like form the result with a call like below:

CountryCodes.find_name_by_a3('SWZ')
"Swaziland"

All of the search conditions are case insensitive.

Well there you have it, a simple rails plugin for performing lookups on ISO 3166-1 country information. If I've missed any information please leave a comment :)

Google Reader fetcher reports number of feed subscribers

Posted by James Brooks Thu, 06 Dec 2007 05:46:00 GMT

A while ago I had a tail running on an access.log for an Apache server I was trying to diagnose a problem for when I noticed a request from Google, presumably updating the feed for a blog on the server.

X.Y.X.Y - - [05/Dec/2007:21:37:56 -0800]
  "GET /blog.rss HTTP/1.1" 200 320 "-" "Feedfetcher-Google; 
    (+http://www.google.com/feedfetcher.html; 1 subscribers;
    feed-id=1348752205994822097)"

The interesting thing that jumped out at me from this is that during the feed update requests, the fetcher reports the number of subscribers to the feed (in this case one, being myself seeing how this is a project in development).

Something like this might be handy to provide subscription statistics in blog administration areas. Does anyone know if you can request the number of subscribers for a feed through Google Reader?