Blog Package Ponderings

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

Drupal has served me pretty well for a number of projects in the past. But as we shift our development focus towards Ruby-based projects, it seems like an ideal time to consider migrating my own blogging platform to something Rails-driven. Nothing against Drupal itself of course. Hell, for a PHP project it’s pretty slick.

But it still just leaves me feeling like I’m flirting with an old (and somewhat unattractive) ex-girlfriend. It’s not you, it’s me.

The obvious candidates seem to be Typo and Mephisto. Another option would be to, of course, roll my own. But does the world really need another half-baked blogging engine? Probably not. If anyone has other recommendations let me know. Looks like I’m leaning towards Mephisto at this point.

Hobo 0.4.3

Posted about 7 years back at The Hobo Blog

May we present, for your pleasure, Hobo version 0.4.3

* hobo-0.4.3.gem

* Change Log

Let’s see… what to tell you about the new stuff? There’s a nice little DSL for integration tests. Most of the goodness is already there with Rails (See Jamis Buck’s blog post). I’ve just added a few convenient methods for testing basic stuff like creating and viewing objects. Here’s a snippet from a test of the POD demo:

def test_user_creating
  fred = fred_session
  new_ad = fred.creates_and_visits(Advert, 
                                 :title => "my car",
                                 :body => "is a nice car",
                                 :category => cars)
  fred.sees new_ad.title
  fred.sees new_ad.body

  fred.cant_create(User, :username => "Jim")
  fred.cant_create(Category,
                   :name => "small furry creatures")
end

Neat eh?

Enjoy.

Hobo 0.4.3

Posted about 7 years back at The Hobo Blog

May we present, for your pleasure, Hobo version 0.4.3

* hobo-0.4.3.gem

* Change Log

Let’s see… what to tell you about the new stuff? There’s a nice little DSL for integration tests. Most of the goodness is already there with Rails (See Jamis Buck’s blog post). I’ve just added a few convenient methods for testing basic stuff like creating and viewing objects. Here’s a snippet from a test of the POD demo:

def test_user_creating
  fred = fred_session
  new_ad = fred.creates_and_visits(Advert, 
                                 :title => "my car",
                                 :body => "is a nice car",
                                 :category => cars)
  fred.sees new_ad.title
  fred.sees new_ad.body

  fred.cant_create(User, :username => "Jim")
  fred.cant_create(Category,
                   :name => "small furry creatures")
end

Neat eh?

Enjoy.

Shysters

Posted about 7 years back at Ryan Tomayko's Writings

Tim Bray’s take on the Microsoft/Wikipedia mess is enlightening but this bit at the end blew my mind:

Netscape hired me to represent their interests, and when I announced this, controversy ensued. Which is a nice way of saying that Microsoft went berserk; tried unsuccessfully to get me fired as co-editor, and then launched a vicious, deeply personal extended attack in which they tried to destroy my career and took lethal action against a small struggling company because my wife worked there. It was a sideshow of a sideshow of the great campaign to bury Netscape and I’m sure the executives have forgotten; but I haven’t.

Wow.

Where I come from we have a word for this kind of stuff: shystie. It’s not a label applied carelessly and once applied it’s almost impossible to shake because it means you cannot be trusted.

You don’t associate with shysters. You don’t try to help or understand them. You stay away.

Shystiness is a terminal disease.

I think this gets to the root of my issue with the recent round of smart and reputable people going to Microsoft. Ozzie, Hugunin, Udell: all insanely smart and respectable individuals. I want to like that company again, I really do, but they’re shystie. It’s a deal breaker.

EDIT: I felt bad after posting this. I'm not sure why because I feel pretty strongly about the sentiment. At any rate, this comment from Mike Champion, one of the folks at MS I have a large amount of respect for, balances out my cynicism a bit:

Finally, on “Which is a nice way of saying that Microsoft went berserk”: To be frank, I watched that episode 10 years ago with horror, and had my own issues with some Microsoft people and the rather arrogant corporate culture back in the ‘90s too. But things change … I guess the perpetrators are now retired and living off their stock options proceeds. Life is unfair, but it goes on, the lawyers move in, and I'm quite sure that that kind of thing wouldn’t happen today. Give MS credit for one thing: they don’t hire dummies (well, maybe I'm an exception) and smart people learn from their mistakes.

Clearly, the shystiness at MS is not a trait shared by everyone. The good guys need to find a way to get out in front of the shysters in a big way.

Bha. I'm breaking my own rules now.

What is Hobo?

Posted about 7 years back at The Hobo Blog

There’s a fair few reactions to Hobo out there on the big wide Internets by now, and it’s interesting to see people’s interpretations. I suppose it’s pretty obvious that people are going to jump to conclusions when I’ve only given a brief glimpse of what Hobo is about. I just wanted to take a quick moment to clear a few things up. Update: this turned from a “quick moment” into a fairly comprehensive overview of what Hobo can do :-)

