Piggy back plugin updated

Posted over 7 years back at RailsExpress.blog

Timo Hentschel, one of my coworkers at the company for which I’m doing contract work at the moment (AutoScout24), has added a nifty little extension to my piggy_back plugin.

It’s now possible to piggy back from has_many :through associations, provided the association will return at most one record from the underlying SQL query.

This type of association currently needs to be used as a replacement for the non existent has_one :through.

There have been rumours that has_one :through will find it’s way into rails core. If it does, I’ll probably remove the has_many :through support from piggy back plugin again, or at least raise a deprecation warning.

UJS @ RailsConf Europe 2006

Posted over 7 years back at Luke Redpath - Home

Update 15 Feb 2009: The UJS plugin for Rails is no longer actively maintained but you can find the the source on github.

There has been a tremendous amount of interest at RailsConf Europe in the UJS Rails Plugin. Dan gave his talk on Thursday morning and it was a struggle to get in; it was completely oversubscribed (I had to use the old ‘but I’m the co-author!’ line just to get in). It was great to see the interest it had generated. The talk proved so popular that a second presentation was scheduled on the Friday in the main congress hall which again proved really popular; we managed to fill up most of the room despite it being lunch – not a bad achievement.

Dan gave a great presentation that went into the full details of the whys and wheres of unobtrusive scripting before giving a run down of the core UJS features, wrapping up with a small case study: building an AJAX-powered shopping cart using UJS. He showed how to build the shopping cart so it works in a traditional manner without JavaScript and then he used UJS to layer the additional behaviour on top of that.

RailsConf Photo

Some people brought up some interesting questions at the end of the talk, some of which I’d like to address.

One person asked if there were any major drawbacks to working this way. In general, I think you’ll find that once you have got into the right mindset, you will find yourself always thinking about how things will work with and without JavaScript. Its important to stress that it is a mindset change, as Dan pointed out in his presentation. It took some time to convince people of the advantages of CSS-powered layouts and I have a feeling that it might take some time with unobtrusive scripting but I think we’ll get there eventually.

Somebody questioned whether or not this approach will work when you trying to create a web-based application that mimcs a desktop application; he cited something like Google Spreadsheets or Google Maps. I think in situations like this it could be difficult to use UJS, simply because creating a fallback would be difficult. You’d also have to question the usefulness of an application like a spreadsheet that didn’t work without JavaScript – how usable would it be? Campfire is another example of where the AJAX functionality is integral to the way in which it works.

Google Maps on the other hand could easily be made unobtrusive. Think about it: how did web-based mapping apps work before AJAX came along? They presented a static map with arrows on each side for moving across the map. It is slow, but it works. There is no reason why Google Maps can’t fall back on this behaviour in the absence of JavaScript.

On a related note, it was great to hear from the guys at Odeo and that they really liked the UJS plugin. They mentioned that most of Odeo is unobtrusive and they had to roll a lot of their own JavaScript helpers and raw JavaScript to achieve this. If Odeo start using UJS, that would just be awesome.

There was one other concern relating to the use of links for GET requests only (with no side-effects) and buttons for everything else (POST, PUT and DELETE in REST terms). The concern revolved around the ability to style buttons. Styling buttons can be tricky in some browsers (such as Camino) but this is easily worked around with a bit of clever CSS or use of an image button.

