Cleaning parameters from string url in Ruby

by-web development

Today I had to make sure that a url wasn’t containing a certain parameter, and if it was I needed to clean it form the params.

Let’s assume a resource like

* RESOURCE
  * url

When saving that resource I need to make sure that the a param ‘user_ref’ is not present from the url. This param can or cannot have values.

So we start with a simple test

require 'spec_helper'

describe Resource do

  describe 'cleaning user_ref param' do

     before do 
        @empty_param = FactoryGirl.create(:resource, :url => "http://google.com?param1=1&clickref=¶m3")
        @full_param      = FactoryGirl.create(:resource, :url => "http://google.com?param1=1&clickref=remove-me¶m3")
        @clean_url        = FactoryGirl.create(:resource, :url => "http://google.com?param1=1")
     end

    it "should remove empty click ref params and keep other params" do
       @empty_param.url.should eql("http://google.com?param1=1¶m3")
    end

    it "should remove full click ref params and keep other params" do
       @full_param.url.should eql("http://google.com?param1=1¶m3")
    end

    it "should still save url without click ref params and keep other params" do
       @clean_url.url.should eql("http://google.com?param1=1")
    end

  end
end

After testing different Regexps (and I have to admin I’m not a master of them, so maybe the solution is somewhere else), I finally found Addressable Gem and everything became easy again.

EDIT: Theo Cushion sent me a better cleaner solution via email, please check the bottom of the post

In the Resource model I have

class Resource < ActiveRecord::Base

....

before_save :clean_clickref

....

protected

def clean_clickref

  if self.url
      require 'addressable/uri'

      uri = Addressable::URI.parse(self.url)
      params = uri.query_values

      if params
        uri.query_values = params.except('clickref')
        self.url = uri.to_s
      end

    end
  end

end

EDIT: This is Theo Cushion’s solution, using the url setter. Way nicer, and we don’t need the :before_save

class Resource < ActiveRecord::Base
  ....
  def url=(value)
    require 'addressable/uri'
    result = if value.is_a? String
      uri = Addressable::URI.parse value
      uri.query_values = uri.query_values.except( 'clickref' ) if uri.query_values

      uri.to_s
    else
      nil
    end

    write_attribute :url, result
  end
  ....
end

This is easy enough and readable enough and make the tests pass, time for the next feature!

Thanks for reading. To continue the discussion contact me: or

Related posts