The main point here is this - Hobo is nothing but extensions to Rails! There’s nothing that Rails can do that Hobo can’t. I’m not saying that Hobo will be to everyone’s taste - of course you may prefer Rails as it is. I’m just making the point that Hobo only adds to Rails, it doesn’t take anything away. Perhaps it’s the slightly “magic” feel to the POD screencast – I can see that the screencast might leave some people thinking they’d rather build the app themselves and have control over everything. So I guess I’m really just making the point that you do have control over everything, in just as direct a manner as you do in Rails without Hobo.

Hobo does do more than your average plugin though – it’s kind of like several plugins rolled into one. Inevitably people are going to be interested in having those features as separate plugins – a few people have asked for DRYML by itself already. But there are a bunch of dependencies between the different features, and to be honest I won’t know exactly where things can be separated until Hobo matures a bit.

So, for now at least, I’ve taken a different approach - you install all these features at once by installing Hobo, but you use only those features you want to. If you want the whole “web app builder” thing, then you’ll end up using most or all of them, but if you just want DRYML? Not a problem, the rest of Hobo won’t get in your way. If you later see that you could also benefit from, say, the ajax-mechanism, fine – just start using it.

So perhaps a quick tour of what these features are would be in order :-)

DRYML

This is really the heart of Hobo – it all started with DRYML. There’s a few posts on this already of course - have a look in the documentation category. DRYML consists of the templating mechanism itself, as well as a “core” tag library, with the basic things like loops and conditionals.

Ajax Rendering

Building on DRYML, this is the ability to mark a section of your page as a “part”. Having done this, Hobo will track the object that was in context when the part was rendered, and can re-render the part using the new state of that object when requested. This mechanism can be used by itself, but works best in combination with the Hobo Rapid tag library, which lets you write very simple stuff like

<delete_button update="number_of_users"/>

and the number of users will automatically change to reflect the deletion.

Right now using the Ajax mechanism without also buying into Hobo Rapid is kind of a pain. Some extra work to smooth that out is in order. Perhaps some regular Rails helpers.

Hobo Rapid Tag Library

This is where things get groovy. A tag library is basically just like a load of Rails helpers, but as DRYML tags instead of methods. Hobo Rapid contains the Hobo equivalent of link helpers, form helpers, ajax helpers, and pagination helpers. There’s also some “scaffold-like” tags for default pages, and support for navigation bars.

This library is expected to grow!

ActiveRecord Permission System

This appears prominently in the POD screencast. At it’s heart it’s just a simple convention for declaring who’s allowed to do what to your models (create, update, delete and view). The permissions come into effect in two places: in customising the views, and in validating http requests.

View customisation is provided in the tag library. The output of various tags is dependent on permissions. For example the <edit> tag will automatically become a read-only view if the current user does not have edit permission.

Validation of web requests is done in Hobo’s generic model controller (see below). If the request, be it a view, a create, an update or a delete (http get/post/put/delete) is not permitted for the current user, it will be rejected.

Fairly simple but useful. Models can declare which columns are searchable (there are sensible defaults of course!) and Hobo provides both server and client-side support for a nice ajaxified search that finds many types of model from a single search page.

Switchable Themes

A Hobo theme consists of public assets such as a stylesheet and images, and some tag definitions. The tags define the basic HTML structure of the various theme elements - the overall page, header and footer, navigation bar, sidebars, panels (boxed sections within the page) etc. Themes are switchable by changing a configuration variable. All the variable does is determine the paths used to find the tag definitions (app/views/hobolib/themes/theme-name) and the public assets (public/hobothemes/theme-name).

User Management (Acts As Authenticated)

In order for the permission system to work, a user model must be present. For that reason we decided to go ahead and include AAA in Hobo. It’s been tweaked a bit – the controller has been merged with Hobo’s “front” controller (so called because it gives you your front page and related pages like search, login and signup). The user model methods that are not commonly changed have been moved out into a module to keep your user model clean.

Hobo also adds the concept of a guest user, this is a pseudo model that is not stored in the database. It’s just a place to define the permissions for someone who has not logged in. One implication of this change this is that instead of testing if current_user is nil, you test for current_user.guest?.

ActiveRecord Composable Query Mechanism

It’s common practice with ActiveRecord to write query methods to capture standard queries your application needs beyond the magic find_by_thingumybob methods. A problem I ran into was that I wanted to be able to compose queries: find everything that matches this query or that one; find the first record that matches some query and some other one.

I found I needed such a feature in Hobo so I implemented the following:

Post.find(:all) { (title_contains("Hobo") | content_contains("Hobo")) &
                   is_in(news_category.posts) }
