Mr eel

Ruby

Sass & Haml - A Sweet Romance Begins

If you’re just starting out using Sass, you can make things easier on yourself by having it automatically compile the stylesheets with every request. This tip applies to both Rails and Merb. Just add the following bit of code to your development.rb file.


Sass::Plugin.options[:always_update] = true

P.S. After being dubious for some time, I’ve now begun my romance with Haml and Sass. It’s sweet indeed. Terse, auto-formatting, variables. Oh my. Delicious.

Posted on January 20th, 2008 | There are 2 comments

More New Merb (0.5 is out now)

Just a quick heads-up. Merb has moved pretty quickly over the last few weeks, with lots of nice additions, code refactoring and general polish.

Now, Merb 0.5 is out. You can install it via RubyGems. Ezra has release notes on his blog.

Well done to all the devs! Merb just keeps looking better and better as it goes along. Yay!

Posted on January 10th, 2008 | There are 0 comments

I Don’t Like Ruby’s Class Variables

Just a general comment. The behaviour of class variables in Ruby is nonsensical.

I’ve had many frustrating moments dealing with the way class variables are handled in sub-classes — they’re shared between all subclasses, rather than belonging to just the one class — now I’m having fun trying to create them when I mix in a module.

What they do and how they are scoped is confusing. Definitely one of my least favourite parts of the language.

Posted on January 9th, 2008 | There are 2 comments

RubyGems - Get Your Backwards-compatibility Here

If you’ve upgraded to the latest version of RubyGems you might notice that some older gems break. This is because the #require_gem method is no longer deprecated, it’s been removed entirely. Instead we need to use the #gem method.

That’s cool, but in the meantime we still need #require_gem to work, since it may take awhile for all the various gems we rely on to be updated. Lucky for us it’s easy to do.


unless Object.respond_to? :require_gem
  class Object
    def require_gem(*args)
      gem(*args)
    end
  end
end

Here we’re just adding the #require_gem method back to the Object class, which palms of it’s arguments to the new #gem method. To make sure it doesn’t break with older versions of RubyGems — an issue when working collaboratively — I’ve wrapped it in a test which checks to see if #require_gem is already declared, in which case we don’t have to add backwards-compatibility.

If you’re using Rails, you can put this bit of code in you environment.rb. Just make sure it comes before any requires for gems.

Posted on January 2nd, 2008 | There are 0 comments

DataMapper - Introductory Docs

I finally got off my bum and put together some documentation for DataMapper. These are mainly introductory docs. Not exhaustive by any measure, but should help folks get up to speed. You can check them out here.

Posted on December 18th, 2007 | There are 0 comments

A Mullion Ways to Do the One Thing

As much as I like Ruby, sometimes I see a feature that just makes me ask why. WHY? Specifically, when you have two features that do exactly the same thing, why implement both? The best argument for redundant features is that one is a short cut for a common argument. The best examples are the various literals.


# Hash
{:yay => 'spasm', :hoon => 'town'}
# Array
[1, 2, 3, 4]
%w(array of four words)
# Integers and floats
1
1.2
# Strings
"Yes, this is actually a literal"
# Regular Expressions
/(w+)/|./
# Ranges
1..100

And more… There are loads of ‘em! Literals are one of the nice things about Ruby. They are also sadly, one of the worst. Why? Because many of them are redundant. One that I came across more recently made me quirk my brows:


# Create a hash
{1 => 2, 3 => 4} #=> {1 => 2, 3 => 4}
{1,2,3,4}        #=> {1 => 2, 3 => 4}

The first is the most common literal for creating hashes. It’s perfect, since you’re listing the pairs that go into your new hash and you can see how the keys are related to the values. The second one is just a shorter version. More to the point, it’s a more opaque version. Why is it even there?

Just one more example:


# Create an array
%w(array of words)  #=> ['array', 'of', 'words']
%w'array of words'  #=> ['array', 'of', 'words']
%w{array of words}  #=> ['array', 'of', 'words']

If you haven’t seen this literal before, it just takes a string and treats each separate word as an entry in the array — it’s equivalent to doing "array of words".split(' '). This means you can’t have multi-word entries, but it’s a super useful shortcut. The first is the most commonly used. The other two do the same thing, but use different characters to delineate the string.

It’s a tiny thing to be sure, but I really don’t like having all these different shortcuts to do the same thing. It’s inelegant. Sadly, new versions of Ruby will have more literals.


# Yet another hash literal
{key: 'value', pairs: 'augogo'}  #=> {:key => 'value', :pairs => 'augogo'}

More deprecations in Ruby I say! Pick one good thing and stick with it.

But… I still love you Ruby *hugs*.

