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.
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!
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.
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.
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.
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*.
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.
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.
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.
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.