Making Links in Ruby

Tweet

Organization Solutions

You have an app that has a note field and you don’t allow HTML in that field. The users would like the ability to add links into that field. How about implementing a link discovery feature?

Sounds great. Where do I start?

Let’s say you want to make a note that says “The url http://www.sitepoint.com/ruby/ should be a link” The URL should turn into a link.

Getting Started

Let’s make a new Ruby file

$ touch make_url.rb

Open that new file up and add the following code.

make_url.rb

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'  
puts NOTE

When you run that code you will see the NOTE output to the screen.

$ ruby make_url.rb
The url http://www.sitepoint.com/ruby/ should be a link

That really doesn’t get us anywhere. We need to see if there is a URL somewhere in that string. One way is to split the string, look at each word, and see if they match the pattern of a URL.

Let’s split the string and look at the individual words.

make_url.rb

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'  

def hasURL(note)
  words = note.split
  words.each do |word|
    puts word
  end
end

hasURL(NOTE)

Run that and you see each individual word.

$ ruby make_url.rb
The
url

http://www.sitepoint.com/ruby/

should
be
a
link

Split takes the string and will split it into an array. The default delimiter for splitting is whitespace. This gives us an array of words that we can individually test against a URL pattern.

make_url.rb

require 'uri'

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'

def isURL(word)
  if word =~ URI::regexp
    puts '---- we have a URL! => ' + word
  else
    puts word
  end
end

def hasURL(note)
  words = note.split
  words.each do |word|
    isURL(word)
  end
end

hasURL(NOTE)

Let’s run that and wee what we get.

$ ruby make_url.rb
The
url
---- we have a URL! => http://www.sitepoint.com/ruby/
should
be
a
link

It works! You might be wondering what that URI::regexp does. It checks to see if it’s a URI like string, returning true if we have a URL. Ruby is great.

We can use our new knowledge to create links.

make_url.rb

require 'uri'

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'

def makelink(url)
  puts '<a href="' + url + '">' + url + '</a>'
end

def isURL(word)
  if word =~ URI::regexp
    makelink(word)
  else
    puts word
  end
end

def hasURL(note)
  words = note.split
  words.each do |word|
    isURL(word)
  end
end

hasURL(NOTE)

This results in

$ ruby make_url.rb 
The
url
<a href="http://www.sitepoint.com/ruby/">http:// www.sitepoint.com/ruby/</a>
should
be
a
link

We are getting close.

Refactor

What if we used the map to loop through each word? In the make_url.rb file comment out hasURL(note) and add

# hasURL(NOTE)
puts NOTE.split.map { |x| x }

Save the file and run it.

$ ruby make_url.rb 
The
url

http://www.sitepoint.com/ruby/

should
be
a
link

This is a step back in terms of output, Now we can remove some code. Remove the hasURL method.

Instead of sending the check to a method, we can check right inline. Since we are doing that we can also remove the isURL method and clean up the makeURL method.

require 'uri'

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'

def makelink(url)
  '<a href="' + url + '">' + url + '</a>'
end

puts NOTE.split.map { |x| x =~ URI::regexp ? makelink(x) : x }

Let’s run that code.

$ ruby make_url.rb
The
url
<a href="http://www.sitepoint.com/ruby/">http://www.sitepoint.com/ruby/</a>
should
be
a
link

Now you’re splitting, iterating though each word, and checking that word to see if it’s a URL. If so, make a link. We have the same output as before and we’ve removed half of the code.

Getting the Band Back Together

That’s cool and all, but the note is still an array. Let’s join it back together.

puts NOTE.split.map { |x| x =~ URI::regexp ? makelink(x) : x }.join(" ")

Run the code and enjoy the simplicity.

$ ruby make_url.rb 
The url <a href="http://www.sitepoint.com/ruby/">http://www.sitepoint.com/ruby/</a> should be a link

Awesome.

The code we had.

require 'uri'

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'

def makelink(url)
  puts '<a href="' + url + '">' + url + '</a>'
end

def isURL(word)
  if word =~ URI::regexp
    makelink(word)
  else
    puts word
  end
end

def hasURL(note)
  words = note.split
  words.each do |word|
    isURL(word)
  end
end

hasURL(NOTE)

The code we have.

make_url.rb
require ‘uri’

NOTE = 'The url http://www.sitepoint.com/ruby/ should be a link'

def makelink(url)
  '<a href="' + url + '">' + url + '</a>'
end

puts NOTE.split.map { |x| x =~ URI::regexp ? makelink(x) : x }.join(" ")

Much cleaner.

When I first started with Ruby, I would see the code we just wrote and I scratch my head. Now we are starting to write code like that and we understand what’s going on in those terse statements.

Ruby is chock-full of utilities and methods that allow us to be very succinct in achieving our goal. Here, we scan strings for URL-like strings and create HTML links out of each one. This is done with just a few lines of Ruby.

You can use this utility to store the note with an array of links or simply display the note in a HTML friendly way.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments