Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gsub! On an argument doesn't work

Tags:

ruby

I am making a function that turns the first argument into a PHP var (useless, I know), and set it equal to the second argument. I'm trying to gsub! it to get rid of all the characters that can't be used in a PHP var. Here is what I have:

dvar = "$" + name.gsub!(/.?\/!@\#{}$%^&*()`~/, "") { |match| puts match }

I have the puts match there to make sure some of the characters were removed. name is a variable passed into a method in which this is its purpose. I am getting this error:

TypeError: can't convert nil into String
cVar at ./Web.rb:31
(root) at C:\Users\Andrew\Documents\NetBeansProjects\Web\lib\main.rb:13

Web.rb is the file this line is in, and main.rb is the file calling this method. How can I fix this?

EDIT: If I remove the ! in gsub!, it goes through, but the characters aren't removed.

like image 385
Imnotanerd Avatar asked Dec 13 '22 13:12

Imnotanerd


2 Answers

Short answer

Use dvar = "$" + name.tr(".?\/!@\#{}$%^&*()``~", '')

Long answer

The problem you are facing is that the gsub! call is returning nil. You can't concatenate (+) a String with a nil.

That's happening because you have a malformed Regexp. You aren't escaping the special regex symbols, like $, * and ., just for a start. Also, the way it is now, gsub will only match if your string contains all that symbols in sequence. You should use the pipe (|) operator to make an OR like operation.

gsub! will also return nil if no substitutions happened.
See the documentation for gsub and gsub! here: http://ruby-doc.org/core/classes/String.html#M001186
I think you should replace gsub! with gsub. Do you really need name to change?

Example:

name = "m$var.name$$"
dvar = "$" + name.gsub!(/\$|\.|\*/, "") # $ or . or *
# dvar now contains $mvarname and name is mvarname

Your line, corrected:

dvar = "$" + name.gsub(/\.|\?|\/|\!|\@|\\|\#|\{|\}|\$|\%|\^|\&|\*|\(|\)|\`|\~/, "")
# some things shouldn't (or aren't needed to) be escaped, I don't remember them all right now

As J-_-L appointed, you could also use a character class ([]), that makes it a little clearer, I guess. Well, it's hard to mentally parse anyway.

dvar = "$" + name.gsub(/[\.\?\/\!\@\\\#\{\}\$\%\^\&\*\(\)\`\~]/, "")

But because what you are doing is simple character replacement, the best method is tr (again reminded by J-_-L!):

dvar = "$" + name.tr(".?\/!@\#{}$%^&*()`~", '')

Way easier to read and make modifications.

like image 64
Thiago Silveira Avatar answered Dec 15 '22 03:12

Thiago Silveira


  • You cannot apply a second parameter and a block to gsub (the block is ignored)
  • The regex is wrong, you forgot the square brackets: /[.?\/!@\#{}$%^&*()~]/`
  • Because your regex is wrong, it didn't match anything and because gsub! returns nil if nothing was replaced, you get this strange nil no method error
  • btw: you should use gsub not gsub! in this case, because you are using the return value (and not name itself) -- and the error would not have happened
like image 36
J-_-L Avatar answered Dec 15 '22 02:12

J-_-L