Capistrano 2.0, upgrading & fitting into a size 0 dress

Posted about 7 years back at Wood for the Trees

The improvements to Capistrano are much welcomed. My deployment recipe is now half the length it used to be and it is much easier to follow what is happening for my many types of deployment. I love the new features added, mostly dealing with manipulating scopes and enhancing the user’s ability to extend the core framework.

Review of new features

namespaces: Like Rake, you can namespace your tasks and group them together more sensibly. This feature alone is worth upgrading for just to make your scripts more sensible and easier to read.

events: Like Rails, you can now perform tasks before or after other ones rather than using the hacky ‘before_something’ and ‘after_something’. Much cleaner and much faster too.

strategies: In addition to checkout, you can now deploy via export and copy and use different strategies for deployment, such as using export for your copy_strategy rather than zips and tarballs.

scoping: All sorts of scoping has been introduced in Capistrano 2.0, from namespacing to single execution of “run” and “sudo”, allowing you to define specific roles or hosts in which your commands run.

help: Capistrano 2.0 now has a more verbose way of explaining tasks with cap -e task_name. You’ll realise how useful this is when you use it for the built-ins as well as your own.

All in all, Capistrano is pretty simple, but it is the way it is written that makes it appear so much simpler than it really is. Capistrano 2.0 takes that to a new level, not groundbreaking perhaps, but definitely a lot cleaner than its previous releases.

Upgrading from 1.4.1

There is no need to change config/deploy.rb out of the box. Capistrano 2.0 is nicely backwards compatible, unlike other things out there, and, at least for me, nothing broke because of the upgrade.

You can look at Capistrano’s instructions for upgrading, if you want to know what is being done, but for the impatient, here are the steps you have to follow before we can start drying up your deploy script.

1. Install the new version of capistrano:
sudo gem install capistrano
2. cd project_root & run capify
~# cd projroot
projroot# capify .
3. Upgrade previous deployments to use the new revision tracking system
projroot# cap -f upgrade -f Capfile upgrade:revisions

4. Rinse and repeat for each of your deployment targets

Getting your deploy.rb into its new size 0 dress

You may now have the very understandable urge to slim down your deployment recipes. With the introduction of Capistrano 2.0, I found my deploy.rb reduced to less than half the size. Below, I cover the areas which you should focus on to get that deploy script into its new size 0 dress.

Anatomy of my deploy.rb

  1. requires: capistrano-ext, mongrel_cluster, etc.
  2. global, stage and custom variables
  3. event chains
  4. rewriting built-ins: web:disable and web:enable
  5. extra tasks: fixing permissions, copying mongrel confs, etc.
  6. custom deploy tasks: long, normal, quick
  7. maintenance tasks: backup, restore

Variables

More than before, variables are the lynch-pin of slimming everything down. The first thing you should do is look over every task rewrite or custom task and see how it can be turned into a simple set :var, true/false/whatever. Capistrano 2.0 will make it very easy to do this.

With Capistrano 2.0, you should use the set command religiously, both for built-in and custom tasks.

I personally set the following at the top of my recipe.

  • Global variables: stages, deploy_via
  • Application specific: application, repository, user, scm_username
  • Deployment specific: deploy_to, rails_env
  • Custom variables: serving_via, suexec, suexec_user, suexec_group, disable_template

Deployment Strategy

I would personally suggest using xport for your deploy_via strategy unless you have a reason for using heckout or copy.

Using Namespaces

Namespaces make it dead simple to group common tasks, like different restart methodologies. I use a serving_via variable which translates into the reload:whatever task to run for restarting the application. For example:

namespace :reload do
  desc "Default reloading procedure"
  task :default do
    mongrels
  end
  desc "Reload an FCGI application"
  task :fcgi, :roles => :app do
    sudo "#{current_path}/script/process/reaper -a graceful -d #{current_path}/public/dispatch.fcgi"
  end
  desc "Reload an LSAPI application"
  task :lsapi, :roles => :app do
    sudo "/usr/local/litespeed/bin/lswsctrl restart"
  end
  desc "Give the mongrels a bath"
  task :mongrels, :roles => :app do
    restart_mongrel_cluster
  end
end

Note: I warn against using restart as a namespace because it clashes with the built-in task and, in certain instances, results in infinite recursion.

Maintenance Splash

The biggest change in Capistrano you may need to worry about is the removal of delete and render. Don’t despair, though, because creating a maintenance splash is still easy. This is my rewrite:

desc "Generate a maintenance.html to disable requests to the application."
deploy.web.task :disable, :roles => :web do
  remote_path = "#{shared_path}/system/maintenance.html"
  on_rollback { run "rm #{remote_path}" }
  template = File.read(disable_template)
  deadline, reason = ENV["UNTIL"], ENV["REASON"]
  maintenance = ERB.new(template).result(binding)
  put maintenance, "#{remote_path}", :mode => 0644
end

desc "Re-enable the web server by deleting any maintenance file."
deploy.web.task :enable, :roles => :web do
  run "rm #{shared_path}/system/maintenance.html"
end

Using events

Like the before and after filters in Rails, you can now cleanly chain together tasks. I’m a sucker for one-line solutions and these are really so simple that it makes my heart bleed:

before "deploy:restart", "fix:permissions"
before "deploy:migrate", "db:backup"
after "deploy:symlink", "deploy:cleanup"
after "deploy:update_code", "deploy:web:disable"
after "deploy:restart", "deploy:web:enable"

capistrano-ext & multistage

I highly recommend the use of multistage. It comes with the capistrano-ext gem (which has been upgraded to Capistrano 2.0, of course).

Basically, it separates the concerns of different deployments. If, like me, you like having a few other versions of your application out there, like a staging area, a testing area for bleeding edge features, and, of course, the production site, separating these in Capistrano before 2.0 was very irritating. Multistage sorts that out very nicely.

By default, you must specify the stage you wish to deploy. This behaviour can be overridden by setting the default_stage variable, but I like being explicit. This is what using stages looks like:

# cap production deploy

If you don’t provide ‘production’, it’ll complain and abort.

Using multistage is dead easy. Put this at the top of your deploy.rb:

  require 'capistrano/ext/multistage'
  set :stages, %w(staging production testing)

Run the task for generating your stage deploy files:

projroot# cap multistage:prepare

This will create a recipe file for each stage in a new config/deploy directory (exactly like Rails environments). Now, in each stage recipe, add all of your stage-specific tasks and variables. For example:

set :rails_env, "stage"
set :application, "staging.example.com"
set :deploy_to, "/var/www/#{application}"

Now switching between different deployments is a breeze. Just make a new recipe file for it with the necessary variables and you’re set.

Great Plugin for Facebook Apps

Posted about 7 years back at Liverail - Home

If you’ve been working through the Facebook/Rails tutorials you might find this plugin useful.

Facebook on Rails is a sexy plugin for developing Facebook apps

It adds some useful functions to Rails for creating a Facebook application.

acts_as_fb_user


class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.column :uid, :integer, :null => false
      t.column :session_key, :string
    end

    add_index :users, :uid, :unique
  end

  def self.down
    drop_table :users
  end
end

class User < ActiveRecord::Base
  acts_as_fb_user

  def self.import(fbsession)
    user = self.find_or_initialize_by_uid(fbsession.session_user_id)

    # Assumes session_key never expires
    if fbsession.session_key != user.session_key
      user.session_key = fbsession.session_key
      user.save!
    end

    return user
  end
end


you can now do things with the user object such as get a user’s friends


>> u = User.find(1)
=> #<User:...>
>> u.friends
=> [1, 2, 3]

FBMLController

You can create FBMLControllers such as


class ApplicationController < Facebook::FBMLController
  before_filter :require_facebook_install
  before_filter :import_user

  private
  def import_user
    @user = User.import(fbsession)
  end
end

Although I still feel this doesnt need to be inherited and such just extend the ApplicationController.

API Calls.

Are now easier, no need to parse the Hpricot XML. And also you can use the fbsession in the Model objects (where it belongs)


class MyController < Facebook::FBMLController
  def friends
    @me         = Facebook::Users.get_info(fbsession.session_user_id, ['first_name', 'last_name'])
    @first_name = @me.first_name
    @last_name  = @me.last_name
    @friends    = Facebook::Friends.get
  end
end

Notifications like ActionMailer


class StampNotificationPublisher < Facebook::NotificationPublisher
  def stamp(friends)
    @to_ids = friends.map(&:uid)
    @text   = "just stamped on you" 
  end
end

I advise you check it out if you plan to write any applications for Facebook.

Great Plugin for Facebook Apps

Posted about 7 years back at Liverail - Home

If you’ve been working through the Facebook/Rails tutorials you might find this plugin useful.

Facebook on Rails is a sexy plugin for developing Facebook apps

It adds some useful functions to Rails for creating a Facebook application.

acts_as_fb_user