User.find(:first) { name_is("Tom") | email_is("foo@bar.com") }

Note that in the first example, the collection my_category.posts doesn’t need to be loaded - the query generates SQL and runs entirely on the database.

The query operations in those examples – *_contains, *_is and in_collection – are all built in. If you write class methods on your model that return SQL expressions you can use those in the query too.

Generic Model Controller (CRUD Support)

Hmmm - this does a fair few things. Maybe I need another cup of tea… Slurp, ahhh. Sorry where was I? Oh yeah - the model controller. To get this functionality, add this to your controller

hobo_model_controller

It’s just a short-hand for including Hobo::ModelController. You can also generate a controller which already contains this declaration (hey - every little helps!) with:

$ ./script/generate hobo_model_controller <model-name>

CRUD support

Hobo derives the model class from the controller class name, so you should follow the Rails convention of PostsController for model Post (the generator will do this for you of course). You then get the basic CRUD methods familiar from scaffolding: index, show, new, create, edit and update.

The controller also has support for your has_many and belongs_to associations. Firstly, your has_many associations get published automatically, so for example the URL

/posts/12/comments

Would map to the action show_comments, which is implemented for you. Also

/posts/12/comments/new

Will invoke the new_comment action - again it’s implemented for you. Note that the form on that page doesn’t post to /posts/12/comments but to /comments as usual. I decided it was best to have a single URL for creating a given model.

There’s also support for your associations when creating / updating models. Without going into too much detail in this overview, when you post (create) or put (update), you can set both has_many associations and belongs_to associations. You can either pass the id of an existing record, or pass entirely new records in nested parameter hashes. There’s support for all this in DRYML and Hobo Rapid, so for example if a person has an address as a separate, associated model, you can easily build a single form with fields for both the person and the associated address.

Data filters

The composable query mechanism for ActiveRecord has been described above. Data filters allow you to expose these queries to the web. This is easiest to explain with an example. Say we have people that are members of groups, and we want a page with all the people not in a particular group. Inside the people controller we define a data filter:

def_data_filter :not_in do |collection|
  not_in(collection)
end

A page with all the people not in the group with id 7 would then be available at

/people?where_not_in=group_17

Enhanced autocomplete

Rails already has support for working with the Scriptaculous auto-completer through the helper auto_complete_for (although that’s on its way out in 2.0). Hobo’s version is enhanced to work with the data filter mechanism. Say for example you wanted an auto-completer to allow you to add people to a list - you don’t want the people already in the list to be included in the completions. You would add the following to your controller:

def_data_filter :not_in do |collection|
  not_in(collection)
end

autocomplete_for :name

You would then point your auto-completer at (e.g.) /people/completions?for=name&where_not_in=list_12

Hobo Rapid has an auto-completer tag so the client side is nice and easy too.

Remote procedure calls

When DHH introduced the Simply Restful stuff, he described CRUD as an aspiration rather than a hard rule (IIRC). In other words, you shouldn’t go crazy trying to model absolutely everything as resources – there will still be “remote procedure calls” (RPC) that we post to. I hit this recently with a need for a “reset password” service on an app I’m building. (BTW - this is basically how Hobo moves forward - if I hit a need for a feature that I feel will crop up again and again, I build it into Hobo, not the app. In this case I didn’t want to build password reset into Hobo, but I did build the RPC mechanism).

The basic procedure is: write an action in your controller as normal. Add web_method <method-name>. Hobo will add a route for your method, and apply a before filter so the object in question is already available in @this. Hobo’s ajax mechanism supports updating the page with results from your method, and there’s integration into the permission system too.

Let’s see an example - the reset password method. In the controller we add:

web_method :reset_password
def reset_password
  new_password = @this.reset_password
  hobo_ajax_response(@this, :password => new_password)
end

On the model we can add a method can_call_reset_password?(user). In my case I only wanted the super-user to have access to this method so I didn’t need can_call_reset_password?.

The method will be available to HTTP posts at, e.g.

/users/21/reset_password

For the client side there’s a <remote_method_button> tag (note to self: should be called <web_method_button>?)

Alternative show methods

Simply Restful introduced the semicolon in the URL to access alternate views of the same object. So

/posts/12

Would be a ‘normal’ view of the post, while

/post/12;edit

Would give you a form to edit the post – still a view of the post, just a different one. You’ll probably find the need for additional “alternative views”, e.g. you might have a main view of a user, plus a separate “My Profile” page where users can edit details that don’t change so often, like their email address. Hobo allows you to simply say

show_method :profile

In your controller. You then create app/views/users/profile.dryml. You also get a named route person_profile so you can call person_profile_url(fred) and get the URL back.

Migration Enhancements