One thing Dan didn’t mention in his presentation, which is worth pointing out, is that the UJS plugin upgrades the built-in Rails helpers (link_to_remote are given the appropriate values.

However, I still want to stress that if you can use the link_to_remote can make things a bit funky:

<% @products.each do |p| %>
  <p><%= link_to_remote product.description, :controller => 'products', 
                                                :action => 'description', 
                                                :id => p.id %></p>
<% end %>

The above will work, but very slowly. That’s one behaviour rule for every div

<div id="products">
<% @products.each do |p| %>
  <p><%= link_to product.description,
           :controller => 'products',
           :action => 'description', 
           :id => p.id %></p>
<% end %>
</div>

<% apply_behaviour "#products a", make_remote_link %>

One behaviour for any number of products.

If you haven’t tried UJS yet, do give it a go. www.ujs4rails.com is the official website, and it contains documentation, tips, tricks, a quick start guide and things such as rdocs and a Trac for filing tickets.

If you like to live on the edge, feel free to try running on the trunk – we have some cool new ideas on the way for 0.4 and 0.5, including custom assertions for Test::Unit for asserting behaviour (and some extensions for RSpec too!) and a cool in-browser debugger that will let you do things such as view elements with behaviour applied and what behaviours are applied to those elements. Combined with FireBug and Thomas Fuchs’ unittest.js library (see my article on his RailsConf talk), that should make a pretty awesome testing environment for your AJAX apps.

Have fun with UJS. All feedback is welcome, especially if you have some ideas that you think would make UJS even cooler.

SqlSessionStore now available as a plugin

Posted over 7 years back at RailsExpress.blog

Rails core team member Rick Olson, the author of many rails plugins, mephisto and techno-weenie, has turned SQLSessionStore into a plugin and sent his code for me to publish. Thanks a lot Rick!

I incorporated the latest changes from my sql session store implementation, most notably postgresql support, and added sql_session_store to my trac installation.

Using sql_session_store is now easier than ever before. Check it out into your vendor/plugins directory:

svn co http://railsexpress.de/svn/plugins/sql_session_store/trunk  \
 sql_session_store

and follow the instructions in the README file.

If you find any problems with the plugin, which would be entirely my own fault, not Rick’s, please use Trac to report them.

BTW, I’d love to get support in for additional database adapters, especially Oracle. I you find the time to write an adapter, please submit the code using Trac, or email me.

RailsConf: Adventures in JavaScript testing by Thomas Fuchs

Posted over 7 years back at Luke Redpath - Home

I’m currently sitting in the main congress hall awaiting the start of Thomas Fuch’s presentation. As I’m sure many readers of my blog are aware, I’m a huge advocate of testing, or to be specific, good testing. However, one thing that I’ve never managed to get into is unit testing with JavaScript. I’ve never really been aware of the tools available or how well it works.

I’m going to write this post live; hopefully it won’t just come across as a mish-mash of incoherent ramblings.

  • Traditional JavaScript “testing” generally revolves around alert. it can be useful sometimes but it generally doesn’t offer anything interesting. Use it sparingly.
  • There are many common misconceptions or attitudes towards JavaScript: “we don’t need tests for 10 lines of code”; “but you can’t debug JavaScript”. Wrong and wrong again. Enter unit testing for JavaScript.
  • Some options exist already, such as jsunit. These have their problems, such as awkward syntax or problems with Prototype.
  • Scriptaculous has its own unittest.js library. All you need to do is include the unittest.js file and an empty div with a “testlog” HTML ID (defaults). Now you’re ready to roll with Test.Unit.Runner.
  • Test.Unit.Runner looks quite similar to the standard xUnit family of testing libraries. It has the standard setup and teardown methods and a suite of assertions.
  • It has some good testing functionality for dealing with effects, and time-sensitive behaviour (wait function).
  • It has a basic benchmarking system too!
  • Rake integration is provided through a the javascript_test plugin – it allows you to launch browsers and run your javascript unit tests through a single command: rake test:javascripts. It uses a WEBrick server and supports multiple browsers, including Camino, Firefox, Safari and Internet Explorer. It’s fairly trivial to add support for other browsers too. It seems to be missing the functionality to close the browser after the rake test run. Perhaps the browser definition classes could be extended to support a “close” method that is called after the test run?
  • The plugin also provides a generator for generating test stub files (HTML format) in test/javascript.
  • Did I mention the browser-based test runner looks pretty sweet?
  • OK, here’s the killer feature so far: RSpec-style syntax, including should* style expectations and context/spec format. I’m convinced, sign me up!
  • Some other hints and tips: If you aren’t using Firebug already, then start using it! It is awesome and makes debugging AJAX and general JavaScript problems a lot easier. (as an aside, its also great for debugging your behaviours when you are using UJS). There is also a tool for Safari called Drosera.
  • Don’t forget your RJS templates either. RJS has some basic debugging support built-in (although this could really do with being expanded upon).

During the question and answer session, Simon Willison mentioned a tool that was part of the Dojo Toolkit that uses a command-line JavaScript interpreter to run its unit tests. It sounds interesting although I feel its a lot more useful to run the tests in the actual environment they are going to run in (i.e. the browsers). By introducing something like a separate interpreter that end-users aren’t going to be using, you are relying on that interpreter being correct.

All in all, it was a good talk and has really got me interested in unit testing with JavaScript. It’s definately something I should be doing, especially as I am so strict about testing with the rest of my code.

Finally, a word of warning for those who want to try a bit of live blogging: IRC is evil and distracting. Use with caution!

Links and useful information:

Gosling v. Greenspun

Posted over 7 years back at Ryan Tomayko's Writings

James Gosling, in a weblog entry on the proposal to add closures to the Java language, dubs his Black Hole Theory of Design:

“Lisp is a Black Hole: if you try to design something that’s not Lisp, but like Lisp, you’ll find that the gravitational forces on the design will suck it into the Black Hole, and it will become Lisp”

Compare to Greenspun’s Tenth Rule of Programming (1993):

“Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.”

Which quote you use will depend on your perspective, I suppose.

Here's a Nickel, Kid

Posted over 7 years back at Ryan Tomayko's Writings

The Dilbert strip referenced in Neil Stephenson’s In The Beginning Was The Command Line:

Here's a Nickel, kid

Huge thanks to Mike Taylor for the original scan and to quickpost for the pointer.

There’s a lively discussion of the section titled, The Hole Hawg of Operating Systems, on reddit.

This strip ran on 06/24/1995 — more than 11 years ago. It is still timely and relevant, although for reasons different from 1995.

It is featured on the front of Advanced Programming in the UNIX® Environment (Addison-Wesley Professional Computing Series):

Advanced Programming in the UNIX Environment

Stephenson actually mis-describes the strip in the essay:

(2) a copy of a Dilbert cartoon in which Dilbert, the long-suffering corporate software engineer, encounters a portly, bearded, hairy man of a certain age—a bit like Santa Claus, but darker, with a certain edge about him. Dilbert recognizes this man, based upon his appearance and affect, as a Unix hacker, and reacts with a certain mixture of nervousness, awe, and hostility. Dilbert jabs weakly at the disturbing interloper for a couple of frames; the Unix hacker listens with a kind of infuriating, beatific calm, then, in the last frame, reaches into his pocket. “Here’s a nickel, kid,” he says, “go buy yourself a real computer.”

It was not the Dilbert character but Wally that had the encounter with the Unix hacker. The hacker quotation is also inaccurate but perhaps better than the original.

Dilbert is by Scott Adams and runs daily on the web and in 2500 newspapers worldwide in 65 countries and 19 languages with over 150 million fans.

Best 500 Page Eva!

Posted over 7 years back at Ryan Tomayko's Writings

I so wish I could throw this into my boring business software app:

reddit broke

Somehow I don’t think my customers have the same sense of humor.

Speaking of programming.reddit.com, I've been spending a lot of time there. Go for the links, stay for the comments – the discussion is top notch unlike some others we know.

Top.app

Posted over 7 years back at Ryan Tomayko's Writings

One thing that’s always bothered me about MacOS X’s Terminal.app is that you can’t really run multiple applications. Technically you can but it’s not right having to switch to Terminal and then cycle through the windows to get to the one you want.

And I'm not talking about being able to have multiple shells running so keep your iTerm has tabs bullshit to yourself. I use GNU/Screen for that and am quite happy with it.

There’s a handful of textmode tools I'd like to be able to run as if they were all out Mac applications like Mutt, irssi, elinks, and Vim.

Some of the more popular textmode tools have graphical versions. Mac Vim is solid. AquaEmacs was a little wonky the last time I played with it. MacIrssi sucks because you can’t use plugins and, really, what’s the point of using a shitty textmode anything if you can’t customize the piss out of it?

We need Terminal.app to be a generic container for all of the textmode tools we'd like to pull up to first-class application land. The good news is that, after reading this article, you’ll be able to do just that. The bad news is that it requires quite a bit of work and the technique is pretty nasty. I would even go so far as to call it a big giant hack.

Top.app Dock Icon

To illustrate, we’re going to turn top into a standalone application: Top.app. Yes, even a tool as humble as top ought to have its own bouncy Dock icon and Command+Tab target. We’ll use it as a backup for Activity Monitor the next time it goes all beach-ball on us.

We need another .app

The first thing I don’t like about this approach is that you have to copy Terminal.app in its entirety. I recommend the Applications directory under your $HOME:

$ mkdir -p ~/Applications  # this may already exists
$ cp -r /Applications/Utilities/Terminal.app ~/Applications/Top.app

Without doing anything else, you can run Top.app and get a separate item in The Dock and Command+Tab.

Open it from Finder, or:

$ open ~/Applications/Top.app

Changing The Menu

The menu still says “Terminal”, which is kind of annoying. We can change this without too much hassle by editing the InfoPlist.strings file under your locale’s directory. Check this out:

$ cd ~/Applications/Top.app/Contents/Resources/English.lproj
$ cat InfoPlist.strings
"CFBundleHelpBookName" = "Terminal Help";
"CFBundleName" = "Terminal";
"NSHumanReadableCopyright" = "? Copyright 1995-2003 Apple Compute ...

We need to open the InfoPlist.strings file in an editor that’s UTF-16 aware and change the CFBundleName value from “Terminal” to “Top”. Vim worked swimmingly for this task and OmniOutliner actually has a special graphical mode for strings files. But you can open it in TextEdit if neither of those is available to you:

$ open -a TextEdit InfoPlist.strings

Once saved, you can quit and start Top.app again and you should now see “Top” in the menu instead of Terminal.

Changing The Icon

The hard part about this step is finding an .icns file for the tool you’re running. top is the command-line equivalent of Activity Monitor, so let’s just grab the icon from there:

$ cd ~/Applications/Top.app/Contents/Resources
$ cp icon.icns{,.orig}     # backup original icons file
$ AM=/Applications/Utilities/Activity\ Monitor.app
$ cp "$AM/Contents/Resources/ActivityMonitor.icns" icon.icns

Note that the new icon won’t show up until you restart Finder. In most tutorials, this is where you logoff and back on. Fuck that:

$ killall Finder

TIP: If you have Apple’s Developer Tools installed, you can find more icns files in the wilderness that is /Developer/Applications.

Top Icon

Customization

Now comes the sickest part of the hack.

We’re presented with a bit of a dilemma. We want our Top.app window to be fully customized and we also need a specific command to be executed (/usr/bin/top). That’s not the problem – Terminal.app stores these types of customization in .term files, which are easily created by opening a terminal, customizing it using the inspector (Command+I), and then saving it (File -> Save As or Command+Shift+S). When you save the .term file there’s an option labeled, Open this file when Terminal starts up and this is the problem: the setting applies to all Terminal applications (even copies) because the default .term file is set as a user global preference in ~/Library/Preferences/com.apple.Terminal.plist. So, if we open Top.app as is, customize it, save it and check that box, we’ll end up loading the Top.term file when any terminal is launched.

But it’s okay because Mac applications turn out to be extremely hackable. On most systems, you'd be getting out your hex editor and patching binaries. But not here – changing the preference property list used by an application turns out to be trivial:

$ cd ~/Applications/Top.app/Contents/
$ grep -A1 CFBundleId Info.plist 
      <key>CFBundleIdentifier</key>
      <string>com.apple.Terminal</string>

See that? Rock! All we need to do is change com.apple.Terminal to something else, like com.rtomayko.Top. You can open the file in the nice little Property List Editor.app and change the CFBundleIdentifier property or you can start using your machine as God intended:

$ perl -pi.orig -e 's/com\.apple\.Terminal/com.rtomayko.Top/'
$ grep -A1 CFBundleId Info.plist 
      <key>CFBundleIdentifier</key>
      <string>com.rtomayko.Top</string>

It’s smooth sailing from here on out. Open Top.app and you should get a little white terminal window. Run top -s1 -ocpu at the prompt so we can get a feel for how the window should be dimensioned. Bump the font size up about 5 times using Command + and then resize the window so that the top output fits just right.

Next, hit Command+I to get into the inspector, and customize it as you see fit. Here are the settings I used for each of the customization areas:

  • Shell – When the shell exits, close the window.
  • Processes – Prompt before closing window: never.
  • Buffer – Buffer Size: Disabled (there’s no need for a scrollback buffer in cursors apps).
  • Display – Text: Bitstream Vera Sans Mono, Anti-aliasing, Disable Blinking Text.
  • ColorGreen on Black, Transparency.
  • Window – Title: “Top”, disable everything else.

The Finished Product

Now, hit Command+S to save the .term file. You get a normal Save As dialog with a few extra options. Enter “Top” in the Save As box, you want to save the Main Window, you want to open this file when Terminal starts up, and you want to execute the following command:

exec /usr/bin/top -s1 -ocpu

You also want to check the Execute command in a shell box (it’s the only way I've found that let’s you pass arguments).

Save It

Save it and Quit. If everything went right, you should be right back where you left the next time you open Top.app.

Lather, Rinse, Repeat

To sum up, the basic steps are as follows:

  1. Copy Terminal.app to Foo.app.
  2. Edit Locale.lproj/InfoPlist.strings for the menu and Info.plist for the preference.
  3. Overwrite icon.icns with a distinct .icns file.
  4. Open Foo.app, customize, save .term file as Default.

Issues / Ideas

This approach has drawbacks and limitations:

  • It’s not correct. Terminal.app should provide a mechanism for achieving these results without all the hackery.

  • Updates to Terminal.app will not automatically be picked up. It may be necessary to go through the process after an update.

  • I have not been able to figure out if it’s possible to open files or pass arguments to these applications otherwise.

I'm considering throwing together a quick shell script that’s capable of performing the nitty gritty aspects given a directory containing a few files: the .icns file and maybe some kind of simple config file that contains the values needed for the Info.plist.

New business cards

Posted over 7 years back at Luke Redpath - Home

Check out our new Agile Evolved business cards which arrived today, just in time for RailsConf.

businesscards

They look really cool. They were printed by Aubergine Print. Our new logo was designed by Tokyo Cube. Mine haven’t arrived yet, but when they do I’ll update the above photo with something a bit more high-quality (theres only so much you can do in Photoshop to improve a camera phone picture).

There will hopefully be many of these being handed out at next week’s European RailsConf.

analogies.google.com

Posted over 7 years back at Ryan Tomayko's Writings

It’s a bit like a Hefty Bag filled with vegetable soup.


<script type="text/javascript"> function analogize() { var word = document.getElementById('ga-word').value ; var query = document.getElementById('pretentious').checked ? ' is a bit like' : ' is like' ; document.getElementById('ga-query').value = '"' + word + query + '"' ; return true; } </script>

Here’s some ideas to get you started:

  • America
  • God
  • Java (pretentious mode)
  • Perl (pretentious mode)
  • My Girlfriend
  • Your Mom

Web Based Site Monitoring Tools

Posted over 7 years back at Ryan Tomayko's Writings

A recent upgrade broke an instance of Nagios we use to monitor non-critical stuff. I've always been impressed w/ Nagios' massive feature-set but the web based GUI leaves a lot to be desired. That combined with the fact that I'm beginning to dislike the amount of daemon processes I have running all over the place has led me to consider alternatives.

As all this was unfolding, I just happened to come across a link to Site24x7 so I decided to give it a spin. Site24x7 makes HTTP/ HTTPS requests at regular intervals of time, tracks your website response time, and notifies via email or SMS when your website is down or when the response time has crossed certain limits you have set. That’s exactly no more and no less than what I need so I think these guys found a nice little sweet-spot.

It’s also free and beta.

I've been monitoring six different sites for a week and it pretty much just works. Here’s what lesscode.org’s monitor looks like at the moment:

site24x7

So that’s Site24x7 in a nutshell. Does anyone have experience with any of their competitors?

Decorator Pattern with Ruby in 8 lines

Posted over 7 years back at Luke Redpath - Home

The Decorator Pattern is a design pattern that enables you to dynamically wrap behaviour around an existing object at runtime. It is especially useful when an object can have many variables that can be combined in different ways, which in turn affect it’s behaviour.

This small, simple implementation of the decorator pattern in Ruby sums up what I love about the hottest dynamic language on the planet.

I’ll borrow a simple example from the excellent Head First Design Patterns book by Eric Freeman, Elisabeth Freeman, Kathy Sierra, and Bert Bates.

Let’s say you want to calculate the cost of a cup of coffee. You have Coffee class, which implements a cost() method. For the purposes of this example, let’s just hardcode a value:

class Coffee
  def cost
    2
  end
end

Great. But what if we want the cost of a coffee with milk? We could have a new class:

class WhiteCoffee
  def cost
    2.4
  end
end

OK. But now we want cream. And sprinkles. Clearly, creating new classes is going to lead to a huge number of classes in our application. It just isn’t realistic to create classes for different combinations of coffee and extras. It could get worse – what if we have different types of coffee? We would then have to have combinations of extras with each different type of coffee. It just isn’t going to work. Enter the decorator pattern. Here’s the the 8 lines of Ruby mentioned in this entry’s title:

module Decorator
  def initialize(decorated)
    @decorated = decorated
  end

  def method_missing(method, *args)
    args.empty? ? @decorated.send(method) : @decorated.send(method, args)
  end
end

And thats all you need. You can include this into any class you want to act as a decorator. You can then use that decorator as if it was the object it is decorating; by default all messages sent to the decorator are forwarded on to the decorated object. You can then decorate the methods you need to extend:

class Milk
  include Decorator

  def cost
    @decorated.cost + 0.4
  end
end

So how does this solve our original problem? The real power of decorators lies in the fact that they can act like the objects they are decorating. By taking this one step further, you can wrap decorators with other decorators as long as they share the same interface. By creating decorators for our different “extras”, we can create coffees using a combination of decorators and get the total cost of the coffee.

class Whip
  include Decorator

  def cost 
    @decorated.cost + 0.2
  end
end

class Sprinkles
  include Decorator

  def cost
    @decorated.cost + 0.3
  end
end

Whip.new(Coffee.new).cost
#=> 2.2
Sprinkles.new(Whip.new(Milk.new(Coffee.new))).cost
#=> 2.9

Of course, there’s nothing stopping us from making life easier with a few factory methods:

class CoffeeFactory
  def self.latte
    SteamedMilk.new(Espresso.new)
  end
  
  def self.cappuccino
    Sprinkles.new(Cream.new(Milk.new(Coffee.new)))
  end
end

order = Order.new
order.add(Coffee.new)
order.add(CoffeeFactory.cappuccino)
puts order.total

Due to Ruby’s highly dynamic nature, the Decorator pattern isn’t the only way of extending class functionality at runtime, however I just love how simple it is to implement the pattern in Ruby. For more information on implementing decorators in Ruby, including generic decorators and alternatives to the traditional decorator pattern, see the DecoratorPattern page at the RubyGarden.

Finally, it would be nice to maintain some kind of identity when using decorators. The RubyGarden page above has one approach. Whilst we aren’t using inheritance, it would be nice to retain one of its features:

CoffeeFactory.cappucino.kind_of? Coffee
#=> true

I can think of a few ways of extending my Decorator class to retain this functionality, but I’m gonna leave this one to the reader. Over to you.

Update: In typical Ruby-fashion, my 8 lines of code has been beaten by, well, zero lines of code by Trevor Squires. Using modules, super and extend, Trevor came up with this alternative solution, which maintains identity as well. Bow down to his Ruby-fu.

Update 2: Never one to step back from a challenge, I see Trevor’s Ruby-fu and raise him with a bit of my own. I still feel my decorator implementation carries some weight, with a nice bit of syntatic sugar:

class Milk
  include Decorator
end

class Whip
  include Decorator
end

class Sprinkles
  include Decorator
end

# normal coffee
Coffee.new

# coffee with milk, whip and sprinkles
Coffee.with :milk, :whip, :sprinkles

The self.with method could do with being extracted into a Decoratable module but here’s a concrete implementation. Trevor’s method still has an advantage in that it maintains object identity, but I have some ideas to solve that. But alas, it is past 1am and bed beckons.

Update 3: Trevor fights back with his own self.with() implementation. Personally I prefer the extend implementation, it eliminates the symbol to class trickery, and still maintains identity. His ’fu is still strong.

However, there is one downside to Trevor’s method: you can only apply a decorator to an object using <filterjscode lang="ruby" inline="true">extend once. But what if you wanted double sprinkles?

Sprinkles.new(Sprinkles.new(Coffee.new))

# or with a bit of sugar (no pun intended)
Coffee.with :sprinkles, :sprinkles
</code></pre>

I Hate This Place

Posted over 7 years back at Ryan Tomayko's Writings

So I decided to resurrect this weblog. Or, should I say, this giant mess of crap that I've decided I now hate. Everyone always says that rolling your own weblog engine is a stupid idea but I did it anyway because, well, I was stupid. It was stupid when I put it together originally and it was stupid yesterday, when I spent a few hours moving everything from Python w/ a brain-dead file based data store to Ruby, Rails, and MySQL…

Dumb.

I should have grabbed Mephisto instead. No, I should have did wordpress.com and just let this place go.

I should never have gotten out of bed this weekend.

A long time ago, I had a bunch of novel ideas like tagging and bookmark integration, and some other things I never got around to doing. Today, most weblog software has all that stuff but I've decided it doesn’t matter because it’s all stupid. I wanted all my crap (bookmarks, articles, essays, smaller weblog entries, etc) in the same place and tagged so that I could combine tags in the URL, a la del.icio.us, and have these ad-hoc pages filtered using this mini URL based query language. I spent way too much time implementing all this crap and then never used it. Not once.

It’s a stupid idea.

Did I mention you could grab an Atom feed for any combination of tags? How cool is that?

It’s not. I never used it. Not once. It’s been ripped out.

There are exactly three things that matter on a weblog. In order of importance, they are:

  1. “Permalink” / real content pages.
  2. Archives.
  3. The main feed.

Anything else becomes a minor annoyance at best (blogrolls, what’s on your record player, the weather in your zip code, etc). Weblog navigation using tags, on the other hand, is almost entirely annoying and tag clouds as a navigational device is quite possibly the worst of 50 really stupid options.

All of the aforementioned have a place, of course, just not on your weblog. If you want to tag stuff, do it on del.icio.us. Want to broadcast what’s currently on your record player? Do it on last.fm. Blogrolling goes here. What people read on your site can be found on reddit.

Coming into harmony with the web means accepting that each end should do exactly one thing well. The weblog is for writing (or publishing anyway — Emacs is for writing), everything that’s not your weblog is for everything else.

So, should time permit, I'm going to completely redesign this place to be totally bleeding edge. I'm going to attempt to emulate what is quite possibly the greatest technical weblog on the planet: Kragen’s TOL.

The first rule of Barcamp...

Posted over 7 years back at Luke Redpath - Home

Ongoing updates live (or when I get round to it) from Barcamp London. I’ll be posting notes on the presentations I attend as the weekend goes on.

Yahoo reception photo

4pm: Above is my current view as I sit in the reception of Yahoo’s swanky West End offices, trying to polish off the second part of my BDD/Rails tutorial, whilst panicking about my UJS presentation tomorrow (AKA my first ever presentation).

After arriving fashionably late (ok, 4 hours late) I dropped into Jonathan’s Comet talk, which was followed up by a talk on the Low Pro extension to the Prototype Javascript library by Dan Web.

Jonathan’s talk on Comet gave me some ideas about a forthcoming project we’re gonna be working on here at Agile Evolved. There do seem to be a few implementation issues to resolve first however.

Surprisingly, Dan’s Low Pro talk was a revelation to me. I say surprsing, because you think I’d know all about Low Pro, what with it being the core behind the UJS For Rails plugin however I was only really aware of its improved event handling capabilities. Even cooler was its improved DOM support and the real killer for me, Behaviour classes. Behaviour classes let you build self-contained classes that contain behaviour for a collection of events, which can then be applied to elements in one goal. Dan is going to be blogging about this in full, but here is a small snippet:

var Sortable = Behaviour.create({
  initialize : function() { },
  onclick: function() { },
  onmouseup: function() { }
});

Event.addBehaviour("#todolist li", Sortable);

How awesome is that? It would be a great to see a re-implementation of script.aculo.us behaviours using Behaviour classes. Its also a great way of building and packaing up your own unique behaviours.

6:14pm: Award for most bizarre use of the English language goes to Simon Willison.

“I’m still upset on a theoretical level.”

Sunday, 3pm: OK, here’s some advice. If you are going to do a presentation, don’t leave it until the last minute to put together. I managed to get my slides finished by about half past 1 and was on the train into central London by 2. In the end my presentation seemed to go ok, though I’m still not a fan of public speaking.

Despite arriving so late, I did manage to couple catch a couple of interesting talks. Nick Fitzsimons gave an interesting talk on the correct use of HTTP, which extended nicely from a talk on Saturday regarding REST and Rails (and whether or not to use it). We generally agreed that in an ideal world, content negotiation and a single URL for a resource (with the accept header determining how you want that resource to be presented) is a good thing. However, there were concerns voiced about misconfigured proxy servers that could end up munging with accept headers which would result in some very strange behaviour.

People were more positive about using HTTP verbs to perform different actions on a resource. The issue surrounding proxy servers (which may not allow certain verbs) remained but it was less severe as a proxy server that did not support a particular verb would simply fail, rather than appear to work but actually do something strange.

Thanks to those who did attend my talk on Unobtrusive Javascript with Ruby on Rails. If you weren’t able to attend Barcamp, you can download the slides.

All in all it was a good weekend. It was good to meet some interesting and friendly people. If you haven’t attended a Barcamp before, I suggest you keep an eye out for one in your area, as they are great fun.

Dave Thomas and Mike Clark - Ruby on Rails Podcast

Posted over 7 years back at Ruby on Rails Podcast

A clarification of what it means for Rails to enter the enteprise, and a preview of the upcoming Rails Edge conferences.
Also mentioned: