user1194509
user1194509

Reputation:

Frozen string - Ruby

I have this code:

 settings[:base_name].gsub! /[\x00\/\\:\*\?\"<>\|]/, ''

When I run the script it throws an error:

gsub!': can't modify frozen String (RuntimeError)

I have changed the code to this:

 settings[:base_name] = settings[:base_name].gsub /[\x00\/\\:\*\?\"<>\|]/, ''

The code above works, but I don't like at all, is there a way to properly use gsub! in this case?

Upvotes: 4

Views: 12736

Answers (2)

Anupam
Anupam

Reputation: 1530

@pabloelices,

The issue is that the String object referenced by settings[:base_name] has been frozen and is now effectively immutable. You can check this by:

settings[:base_name].frozen?  # => will return 'true'

You could clean up the code and intent somewhat by doing the following:

my_setting = settings[:base_name].dup   # Create a duplicate of the setting.
settings[:base_name]  = my_setting.gsub /[\x00\/\\:\*\?\"<>\|]/, ''

But the original String object will not allow gsub! to be invoked on it.

Upvotes: 5

Linuxios
Linuxios

Reputation: 35803

No. Apparently, the API providing the string has frozen it, which means any method that modifies it will fail. Because gsub! modifies the string it is called on, a frozen object can not use gsub!. However, the variable that contains a frozen object can still be set to a non-frozen object, which is why your second code snippet works.

The API probably froze the object because it is a constant string that all of the instances share, and so one instance shouldn't be able to ruin the string. But they do define a setter method, so you can set the value.

Upvotes: 7

Related Questions