This is a little one, but very useful. In create_table calls, you can add columns like this

t.string :name, :subject, :limit => 50

instead of

t.column :name, :string, :limit => 50
t.column :subject, :string, :limit => 50

There’s also t.auto_dates that gives you updated_at and created_at, and

t.fkey :zip, :zap

That will give you integer columns zip_id and zap_id.

ID Names

In ActiveRecord everything has a numeric ID. It’s common however, that models also have an identifying name (e.g. a name column where every row is unique). If a model has an ID name like this, it’s nice to be able to sometimes use it instead of the numeric ID, for example in readable URLs. If your model declares hobo_model, you can also declare

id_name <column-name>

If you don’t specify a column it defaults to name. This gives you a read/write attribute id_name which is just an alias for the column in question. You also get find_by_id_name on the class.

If you are using Hobo’s model_controller you can then use names instead of IDs in your URLs, e.g. (using ID names in combination with the associations support):

/categories/News/posts

The helper object_url will generate this kind of URL too - if the object you pass supports ID names.

That’s All Folks!

That’s pretty much everything, although of course lots of detail is lacking. Oh and there’s a ton of great new stuff just around the corner of course!

What is Hobo?

Posted about 7 years back at The Hobo Blog

There’s a fair few reactions to Hobo out there on the big wide Internets by now, and it’s interesting to see people’s interpretations. I suppose it’s pretty obvious that people are going to jump to conclusions when I’ve only given a brief glimpse of what Hobo is about. I just wanted to take a quick moment to clear a few things up. Update: this turned from a “quick moment” into a fairly comprehensive overview of what Hobo can do :-)

The main point here is this - Hobo is nothing but extensions to Rails! There’s nothing that Rails can do that Hobo can’t. I’m not saying that Hobo will be to everyone’s taste - of course you may prefer Rails as it is. I’m just making the point that Hobo only adds to Rails, it doesn’t take anything away. Perhaps it’s the slightly “magic” feel to the POD screencast – I can see that the screencast might leave some people thinking they’d rather build the app themselves and have control over everything. So I guess I’m really just making the point that you do have control over everything, in just as direct a manner as you do in Rails without Hobo.

Hobo does do more than your average plugin though – it’s kind of like several plugins rolled into one. Inevitably people are going to be interested in having those features as separate plugins – a few people have asked for DRYML by itself already. But there are a bunch of dependencies between the different features, and to be honest I won’t know exactly where things can be separated until Hobo matures a bit.

So, for now at least, I’ve taken a different approach - you install all these features at once by installing Hobo, but you use only those features you want to. If you want the whole “web app builder” thing, then you’ll end up using most or all of them, but if you just want DRYML? Not a problem, the rest of Hobo won’t get in your way. If you later see that you could also benefit from, say, the ajax-mechanism, fine – just start using it.

So perhaps a quick tour of what these features are would be in order :-)

DRYML

This is really the heart of Hobo – it all started with DRYML. There’s a few posts on this already of course - have a look in the documentation category. DRYML consists of the templating mechanism itself, as well as a “core” tag library, with the basic things like loops and conditionals.

Ajax Rendering

Building on DRYML, this is the ability to mark a section of your page as a “part”. Having done this, Hobo will track the object that was in context when the part was rendered, and can re-render the part using the new state of that object when requested. This mechanism can be used by itself, but works best in combination with the Hobo Rapid tag library, which lets you write very simple stuff like

<delete_button update="number_of_users"/>

and the number of users will automatically change to reflect the deletion.

Right now using the Ajax mechanism without also buying into Hobo Rapid is kind of a pain. Some extra work to smooth that out is in order. Perhaps some regular Rails helpers.

Hobo Rapid Tag Library

This is where things get groovy. A tag library is basically just like a load of Rails helpers, but as DRYML tags instead of methods. Hobo Rapid contains the Hobo equivalent of link helpers, form helpers, ajax helpers, and pagination helpers. There’s also some “scaffold-like” tags for default pages, and support for navigation bars.

This library is expected to grow!

ActiveRecord Permission System

This appears prominently in the POD screencast. At it’s heart it’s just a simple convention for declaring who’s allowed to do what to your models (create, update, delete and view). The permissions come into effect in two places: in customising the views, and in validating http requests.

View customisation is provided in the tag library. The output of various tags is dependent on permissions. For example the <edit> tag will automatically become a read-only view if the current user does not have edit permission.

Validation of web requests is done in Hobo’s generic model controller (see below). If the request, be it a view, a create, an update or a delete (http get/post/put/delete) is not permitted for the current user, it will be rejected.

Fairly simple but useful. Models can declare which columns are searchable (there are sensible defaults of course!) and Hobo provides both server and client-side support for a nice ajaxified search that finds many types of model from a single search page.

Switchable Themes

A Hobo theme consists of public assets such as a stylesheet and images, and some tag definitions. The tags define the basic HTML structure of the various theme elements - the overall page, header and footer, navigation bar, sidebars, panels (boxed sections within the page) etc. Themes are switchable by changing a configuration variable. All the variable does is determine the paths used to find the tag definitions (app/views/hobolib/themes/theme-name) and the public assets (public/hobothemes/theme-name).

User Management (Acts As Authenticated)

In order for the permission system to work, a user model must be present. For that reason we decided to go ahead and include AAA in Hobo. It’s been tweaked a bit – the controller has been merged with Hobo’s “front” controller (so called because it gives you your front page and related pages like search, login and signup). The user model methods that are not commonly changed have been moved out into a module to keep your user model clean.

Hobo also adds the concept of a guest user, this is a pseudo model that is not stored in the database. It’s just a place to define the permissions for someone who has not logged in. One implication of this change this is that instead of testing if current_user is nil, you test for current_user.guest?.

ActiveRecord Composable Query Mechanism

It’s common practice with ActiveRecord to write query methods to capture standard queries your application needs beyond the magic find_by_thingumybob methods. A problem I ran into was that I wanted to be able to compose queries: find everything that matches this query or that one; find the first record that matches some query and some other one.

I found I needed such a feature in Hobo so I implemented the following:

Post.find(:all) { (title_contains("Hobo") | content_contains("Hobo")) &
                   is_in(news_category.posts) }
User.find(:first) { name_is("Tom") | email_is("foo@bar.com") }

Note that in the first example, the collection my_category.posts doesn’t need to be loaded - the query generates SQL and runs entirely on the database.

The query operations in those examples – *_contains, *_is and in_collection – are all built in. If you write class methods on your model that return SQL expressions you can use those in the query too.

Generic Model Controller (CRUD Support)

Hmmm - this does a fair few things. Maybe I need another cup of tea… Slurp, ahhh. Sorry where was I? Oh yeah - the model controller. To get this functionality, add this to your controller

hobo_model_controller

It’s just a short-hand for including Hobo::ModelController. You can also generate a controller which already contains this declaration (hey - every little helps!) with:

$ ./script/generate hobo_model_controller <model-name>

CRUD support

Hobo derives the model class from the controller class name, so you should follow the Rails convention of PostsController for model Post (the generator will do this for you of course). You then get the basic CRUD methods familiar from scaffolding: index, show, new, create, edit and update.

The controller also has support for your has_many and belongs_to associations. Firstly, your has_many associations get published automatically, so for example the URL

/posts/12/comments

Would map to the action show_comments, which is implemented for you. Also

/posts/12/comments/new

Will invoke the new_comment action - again it’s implemented for you. Note that the form on that page doesn’t post to /posts/12/comments but to /comments as usual. I decided it was best to have a single URL for creating a given model.

There’s also support for your associations when creating / updating models. Without going into too much detail in this overview, when you post (create) or put (update), you can set both has_many associations and belongs_to associations. You can either pass the id of an existing record, or pass entirely new records in nested parameter hashes. There’s support for all this in DRYML and Hobo Rapid, so for example if a person has an address as a separate, associated model, you can easily build a single form with fields for both the person and the associated address.

Data filters

The composable query mechanism for ActiveRecord has been described above. Data filters allow you to expose these queries to the web. This is easiest to explain with an example. Say we have people that are members of groups, and we want a page with all the people not in a particular group. Inside the people controller we define a data filter:

def_data_filter :not_in do |collection|
  not_in(collection)
end

A page with all the people not in the group with id 7 would then be available at

/people?where_not_in=group_17

Enhanced autocomplete

Rails already has support for working with the Scriptaculous auto-completer through the helper auto_complete_for (although that’s on its way out in 2.0). Hobo’s version is enhanced to work with the data filter mechanism. Say for example you wanted an auto-completer to allow you to add people to a list - you don’t want the people already in the list to be included in the completions. You would add the following to your controller:

def_data_filter :not_in do |collection|
  not_in(collection)
end

autocomplete_for :name

You would then point your auto-completer at (e.g.) /people/completions?for=name&where_not_in=list_12

Hobo Rapid has an auto-completer tag so the client side is nice and easy too.

Remote procedure calls

When DHH introduced the Simply Restful stuff, he described CRUD as an aspiration rather than a hard rule (IIRC). In other words, you shouldn’t go crazy trying to model absolutely everything as resources – there will still be “remote procedure calls” (RPC) that we post to. I hit this recently with a need for a “reset password” service on an app I’m building. (BTW - this is basically how Hobo moves forward - if I hit a need for a feature that I feel will crop up again and again, I build it into Hobo, not the app. In this case I didn’t want to build password reset into Hobo, but I did build the RPC mechanism).