Posted on December 4th, 2007 | There are 2 comments

Rails - acts_as_tree Select Helper

Do you have a model with acts_as_tree? At some point you probably might want to generate a select with a representation of your tree — say categories and sub-categories for blog posts or something. I’ve seen some slightly nasty ways of doing this, so I thought I might try my hand at something cleaner.

Firstly, the most efficient way of building the options for the select is via recursion. Secondly, you shouldn’t try to do it with one method, otherwise you’ll end up checking conditions repeatedly — Is this the top level? Do I have to write out the select open or select close? — when you really don’t need to.

So I’ve split my helper into two methods. One to generate the select tag and another for the options. The method for the options recurses, going through each level in the hierarchy.


def select_for_tree(model, name, entries, options = {})
  # Grab the current value of the specified attribute
  current = instance_variable_get("@#{model}").send(name)
  # Build the option tags
  option_tags = options_for_tree(entries, current, 0)
  # Check to see if we need to include a blank entry at the top
  option_tags.insert(0, content_tag(:option)) if options[:include_blank]
  # Build the select tag
  select_tag("#{model}[#{name}]", option_tags, :id => "#{model}_#{name}")
end

def options_for_tree(entries, current, level)
  options = ''
  entries.each do |entry|
    attrs = {:value => entry.id}
    attrs[:selected] = 'selected' if entry.id == current
    options < < content_tag(:option, ("- " * level) + entry.name, attrs)
    # This is the bit that does the recursion.
    options << options_for_tree(entry.children, current, level + 1) unless entry.children.empty?
  end
  options
end

Not particularly clever, but it was interesting trying to get something reasonably simple and clean.

Posted on November 27th, 2007 | There are 3 comments

Just What The Bloody Hell is a Merb?

I’ve posted about Merb a few times, but I noticed I haven’t actually given anything like an introduction to the framework, which might be useful considering it’s not too well-known. Well, I’m not gonna do that since other nicer, better-spoken people have done it already. So here is a few links to get you started.

Merb

The official site, which has got a good overview of the framework and installations. I recommend starting with the Why Merb? page, which will hopefully convince you to give it a serious look. After that, look at the Features page.

Merb & Datamapper: Getting Rolling

A quick introduction to installing Merb and DataMapper. It should be enough to get you started coding. A slight aside; DataMapper is a really awesome ORM, my preferred choice when using Merb.

Wycats’ Introduction to Plugins

Plugins in Merb are implemented as Gems, not a custom format. The benefits for doing this are manifold. Here Wycats gives a good overview of both creating and using Merb plugins.

Wycats on the Mailer

Merb’s mailer is a very nice, well thought out bit of work.

Hassox - The Great Merb Speedup

Merb is pretty fast. The code in trunk is even faster. There has been loads of good work in the last month or so, which has seen Merb speed up many times over. Hassox has got some rather tasty benchmarks :)

Hassox - The Provides API

Previously Merb had a respond_to API similar to that in Rails. This has since been replaced with a cleaner alternative; the provides declaration.

Posted on November 22nd, 2007 | There are 0 comments

internets.search(”[text()*=Hpricot Kicks Arse]”)

There are far too many Ruby libraries I hear about and never use… until the one day I actually start playing with them and think “ZOMG this is awesome, why haven’t I used it before?”. I seem to do this a lot. Today, let’s talk about Hpricot.

It is essentially a library for navigating through HTML documents and extracting the contents. It’s the Rolls-Royce of screen-scrapers. It makes it extremely easy to select elements using CSS syntax, grabbing either an array of elements or the first match. Not only that, it’ll let you modify the contents of elements and output your updated document. As you might guess, there are many wicked things we can do with this!

But lets start out by scraping some results from Google. First step is to require Hpricot and Open-URI. We need open URI to actually retrieve the HTML from the server.


require 'rubygems'
require 'hpricot'
require 'open-uri'

Now lets actually open a url and generate a Hpricot document. Let’s search for some information on Behold… The Arctopus.


url = "http://www.google.com.au/search?hl=en&q=behold+the+arctopus&btnG=Search&meta="
doc = open(url) {|f| Hpricot(f)}

We call the open method in open-uri and pass in our URL. You can see I’ve stuck ‘behold+the+arctopus’ inside the query string. We also pass a block to open which gives us access to the HTML document returned. We pass this off to Hpricot, which then returns a Hpricot document. Now the fun begins!

Our Hpricot document has lots of nice methods in it for grabbing elements, their contents and manipulating them. So, let’s say I was looking for You Tube videos of our beloved Prog-Metal-Avant-Totally-Mental instrumentalists. We can do this by looking for an anchor which contains the words ‘YouTube’.