class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.column :uid, :integer, :null => false
      t.column :session_key, :string
    end

    add_index :users, :uid, :unique
  end

  def self.down
    drop_table :users
  end
end

class User < ActiveRecord::Base
  acts_as_fb_user

  def self.import(fbsession)
    user = self.find_or_initialize_by_uid(fbsession.session_user_id)

    # Assumes session_key never expires
    if fbsession.session_key != user.session_key
      user.session_key = fbsession.session_key
      user.save!
    end

    return user
  end
end


you can now do things with the user object such as get a user’s friends


>> u = User.find(1)
=> #<User:...>
>> u.friends
=> [1, 2, 3]

FBMLController

You can create FBMLControllers such as


class ApplicationController < Facebook::FBMLController
  before_filter :require_facebook_install
  before_filter :import_user

  private
  def import_user
    @user = User.import(fbsession)
  end
end

Although I still feel this doesnt need to be inherited and such just extend the ApplicationController.

API Calls.

Are now easier, no need to parse the Hpricot XML. And also you can use the fbsession in the Model objects (where it belongs)


class MyController < Facebook::FBMLController
  def friends
    @me         = Facebook::Users.get_info(fbsession.session_user_id, ['first_name', 'last_name'])
    @first_name = @me.first_name
    @last_name  = @me.last_name
    @friends    = Facebook::Friends.get
  end
end

Notifications like ActionMailer


class StampNotificationPublisher < Facebook::NotificationPublisher
  def stamp(friends)
    @to_ids = friends.map(&:uid)
    @text   = "just stamped on you" 
  end
end

I advise you check it out if you plan to write any applications for Facebook.

Episode 63: Model Name in URL

Posted about 7 years back at Railscasts

By default, Rails uses the model's id in the URL. What if you want to use the name of the model instead? You can change this behavior by overriding the to_param method in the model. Watch this episode for details.

Refactoring by Martin Fowler - Developer must have

Posted about 7 years back at work.rowanhick.com

Late last year I was spending a lot of time on trains between T.O and Montreal, on one trip I picked up this book and was thoroughly engrossed - Refactoring - Martin Fowler is one of those simply must-have books on any developers bookshelf. Of all technical books I've found it to be the one that actually compels you to be a better programmer. The first chunk of the book is dedicated to whats, whys, testing etc of how you should turn your mish-mash of spaghetti code into beautiful elegant world class code, the rest of the book is dedicated to a catalog of various examples of refactorings. Each refactoring is structured with a small class diagram, theory about why you want to do it, then a detailed walk through of the steps written to get there. Well written, most of them are a doddle to understand. Even though the book uses examples in Java, they equally can apply for your Ruby, PHP, Actionscript code or whatever else tickles your fancy. If you want to change from a programmer to a code artisan, this is the book for you. If not we'll leave you alone with your unmaintainable spaghetti code. Some of the refactorings are obvious, and some the light switches on and you go 'a-ha'. Certainly if I'd have had this book from day 1 many moons ago I would've been a much happier chappy. I know using principles in the book I came away refactoring a working but messy piece of code days after reading it - the principles learned in the book made it a lot easier and quicker to do. One big personal improvement I made was towards not being afraid of breaking up functions for readability e.g. like so: class MyClass def able_to_checkout if ( ugly_condition_1 == a && ugly_condition_2 == c && you_get_the_picture ) self.set_book_to_checked_out end end (guilty as charged) to the following: class MyClass def able_to_checkout if ( no_books_checked_out? ) self.set_book_to_checked_out end end def no_books_checked_out? ugly_condition_1 == a && ugly_condition_2 == c && you_get_the_picture end end To round off the book, it's a hard cover with a little red cloth tape bookmarker. What other technical book have you seen with that in recent history ? It's been designed to stay on your shelf for a very long time - unlike some faded examples gathering cobwebs on mine. A rare timeless classic ? Quite possibly. Go out and buy it today if you haven't already. Another 10 | 10

How do you process literature?

Posted about 7 years back at Saaien Tist

A quick glance at the side of my desk reveals two stacks of manuscripts to read; each stack about 20cm high. Sounds familiar? There seems to be a major task in front of me to process all that.
First thing to do is to identify what caused those piles in the first place. The answer: no system that I'm satisfied with for reference management. Of course, there is software like Reference Manager and EndNote as well as websites like Connotea and CiteULike. But they all have one major flaw: they are not suited to store the knowledge gained from those papers. Entering a reference to those papers in the software is not the same as going through them and extracting useful information. Sure, they do have a notes field where you can jot down some short remarks, but often knowledge is much easier recorded and remembered in little graphs and pictures than in words. There's reference management, and there's knowledge management.

