November 7, 2016 · ruby erb rails

Hyperlinking hashtags

Hashtags are #great. They allow people to share experiences, such as watching TV. These days you can hardly find a show on television that doesn’t have #showName watermarked in the corner of the screen. These hashtags can be followed live to see what other people are saying.

However, tweeting isn’t limited to the spectators. During the 2014 Oscars, the host Ellen tweeted the most liked tweet ever and tagged it with “#oscars”.

The text “#oscars” links to https://twitter.com/hashtag/oscars. This takes people to a timeline dedicated to the “oscars” hashtag.

But how do you go about finding hashtags in content and hyperlinking them? In these examples, we will use gsub and regular expressions (regex).

Using gsub to hyperlink hashtags

The gsub method is called on a String. It takes a regular expression and returns the string with matches replaced. In a tweet, the hashtags need to be replaced with hyperlinks.

Here is the basic usage of String#gsub.

"hello #world #foo".gsub(/#\w+/) { "hello" }
# => "hello hello hello"

The hashtags are matched and replaced with the return value of the block, “hello”.

The argument provided to gsub is a regular expression. The forward slashes create a Regexp object. The body of the regex is #\w+. It finds an octothorp (#) followed by any word character (\w), and the word character must occur one or more times (\w+).

Let’s hashify the Oscar tweet!

tweet = "If only Bradley's arm was longer. Best photo ever. #oscars"
tweet.gsub(/#\w+/) { |match| %Q{<a href="/hashtags/#{match}">#{match}</a>} }
# => If only Bradley's arm was longer. Best photo ever.
#    <a href="/hashtags/#oscars">#oscars</a>

Here we are taking the match and using it to build up a link around the hashtag. The hashtag wrapped in anchor tags is returned from the block and used as the replacement value.

Note: %Q{} acts like double quotes around the string, but allows the use of double quotes inside without escaping. This works great when you want variable interpolation, but the string contains double quotes.

Removing the octothorp from the URL

In the example above, the href is not quite correct. To match Twitter, the path should be “/hashtags/oscars” but instead it is “/hashtags/#oscars”.

The octothorp can be easily removed using the delete method.

%Q{<a href="/hashtags/#{match.delete("#")}">#{match}</a>}

However, there is a better way.

tweet.gsub(/#(\w+)/) do |match|
  %Q{<a href="/hashtags/#{$1}">#{match}</a>}
end

Notice the change? Parentheses are added around the part of the regex matching the word characters (\w+). This captures whatever is inside of the parenthesis and makes it available inside of the block as $1.

Inside of the block we still have access to match which is “#oscars”, but now $1 is also available, and it contains just the tag “oscars”.

Simplifying with Rails helpers

We can simplify this further in a Rails application using link_to and a named route.

tweet.gsub(/#(\w+)/) { |match| link_to match, hashtag_path($1) }

This can be added to a helper method to make it available in views.

# app/helpers/tweet_helper.rb
module TweetHelper
  def link_hashtags(tweet)
    tweet.gsub(/#(\w+)/) { |match| link_to match, hashtag_path($1) }
  end
end

Now link_hashtags can be used anywhere in the app to hyperlink hashtags.

<%# app/views/tweets/_tweet.erb %>
<%= link_hashtags(tweet.text) %>