vids = doc.search("a[text()*=YouTube]")

We call the search method on the document and pass in our CSS selector. This returns a collection of matching elements. If we only wanted the first match, we can replace search with at. The selector is a little bit clever. It’s saying give us the anchors with text-nodes that contain ‘YouTube’ in them somewhere. Unlike most browsers, Hpricot supports a huge range of selectors. A bitter, bitter reminder of what we’re missing my friends.

Now, lets actually list out the links. We can loop through the collection and write out attributes for each. We can access the tag attributes for each element using the [] method, which we pass a symbol for the relevant attribute.


vids.each do |vid|
  puts vid[:href]
end

The code above would output:


http://www.youtube.com/watch?v=wniXxeTJlyM
http://www.youtube.com/watch?v=t80_eFghMdk

We also have access to the innerHTML of the elements:


vids.each do |vid|
  puts vid.inner_html
end

# Outputs
YouTube - <b>Behold... The Arctopus</b> in Guitar one magazine
YouTube - <b>Behold... The Arctopus</b> - Transient Exuberance

Now you can see that our link elements actually have bold tags nested inside of them. Since all the methods we have access to in the doc are available in the elements, we can select children elements with search. For no other reason that serving as a contrived example let’s go, YAAAAAAY!


vids.each do |vid|
  puts vid.at("b").inner_html
end

# Outputs
Behold... The Arctopus
Behold... The Arctopus

OK, so not that interesting, but I’m sure you can see how potentially useful Hpricot is. Want to programatically access a site without an API? OH HO HO HO! Hpricot for the motherbitchin’ win.

Posted on November 21st, 2007 | There are 0 comments

Ye Newbyes Gyde to Routing in Merb

The part of the Merb I’ve found most interesting lately is the routing. A fair number of people will be familiar with the routing in Rails. Have you ever considered how useful it is? For simple cases it does it’s job with no fuss, but if you want to get clever, most of the time you’re just out of luck.

Consider this; how do you route a request based on the subdomain? Can’t. How about based on the protocol? Nope. The port number? Naah. How about using a regular expression to analyze a URL? Shit out of luck my friends.

Merb’s routing holds the answers! It can do all of that with a much nicer syntax in it’s DSL. So, for the sake of illustration I might run through a few examples from an application I’m currently working on — I’m no expert, so these will just be simple ones.

First something real simple. Sending requests on the root url to a particular controller and action. First we match() the url. Then we specify the controller and action we want to send it to. OK… so not that clever.


r.match('/').to(:controller => 'home', :action => 'index')

Another simple one to demonstrate the use of place holders in the match. Any parts of the URL that appear where you specify a place holder will then be available in the routing.


r.match('/:controller/:action').
  to(:controller => ':controller', :action => ':action')

Just to demonstrate, you could have a weird URL scheme like this:


r.match('/:id/:controller').
  to(:controller => ':controller', :action => 'show', :id => ':id')

Now time to show some awesomeness. You can send requests to controllers that live in a particular module based on the subdomain.


r.match('/:controller/:action', :subdomain => ':subdomain').
  to(:controller => ':subdomain/:controller', :action => ':action')

This would be perfect for redirecting the requests via an admin subdomain. So requests to admin.domain.com/users would get sent to the controller/action Admin::Users#index. Nice!

I should also point out that you can also easily turn each one of these route declarations into a named route. Like so:


r.match('/login').to(:controller => 'users', :action => 'login').name(:login)

You just call #name at the end of the route declaration and pass in a symbol which will be the name you can then use in your #url calls inside controllers and views.

Ok, one last cool thing. You can match to a segment of a URL, then define a bunch of sub-matches. This is done by passing a block to the match method.


r.match('/admin') do |admin|
  admin.match("/:controller").
    to(:controller => "admin/:controller", :action => 'index')
  admin.match("/:controller/:id").
    to(:controller => "admin/:controller", :action => ":show", :id => ':id')
  %w(edit delete).each do |action|
    admin.match("/:controller/:id/#{action}").
      to(:controller => "admin/:controller", :id => ":id", :action => action)
  end
end

So what I’ve done here is match against /admin then we go onto our sub-matches. First the controllers index action. Then with an id, we map to the show action. Finally we map to the new and delete actions. This isn’t a real world example, since we’re only crudely emulating RESTful routing, but it shows how flexible you can be with matching parts of a url.

In my next Merb(ivorian) post I’ll go into a little more detail about the resources route declarations and doing some more clever stuff with ports and sub-domains. OH YEA.

Posted on November 20th, 2007 | There are 1 comment

All contents © 2005—2007 Luke Matthew Sutton