What do I want my system to look like? First of all, it should be searchable. The tagging system provided by CiteULike/Connotea seems good for that. Also (and this might seem illogical for a bioinformatician), the system should not be fully automatic or even electronic, but analog. Why? Just pressing a button to for example add the abstract from a paper to the system gives a sense of... what's the word in English: volatility? For some things you should use the help of a computer, and for some you shouldn't. There's a difference between using Excel to repeat the same calculation 50 times, and trying to use a pc for storing knowledge. It's me who needs to store that knowledge, not the computer. If that was the case, I could always go back to Google instead of making the effort of using a reference manager in the first place. I've played around with zotero and personal wikis in the past, and they just didn't do the trick: I still ended up just copy-pasting the information instead of absorbing it.

Another advantage of using an analog system, is that when you feel your productivity behind your computer is suboptimal, you can always take your cards, find yourself a quiet place, put your feet on a desk, and flick through the things you wrote down. Slippers and pipe are optional.

During my PhD a few years ago, I used a system that was exclusively based on index cards. The inspiration came from Umberto Eco's book "Come si fa una tesi di laurea" (Or "How to make a doctoral thesis") (1977) in which he explains how he handles the knowledge for his book research. For each manuscript, I'd make a new card. The front contained an identifier, the paper title, full reference and keywords. On the back I'd write down what I had to remember from that paper, including little graphs, schemas and stuff. I've got to admit that a drawback of using these cards was that they were not easily searchable, but linking them worked quite well with a bit of discipline.
During those years, I used the index card system both as reference manager and as knowledgebase. Although it did work to satisfaction, the role of reference manager should be fulfilled by a better tool.