The basic procedure is: write an action in your controller as normal. Add web_method <method-name>. Hobo will add a route for your method, and apply a before filter so the object in question is already available in @this. Hobo’s ajax mechanism supports updating the page with results from your method, and there’s integration into the permission system too.

Let’s see an example - the reset password method. In the controller we add:

web_method :reset_password
def reset_password
  new_password = @this.reset_password
  hobo_ajax_response(@this, :password => new_password)
end

On the model we can add a method can_call_reset_password?(user). In my case I only wanted the super-user to have access to this method so I didn’t need can_call_reset_password?.

The method will be available to HTTP posts at, e.g.

/users/21/reset_password

For the client side there’s a <remote_method_button> tag (note to self: should be called <web_method_button>?)

Alternative show methods

Simply Restful introduced the semicolon in the URL to access alternate views of the same object. So

/posts/12

Would be a ‘normal’ view of the post, while

/post/12;edit

Would give you a form to edit the post – still a view of the post, just a different one. You’ll probably find the need for additional “alternative views”, e.g. you might have a main view of a user, plus a separate “My Profile” page where users can edit details that don’t change so often, like their email address. Hobo allows you to simply say

show_method :profile

In your controller. You then create app/views/users/profile.dryml. You also get a named route person_profile so you can call person_profile_url(fred) and get the URL back.

Migration Enhancements

This is a little one, but very useful. In create_table calls, you can add columns like this

t.string :name, :subject, :limit => 50

instead of

t.column :name, :string, :limit => 50
t.column :subject, :string, :limit => 50

There’s also t.auto_dates that gives you updated_at and created_at, and

t.fkey :zip, :zap

That will give you integer columns zip_id and zap_id.

ID Names

In ActiveRecord everything has a numeric ID. It’s common however, that models also have an identifying name (e.g. a name column where every row is unique). If a model has an ID name like this, it’s nice to be able to sometimes use it instead of the numeric ID, for example in readable URLs. If your model declares hobo_model, you can also declare

id_name <column-name>

If you don’t specify a column it defaults to name. This gives you a read/write attribute id_name which is just an alias for the column in question. You also get find_by_id_name on the class.

If you are using Hobo’s model_controller you can then use names instead of IDs in your URLs, e.g. (using ID names in combination with the associations support):

/categories/News/posts

The helper object_url will generate this kind of URL too - if the object you pass supports ID names.

That’s All Folks!

That’s pretty much everything, although of course lots of detail is lacking. Oh and there’s a ton of great new stuff just around the corner of course!

Markaby vs Haml vs ERB for Page Templates

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

I’ve been spending some time lately looking at different templating packages for Rails, in hopes of finding something cleaner and sexier than the standard ERB (rhtml) recipe, that also helps avoid common HTML pitfalls that cause pages not to validate.

My search has pretty much boiled down to two candidates at this point. The first is Markaby, which has been around for a while now and lets us represent our XHTML in Ruby code. The other candidate is the new kid on the block, Haml, which just reached a 1.0 last week and has it’s own proprietary CSS-ish syntax. Let’s take a look at brief look at both of them…

Here’s some ERB:

<div class="column" id="content">
  <h2 class="entry_title"><%= h @thing.name %></h2>
  <div class="entry_link"><%= link_to('link', @thing.link) %></div>
</div>

This is probably what we’re all used to and there’s no arguing that it works well enough, but… Well, it’s kind of ugly, isn’t it? To represent this same thing in Markaby, we install the plugin and create a template with a .mab extension and stick this in it:

div.column.content! {
  h2.entry_title @thing.name
  div.entry_link link_to 'link', @thing.link
}

That sure looks better to me. Nice and compact, clean. The best part is that Markaby is actually valid Ruby syntax. This buys us a couple things: first of all, it means that our view won’t run at all if we end up with a syntax error in it, which in turn means that it’s valid XHTML. Slick.

The downside is, of course, performance. It requires rendering for every single tag and property, which makes it slow in comparison to ERB, since just the inline Ruby snippets in the rhtml file have to be processed and inserted into a mostly pre-rendered HTML template. I also have some minor gripes about the use of bang instead of pound for representing element IDs, and the fact that it blows up when I put a yield in my Markaby layout code (I have to use @content_for_layout, which is deprecated now).

Anyway, enough about that. Let’s talk about Haml for a second. Install the plugin, and create a view with a .haml extension. Here’s the same chunk of code we saw before written in Haml:

.column#content
  %h2.entry_title= @thing.name
  .entry_link= link_to('link', @thing.link)

