4

I've currently got a string that reads something like ["green%20books"] and I'd like it to read ["green books"].

I thought Googling for this would yield a result pretty quickly but everyone just wants to turn spaces into %20s. Not the other way around.

Any help would be much appreciated!

Edit:

This is the function I'm working with and I'm confused where in here to decode the URL. I tried removing the URI.encode text but that broke the function.

def self.get_search_terms(search_url)
    hash = CGI.parse(URI.parse(URI.encode(search_url)).query) #returns a hash
    keywords = []
    hash.each do |key, value|
      if key == "q" || key == "p"
        keywords << value
      end
    end
    keywords
  end
Zack Shapiro
  • 6,648
  • 17
  • 83
  • 151
  • Are you using Rails? If so, does `params[:q]` not meet your needs? – Benjamin Oakes Jul 24 '12 at 01:01
  • Yes, I am using Rails. I'm not sure that my string is a param of anything... – Zack Shapiro Jul 24 '12 at 01:01
  • I can understand wanting a utility method here. However, the parameter parsing itself probably shouldn't be something the controller -- or a helper -- concerns itself with. Maybe define the method in terms of a `Hash` (e.g., `params` within a controller) instead. – Benjamin Oakes Jul 24 '12 at 01:05
  • This is being done inside of a model, for what that's worth... – Zack Shapiro Jul 24 '12 at 01:08
  • In that case, this might be a duplicate of [How to extract URL parameters from a URL with Ruby or Rails?](http://stackoverflow.com/questions/2500462/how-to-extract-url-parameters-from-a-url-with-ruby-or-rails). Does that question help? – Benjamin Oakes Jul 24 '12 at 01:33

3 Answers3

20

you can use the 'unencode' method of URI. (aliased as decode)

require 'uri'
URI.decode("green%20books")
# => "green books"

this will not only replaces "%20" with space, but every uri-encoded charcter, which I assume is what you want.

documentation

YenTheFirst
  • 2,172
  • 13
  • 11
5

CGI::unescape will do what you want:

1.9.2-p320 :001 > require 'cgi'
=> true 
1.9.2-p320 :002 > s = "green%20books"
=> "green%20books" 
1.9.2-p320 :003 > CGI.unescape(s)
=> "green books"

Another option (as YenTheFirst mentioned) might be URI.decode. However, I read a discussion that it would be deprecated -- although that was in 2010.

Anyway, since you're asking about arrays, you would perhaps map using that method:

ary.map { |s| CGI.unescape(s) }
Benjamin Oakes
  • 12,262
  • 12
  • 65
  • 83
4

You can use regular expressions:

string = "green%20books"
string.gsub!('%20', ' ')

puts string
Иван Бишевац
  • 13,811
  • 21
  • 66
  • 93
  • 1
    In fact, there's no need for regex: string.gsub!('%20', ' ') – pguardiario Jul 24 '12 at 01:20
  • @pguardiario Though note that internally `gsub` converts the string to a regex anyway. – Andrew Marshall Jul 24 '12 at 01:27
  • 1
    Following `gsub` into the C source: `str_gsub` → `get_pat` → `rb_reg_regcomp` → `rb_reg_new_str` → `rb_reg_init_str` → `rb_reg_alloc` → `rb_reg_s_alloc`, which returns a new Regexp. – Andrew Marshall Jul 24 '12 at 02:25
  • 1
    @pguardiario: A string argument will be regex-ified but it will be escaped first (using `rb_reg_quote`) so you don't have to worry about `gsub('.*')` treating `.*` as a regex rather than a plain string. – mu is too short Jul 24 '12 at 02:34
  • @Andrew - that's interesting, do you have a link to where we can see that? What about rubinius/jruby? – pguardiario Jul 24 '12 at 05:50
  • @pguardiario Download the C source, I don't have the energy at the moment to go back and retrace the path while providing GitHub srouce links (though I wish I did `:\`). With some use of Ack it's not too hard to track things down, and the call path is exactly what I said it was above. – Andrew Marshall Jul 25 '12 at 01:53