Now how could I implement something like that into a workflow? Basically, any new paper to be read should be entered in CiteULike and tagged as 'to_read'. When I've got time to read it: see if it's necessary to print out, or preferably read from the screen (we want to be nice to the trees, don't we?). When I've read the manuscript and there is interesting information to remember, only then create an index card. In case it's a landmark paper and/or I've been adding a lot of comments and markings in the text: keep the printout as well, and mark the index card that I've got that printout as well.
Let's try this out for a few weeks and see where it goes...

BTW: for a knowledgebase system based on index cards taken to the extreme, see PoIC (Pile of Index Cards).

Episode 62: Hacking ActiveRecord

Posted about 7 years back at Railscasts

Have you ever wanted to temporarily disable all validations? Well, ActiveRecord doesn't support this, but that doesn't mean we can't add it. This episode will show you how to open up an existing class and change its behavior.

Impressed With Comatose CMS

Posted about 7 years back at zerosum dirt(nap) - Home

Often after I’m finished building the bulk of a web app, I find there are some secondary pages that need to be built. These pages are largely informational, such as an about page, a contact page, an FAQ, etc. They’re relatively static in terms of the content, but it’s always nice if we can supply our client (or ourselves) with a nice CMS-style interface to make updating them easy, and within the context of our existing application layouts. Keep it simple, keep it DRY.

The obvious thing is to cook up some sort of PagesController from scratch. This is nice because it’ll make use of your existing facilities, your authentication/authorization system, layouts, etc. It is custom, after all, and a custom fit is almost always the best fit. But it’s a fair bit of work for something that’s probably not ‘core’ to the application, and takes cycles away from other places they could be better spent.

On the other hand, you can integrate with a 3rd-party CMS or blogging package like Typo, Radiant CMS, or Mephisto. They’re all great packages and do what they do really well. The downside is you’ve got to write a fair amount of glue to hook everything together and make it look (and feel) uniform.

Another option is to use Matt McCray’s Comatose plugin, a micro CMS. It’s got all the basic functionality you want for this sort of stuff out of the box and it couldn’t be much easier to use. The real bonus is integration is almost completely seemless, which makes it (imho) the best of both worlds for this sort of project.

Installing the plugin gets you a ComatoseController and a ComatoseAdminController. You add an entry (or multiple entries, if you like) in your routes file to tell your application when to invoke the ComatoseController. You might prefer a scheme where all URLs starting with /pages are passed to Comatose, for example. Then you log into the admin controller (which also needs an entry in routes) to create the pages. All the basic management tools we need are here; pages are organized hierarchically and can be edited with great ease, using a variety of markup filters. Each page gets a number of attributes, including a title, keywords, author, etc.

Basically it’s everything we need for the bare-minimum no-frills CMS experience and nothing we don’t. Which is just the way I like it. Check it out for your next project.

UPDATE

Anyone having issues with Comatose and authentication should check out this bug report. If you’re specifying an alternate session key, you should put it in environment.rb instead of ApplicationController.

ActionController::Base.session_options[:session_key] = "_your_custom_session_id"

Comatose controllers inherit directly from ActionController::Base instead of from your application controller. So if you specify the session key in application.rb, the Comatose-driven sections of your app will be blissfully unaware of it. This means a method like logged_in? (which checks the session for your login status) will always report back as false.

Episode 61: Sending Email

Posted about 7 years back at Railscasts

This is a brief guide to sending email in Rails. See how to configure the environment, generate a mailer, create a template, and deliver the mail.

XChain - it has a name, license, and home.

Posted about 7 years back at work.rowanhick.com

The open source Rails/Flex eCommerce application now has a name - XChain - pronounced cross-chain. I had some air travel time over the weekend and put it to good use coming up with a name, the basic premise being that the app should really be classified as a Supply Chain Management system as it deals with a lot more than simply taking peoples money for a product. (Order fulfillment, shipment tracking, eventually CRM and inventory management), and being a cross of two major technologies it seems to fit. Catchy enough and has meaning. Well I think so anyway, others might disagree - (that's what the comments form at the bottom is for...), only downer is XChain.com is taken by some spammer, but I've snapped up .ca and other appropriate domains. To this end, I've also created a home for it here http://code.google.com/p/xchain/ which seems to be a good location for now, satisfies the free and accessible by SVN requirements. Alas no RSS feed, so stick to here for the updates. I'm not a lawyer by any stretch, and have to a little more digging, but have basically decided on a license for it. The Mozilla Public License. My wish is that anyone will be able to use it for either non-commercial and commercial applications free of charge. The only restriction is if you extend it, you have to provide source code back to the community. I believe this is fair enough as you will be getting a tonne of usable code out of the box to start with. I just need to check that we can provide mechanisms for companies sensitive proprietary processes - to make sure these can be wrapped up in a separate lib, or DSL stored in the db, to make sure that doesn't need to be opened up to the outside world. Final decision of the day is to go with Cairngorm - this has more exposure so will hopefully appeal to a wider base of developers, and seems more suited to the scale of this application. I also found a Cairngorm Rails code generator via onrails.org which looks like it will do the business saving time generating code. Right, time to get some code into that repository.... in the meantime feel free to let me know your thoughts on the name and license choice.

New DRYML - Part 1

Posted about 7 years back at The Hobo Blog

As I’ve mentioned a few times, there’s lot of breaking changes in the “new DRYML”. In some ways there’s not a huge amount of new functionality, but we really feel it’s much cleaner and more elegant now. I’ll go over the new features in this and probably one or two further posts.

If you want to try any of this out, Hobo 0.6-pre1 has been tagged in the repository:

  • svn://hobocentral.net/hobo/tags/rel_0.6-pre1

It’s just a preview though and you’ll likely encounter bugs. We won’t we updating the website or releasing a gem.

Changes to current features

Let’s start by working through some features from the perspective of changing an app to work with the new DRYML.

A bunch of names changes

The hobolib directory (app/views/hobolib) is now taglibs. We wanted to make Hobo feel less like an add-on and more integrated.

<taglib> is now <include>

The part_id attribute for creating ajax parts is now simply part. Hopefully this will help avoid some confusion about the different roles in the ajax mechanism of part names and DOM IDs.

The xattrs attribute for adding a hash-full of attributes to a tag in one go is now merge_attrs.

Code attributes

Code attributes are now signified with & instead of a #, so for example:

<if q="&logged_in">

Instead of

<if q="#logged_in">

The reason for the change is that you can now use #{...} at the start of an attribute, e.g.:

<button label="#{name} is my name" />

field and with instead of attr and obj

To set the context to some field of the current context you now say field="..." instead of attr="...". You can also use a new shorthand:

<repeat:comments> ... </repeat>

Notice the :comments part is missing from the close tag (that’s optional).

To set the context to any value, use with="&..." instead of obj="#..."

Bye bye parameter tags, hello templates

Parameter tags used to offer an alternate syntax to attributes for passing parameters to tags, so

<page title="My Page"/>

Was the same as

<page><:title>My Page</:title></page>

It looks great in a simple example like that, but in practice this feature was getting messy. Looking at some DRYML code, it was far from obvious why you’d be using a <:parameter_tag> in one place and a <normal_tag> in another. And what happened when you had a tag-body and parameter tags? That was even messier. And what about inner tags? Are they another name for parameter tags or something different? And then there was the mysterious content_option and replace_option. Which one should I use? Why?

So now there are no parameter tags, and instead there are template tags. Templates are a new kind of tag you can define:

  • They are distinguished form normal tags because the name is in <CamelCase>
  • They don’t have a tag-body. You never user <tagbody> in a template definition
  • Templates have attributes like regular defined tags. They also have parameters
  • A parameter is a section of content that the caller of the template can augment or replace
  • You create a parameter by adding the param attribute to any tag inside the template

Here’s an example:

<def tag="Page">
  <html>
    <head param="head">
      <title param="title" />
    </head>
    <body param="body">
      <div class="header" param="header" />
      <div class="main" param="main" />
      <div class="footer" param="footer" />
    </body>
  </html>
</def>

(note: it’s quite common that the parameter name is the same as the tag name, as in <head param="head">, in this case you can omit the parameter name, e.g. <head param>)

When calling this template, you can provide content and attributes for any of thed parameters. You can also append and prepend to parameters, or even replace parameters entirely:

<Page>
  <title>My Page</title>
  <head.append>
    <script src="..."/>
  </head.append>
  <body onclick="runMyScript()"/>
  <header>
    ...my header...
  </header>
  <main>
    ...my content...
  </main>
  <footer.replace/>
</Page>

To explain what’s going on in terms of “old DRYML”, it’s as if every child of <page> is a parameter tag. <title>, <head>, <body> etc. are neither defined tags or plain HTML tags. They are template parameters. The attributes and content of these tags are passed to the template and appear in the appropriate places.

Parameters can be called with various modifiers. In the above example we see <head.append>, which adds a script tag to the head section, and <footer> which replaces the footer entirely – in this case with nothing at all, so the footer is simply removed. The full set of these modifiers is:

  • append: append content to the body of the parameter
  • prepend: prepend content to the body of the parameter
  • before: insert content just before the parameter
  • after: insert content just after the parameter
  • replace: replace the parameter entirely

The power really kicks in with the fact that you can nest parameters, but I think that will have to go in part 2, along with local tags, control attributes and a few other bits and bobs…

New DRYML - Part 1

Posted about 7 years back at The Hobo Blog

As I’ve mentioned a few times, there’s lot of breaking changes in the “new DRYML”. In some ways there’s not a huge amount of new functionality, but we really feel it’s much cleaner and more elegant now. I’ll go over the new features in this and probably one or two further posts.

If you want to try any of this out, Hobo 0.6-pre1 has been tagged in the repository:

  • svn://hobocentral.net/hobo/tags/rel_0.6-pre1

It’s just a preview though and you’ll likely encounter bugs. We won’t we updating the website or releasing a gem.

Changes to current features

Let’s start by working through some features from the perspective of changing an app to work with the new DRYML.

A bunch of names changes

The hobolib directory (app/views/hobolib) is now taglibs. We wanted to make Hobo feel less like an add-on and more integrated.

<taglib> is now <include>

The part_id attribute for creating ajax parts is now simply part. Hopefully this will help avoid some confusion about the different roles in the ajax mechanism of part names and DOM IDs.

The xattrs attribute for adding a hash-full of attributes to a tag in one go is now merge_attrs.

Code attributes

Code attributes are now signified with & instead of a #, so for example:

<if q="&logged_in">

Instead of

<if q="#logged_in">

The reason for the change is that you can now use #{...} at the start of an attribute, e.g.:

<button label="#{name} is my name" />

field and with instead of attr and obj

To set the context to some field of the current context you now say field="..." instead of attr="...". You can also use a new shorthand:

<repeat:comments> ... </repeat>

Notice the :comments part is missing from the close tag (that’s optional).

To set the context to any value, use with="&..." instead of obj="#..."

Bye bye parameter tags, hello templates

Parameter tags used to offer an alternate syntax to attributes for passing parameters to tags, so

<page title="My Page"/>

Was the same as

<page><:title>My Page</:title></page>

It looks great in a simple example like that, but in practice this feature was getting messy. Looking at some DRYML code, it was far from obvious why you’d be using a <:parameter_tag> in one place and a <normal_tag> in another. And what happened when you had a tag-body and parameter tags? That was even messier. And what about inner tags? Are they another name for parameter tags or something different? And then there was the mysterious content_option and replace_option. Which one should I use? Why?

So now there are no parameter tags, and instead there are template tags. Templates are a new kind of tag you can define:

  • They are distinguished form normal tags because the name is in <CamelCase>
  • They don’t have a tag-body. You never user <tagbody> in a template definition
  • Templates have attributes like regular defined tags. They also have parameters
  • A parameter is a section of content that the caller of the template can augment or replace
  • You create a parameter by adding the param attribute to any tag inside the template

Here’s an example:

<def tag="Page">
  <html>
    <head param="head">
      <title param="title" />
    </head>
    <body param="body">
      <div class="header" param="header" />
      <div class="main" param="main" />
      <div class="footer" param="footer" />
    </body>
  </html>
</def>

(note: it’s quite common that the parameter name is the same as the tag name, as in <head param="head">, in this case you can omit the parameter name, e.g. <head param>)

When calling this template, you can provide content and attributes for any of thed parameters. You can also append and prepend to parameters, or even replace parameters entirely:

<Page>
  <title>My Page</title>
  <head.append>
    <script src="..."/>
  </head.append>
  <body onclick="runMyScript()"/>
  <header>
    ...my header...
  </header>
  <main>
    ...my content...
  </main>
  <footer.replace/>
</Page>

To explain what’s going on in terms of “old DRYML”, it’s as if every child of <page> is a parameter tag. <title>, <head>, <body> etc. are neither defined tags or plain HTML tags. They are template parameters. The attributes and content of these tags are passed to the template and appear in the appropriate places.

Parameters can be called with various modifiers. In the above example we see <head.append>, which adds a script tag to the head section, and <footer> which replaces the footer entirely – in this case with nothing at all, so the footer is simply removed. The full set of these modifiers is:

  • append: append content to the body of the parameter
  • prepend: prepend content to the body of the parameter
  • before: insert content just before the parameter
  • after: insert content just after the parameter
  • replace: replace the parameter entirely

The power really kicks in with the fact that you can nest parameters, but I think that will have to go in part 2, along with local tags, control attributes and a few other bits and bobs…

Episode 60: Testing without Fixtures

Posted about 7 years back at Railscasts

Tests which rely heavily on fixtures are brittle and can be difficult to maintain. This episode will show a couple techniques for creating tests which don't use fixtures.

Essential Actionscript 3 - Essential !

Posted about 7 years back at work.rowanhick.com

The great chapters.ca boat sailed into port - last week Essential Actionscript 3.0 by Colin Moock arrived on my doorstop. First impressions this is by far the biggest tech book to grace my shelves. 900+ pages worth, it dwarfs O'Reillys recently released Programming Flex 2 book. This book really does cover everything from general programming skills to the nitty gritty of E4X useage. The work that has gone into this book by Mr Moock shows. Approximately the first ~350 pages of the book is devoted to Core Actionscript & OOP principles in general, the second half Flash/Flex features such as XML, Drawing API, Security etc. Coupled with the Programming Flex 2 book I really think that's all you need for your bookshelf. My learning style is to learn by example (I skim read text - but thoroughly read code to understand) which is covered off really well, the vast majority of pages have a short code fragment or diagram to complement the text along with longer full code examples where applicable. Essential AS3 has depth to each and every topic, the ones I've read thus far anyway, going through example after example illustrating different facets of the topic - the XML chapter was particularly impressive. Too often you read a book and feel like you have to go back to the great Google Gods to discover more, whereas with this book I feel like that's all I need right there. All in all, the best tech book I've purchased (even over the famous Agile Web Development with Rails book). Value for money can't be beat, cost me about $55CAD to my doorstep - and illustrates how thankful I am living in Canada now, after being used to New Zealand book prices! It's already taken pride of place by the keyboard as I'm working on our new widget seller solution. 10|10

Low Pro Behaviours 101: Part 2

Posted about 7 years back at danwebb.net - Home

In the first post I briefly explained how to use pre-made Low Pro behaviours but, although I’m in the process of writing a few myself, Low Pro is not going to be a widget library – what it is is a great framework to write your own components with. So, in this post, I’m going to go into a little detail about how to write your own behaviours. If the idea of that doesn’t bore your rigid then read on…

Creating a behaviour

As discussed in the last post behaviours are actually just specialised constructor functions. So, to create our behaviour we use Behavior.create in a very similar way to Class.create:

var Hover = Behavior.create();

Adding methods and properties

This creates an empty behaviour much the same as Class.create gives us an empty class. Now we add our methods on to the prototype of the constructor that we’ve created. This example is a super simple behaviour, Hover, that will add/remove a class name (which you can specify) on mouse over/out:

Object.extend(Hover.prototype, {
  initialize: function(className) {
    this.className = className || 'over';
  },
  onmouseover: function() {
    this.element.addClassName(this.className);
  },
  onmouseout: function() {
    this.element.removeClassName(this.className);
  }
});

Any on* methods are bound as event handlers to the element when the behavior is attached to the element. The scope of these methods is ‘corrected’ automatically so that this will always refer to the behaviour instance. The behaviour instance also has a magic property, this.element, which points to the element it is attached to. The final thing you need to know is that the initialize method is called as soon as the DOM is ready (as soon as the element is available). We can now use this behaviour in the manner discussed in the last post:

Event.addBehavior({
  '.dongle': Hover('hover')
});

Aside from these special cases behaviour constructors are identical to any regular JavaScript ‘class’. You can add methods and properties as you see fit. Note that each element that has the behaviour attached to it gets its own instance of the behaviour so you can maintain the state of each behaviour independently without having to resort to setting expandos on the element, using closures or any other method which is messy and prone to causing those nasty circular references that cause memory leaks. As an alternative you can just pass your methods straight into the Behavior.create call so the following is equivilent to the above code:

var Hover = Behavior.create({
  initialize: function(className) {
    this.className = className || 'over';
  },
  onmouseover: function() {
    this.element.addClassName(this.className);
  },
  onmouseout: function() {
    this.element.removeClassName(this.className);
  }
});

Working with multiple elements

Now this is all good for dealing with behaviours that work on a single element but in many cases we want a behaviour to operate on a number of elements. For example, you would want to be able to attach a Sortable behaviour to a list element but the behaviour itself would also need to deal with all the list element inside it. There are a number of ways to approach writing these kind of behaviours, all of which are demonstrated in the various test behaviours I’ve written.

Event delegation with behaviours

The first technique, and normally the best is using event delegation to capture all the events on elements inside the attached element with your behaviour and process them. The process is pretty simple…here’s part of the Calendar behaviour:

var Calendar = Behavior.create({
  // other methods hidden for clarity
  onclick : function(e) {
    var source = Event.element(e);
    Event.stop(e);

    if ($(source.parentNode).hasClassName('day')) return this._setDate(source);
    if ($(source.parentNode).hasClassName('back')) return this._backMonth();
    if ($(source.parentNode).hasClassName('forward')) return this._forwardMonth();
  }
});

Here, we define a single onclick method which will capture clicks on all the elements inside the calendar – Forward and back arrows, and the dates themselves. Firstly, we use Event.element to grab the source element, the element that was actually clicked, then we can just examine this element to work out what needs to happen to the calendar and call the relevent method. In this case, and in most cases, the most convenient way is to look at what class names the element has. In the calendar, each day has the class ‘day’ and the forward/back arrows have the classes ‘forward’ and ‘back’. This method is really nice for a number of reasons, firstly, we avoid attaching lots of event handlers for each sub element and secondly we have this central point where we can handle and dispatch events – a really pleasant way to work with complex interactions. Of course, event delegation isn’t always a good fit so…

Linking behaviours

In more complex cases when the sub elements of your behaviour need to maintain their own state or handle events in a more complex way you can have your main behaviour attach sub-behaviours to inner elements during initialisation and maintain a link between the two. An example of this can be seen in the Draggable behaviour:

Draggable = Behavior.create({
  initialize : function(options) {
    // code hidden for clarity
    this.handle = this.options.handle || this.element;
    new Draggable.Handle(this.handle, this);
  }
  // code hidden for clarity
});

Draggable.Handle = Behavior.create({
  initialize : function(draggable) {
    this.draggable = draggable;
  },
  onmousedown : function(e) {
        // code hidden for clarity
  }
});

Here, the initialize method of Draggable finds the element that it wants to be the ‘drag handle’ and attaches another behaviour, Draggable.Handle, to it. At this point we pass a reference to the Draggable instance to the Draggable.Handle instance so the drag handle can refer back to and control the main draggable behaviour. You can of course, if necessary, build up a complex component by building a number of linked behaviours that all comunicate back to the main behaviour.

Get it? Got it? Good

So that’s all for now. Any questions just drop me a comment and I’ll get back to you ASAP. At this point, if you are interested in writing your own behaviours then it would be worth referring to the behaviours in SVN. However, I’m just feeling this out for myself and I’m sure I’ve not explored any near all of the possibilities of working with behaviours so if you have any brain waves be sure to post a comment also. If there’s enough interest I might include a behaviours repository on the upcoming Low Pro site.