Haml defines it’s own syntax, which borrows from familiar CSS markup, and takes advantage of whitespace sensitivity for nesting. This latter bit is great news if you’re one of those undercover Python people hiding amongst us (I’m not one of you, now go away). It generates really nice clean appropriately nested HTML for output too.

Although it’s fairly easy to read and satisfies our cleanliness criteria, there are some immediate downsides to the fact that the markup is proprietary. Firstly, it means the files still have to be parsed and re-rendered by Rails, for a performance hit — same as we’d get with Markaby or any other higher-level template language for that matter. It also means that your editor isn’t going to be able to help you with syntax highlighting unless it has explicit support through a plugin.

I can see why people like Haml, it’s compact and kind of fun (see the tutorial for more). But all things considered, I really can’t see any reason I’d use it instead of Markaby, which feels much more natural to me and has the added benefit of Ruby syntax validation. Perhaps if it were to represent a significant performance increase — this seems doubtful — but I haven’t seen any real benchmarks. In any case, I don’t think I’ll be using it any time soon.

If I were to choose one of these two, I’d have to go with Markaby. I’m quite smitten by the idea of writing template code in pure Ruby, and the syntax validation enforcement is extremely desirable. As bizarre as it may seem, I love the idea of a page failing to run because of a syntax error in my “HTML” markup. Still, the performance issues give me pause. An even bigger issue is that of fragment caching, which sadly seems to be currently busted in Markaby. So, all things considered, I guess I’m sticking with ERB in my view templates, coupled with assert_valid_markup for my validation testing needs. At least for now. Even thought it makes me cringe a bit.

If I’ve missed anything worth considering about either of these templates, or if there are other options, please drop me a line. I’d love to hear what the rest of the community is using for their high-volume web apps…

A Healthy Venus

Posted about 7 years back at Ryan Tomayko's Writings

When I first got into my latest venture, one of the first things I did was scour the web for anything health care related with a feed attached to it. I found a few heavy medical weblogs, the occasional disgruntled nurse, and I do believe there was a hospital janitor lamenting the effects various human fluids had on his tile surface. Yeah, there wasn’t a whole lot going on there, even considering the janitor’s delicate prose.

The situation has changed in a big way over the past year. I'm seeing new health business blogs pop up weekly – and they’re good. One of the more popular sites has, in fact, created a derivative of The Cluetrain Manifesto imaginatively titled “The HealthTrain Manifesto”, and they have an RSS 2.0 feed that is damn near valid.

A couple of months ago I decided we really ought to have a corporate Venus. Not for internal blogs—we don’t believe in those—but to use as a kind of shared news reader. “It will help get the team engaged in the conversation of the market,” I said, “and besides, all the cool kids are doing it.”

I have to hand it to the Planet guys, and especially Sam: we had a health news river flowing within an hour. That might not sound like a big deal but consider that none of these feeds are valid (or even approaching valid) and you soon realize that it is actually quite magical.

The site worked so well internally that we decided to make it publicly available as The Health Benefit News River. We’ll see how that goes.

To be honest, I'm a bit worried about what the reaction will be. If anyone has experience running these sites, especially in areas outside of technology, maybe you could help me out with a couple of questions:

  1. Full content – I have a bad feeling that some may not like the idea of having their content republished in full, even if it’s temporarily. Experiences?

  2. We'd like to ensure we’re able to syndicate content licensed under any of the non-commercial variants from Creative Commons or other compatible licenses. The site is loosely affiliated with the company (as in, the company pays the hosting bills) but we receive no revenues from the service, nor do we plan to in the future. Are we in the clear here? If not, what would need to change?

  3. Why do people do stuff like wrap every post in a <font size="7"> tag? Does seeing that get easier with time?

I’ll try to have a progress update in a month or so. We’ll put some numbers together on various feed characteristics, license use, and other items of interest.

MicroTest 1.3 / MicroStub 1.1: still under 4KB

Posted about 7 years back at Wood for the Trees

MicroTest has had a few tweaks, making it more brief and efficient at what it does. Also, I added a setup and teardown interface which can be used. For example, I removed the use of ObjectSpace and squeezed a few percent of performance just from that. On my 1.83GHz, the 6 tests of the self test now consistently take around 500 microseconds (or 0.0005 seconds). Pretty nippy.

MicroStub had a little problem with it—it stubbed instance methods and didn’t return the class back to normal. So, it violated one of the most basic principles of testing: isolated tests. That’s all fixed now, using some Spartan back-and-forth aliasing. Obviously a double stub will fail. Maybe I’ll fix that later.

Lastly, I added a benchmarking test case, really just useful for profiling.

Of course, the library is still under 4KB—in fact, it’s 3940 bytes.

Have a look at the repository (revision 25) for the latest version.

MicroTest 1.3 / MicroStub 1.1: still under 4KB

Posted about 7 years back at Wood for the Trees

