Search code examples
ruby-on-railsruby-on-rails-4hyperlinkautolink

Link Detection / String to Link (even without www)


Case: A User's Profile where he can add a bunch of links.

I collect the links via the User Registration Page, but i'm having a Problem with Users not entering www. and http:// in front of the URL.

I could fix the http:// problem with auto_link but i have to many users just typing example.com.

How can i extract the URL from a String, even if it is without www. or http:// (The field contains ONLY the url).

Display Code:

<% if @user.website.present? %>
  <li>
    <%= link_to @user.website, target: '_blank' do %>
      <i class="fa fa-globe"></i> <span>Website</span>
    <% end %>
  </li>
<% end %>

Solution

  • Consider the following sample urls:

    text1="example.com/foo/bar"
    text2="www.example.com/foo/bar"
    text3="http://www.example.com/foo/bar"
    text4="https://www.example.com/foo/bar"
    

    This:

    gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4")
    

    will output the following:

    text1.gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4") 
    # http://www.example.com/foo/bar
    
    text2.gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4") 
    # http://www.example.com/foo/bar
    
    text3.gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4") 
    # http://www.example.com/foo/bar
    
    text4.gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4") 
    # https remains
    # https://www.example.com/foo/bar 
    

    So, if you want to use link_to external link:

    <%= link_to '<i class="fa fa-globe"></i> <span>Website</span>'.html_safe, 
        @user.website.
        gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4") unless
        @user.website.nil? %>
    

    Edit:

    The above case will have a bad exception.

    text5="http://example.com/foo/bar"
    

    the above substitution will return

    http://www.example.com/foo/bar # inserting a "www"
    

    which is not ok for most cases. So, you must provide a condition to substitute. I'd suggest you create a helper method like this:

    def url_to_external(text)
        /\Ahttp(s)?:\/\//.match(text) ? text : text.gsub(/\A(http(s)?:\/\/)?(www\.)?(.*)/,"http\\2://www.\\4")
    end
    

    Which will only replace if there is no "http://" or "https://" at the start of the string.

    In your view, then:

    <%= link_to '<i class="fa fa-globe"></i> <span>Website</span>'.html_safe,
        url_to_external(@user.website) unless @user.website.nil? %>