MicroTest has had a few tweaks, making it more brief and efficient at what it does. Also, I added a setup and teardown interface which can be used. For example, I removed the use of ObjectSpace and squeezed a few percent of performance just from that. On my 1.83GHz, the 6 tests of the self test now consistently take around 500 microseconds (or 0.0005 seconds). Pretty nippy.

MicroStub had a little problem with it—it stubbed instance methods and didn’t return the class back to normal. So, it violated one of the most basic principles of testing: isolated tests. That’s all fixed now, using some Spartan back-and-forth aliasing. Obviously a double stub will fail. Maybe I’ll fix that later.

Lastly, I added a benchmarking test case, really just useful for profiling.

Of course, the library is still under 4KB—in fact, it’s 3940 bytes.

Have a look at the repository (revision 25) for the latest version.

"Helpful" Thumbnails

Posted about 7 years back at Ryan Tomayko's Writings

Rafe Colburn:

Today I was reading this article, which “helpfully” offers thumbnails of the pages each link points to, powered by Snap. I guess this is supposed to provide value to users, but it doesn’t. It’s just harassment.

I concur. I first noticed this on Techcrunch and thought it was interesting from an integration perspective. I've since seen these popouts explode all over the place and I can’t stand them.

This is the kind of stuff that should be enabled on the client with a browser extension or Greasemonkey script but it seems we’ll be using client side tech to disable the crap that’s thrown at us from the server instead.

At this point I went looking for a Greasemonkey script to disable these Snap previews and quickly found that Snap let’s you disable them directly and centrally. That’s really cool and also unexpected.

I suppose I don’t have anything to complain about today, people – as you were.

Tim Lucas - Ruby on Rails Podcast

Posted about 7 years back at Ruby on Rails Podcast

Tim Lucas, co-developer of Web Connections and godfather of the Sydney Ruby Brigade, talks about developing with REST and JSON.

Bayesian Networks for Ruby release 0.9

Posted about 7 years back at Spejman On Rails

Bayesian Networks for Ruby (bn4r) permits create, modify, solve, import and export Bayesian Networks, give it a try and infer some probabilities with them!

This release includes suport for discrete variable nodes, now you can use nodes with values like {small, normal, big} instead of {true, false}.

Export to Microsoft Belief Network has been improved.

As previous releases you can solve your networks with enumeration_ask, prior_sample, rejection_sampling and likelihood_weighting algorithms.

Testing work will be appraised, if you are interested please contact me in http://rubyforge.org/projects/bn4r or at sergio.espeja (you know what ...) gmail.com.

More info:

IntelliJ Ruby Plugin 0.1 Beta Released

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

The kind folks over at JetBrains have finally got around to releasing a 0.1 Beta of their Ruby Plugin to the IDEA Repository. If you’re an IntelliJ user, it’s now as easy as going to the plugin manager in Preferences and selecting the Ruby plugin for installation. The workflow is the same as I described earlier but this release brings some important bugfixes; console output is now available, starting/stopping the WEBrick server now works as expected, etc.

In case you haven’t checked it out, the integrated Rails generators and Rake tasks rock, there’s an RDoc toolbar with lookup, goto class functionality, code formatting, and a bunch of other goodies, all detailed in the Release Notes. I got all excited when I saw keyword completion in the list; but it turns out that it’s really just that — although a ticket for proper code completion is listed in the issue tracker it looks like it’ll still be awhile before we get to feel that love. Syntax highlighting in rhtml/builder templates will be huge also (in the roadmap).

I’ve been using RadRails as my RoR IDE so far, but now that the IntelliJ plugin is mature enough to work with I’ll probably start migrating over. Don’t get me wrong; RadRails is a great project (and free!), but IntelliJ is my IDE of choice for Java dev, and I’m psyched to see it evolving into a platform for Ruby development too.

MicroTest 1.2 & MicroStub 1.0: Your microscopic testing pals

Posted about 7 years back at Wood for the Trees

Just after writing the previous post, I discovered the need for a little bit of method stubbing and promptly fell upon the task with MicroStyle1. Also, I will officially keep MicroTest under 4 kilobytes2.

So, without further ado, here are the latest new features of MicroTest:
  • colour output
  • execution time in microseconds
  • MicroStub: overwrite a method with stub()
  • twice as fast (no sweat)
  • a self-test! (SELFTEST=true ruby microtest.rb)
  • and its own home. Awwww.

MicroTest now lives in my Google Code SVN repository.

  svn co http://mabs29.googlecode.com/svn/trunk/other/microtest/

1 By the way, if you haven’t noticed yet, I’ve been a little inspired by Camping.

2 Unlike Camping (because MicroTest is less complicated), I think it only fair that the 4 kilobytes include comments and the self-test.