Use downcase! with caution in Ruby

Summary

Ruby's `!` convention indicates methods that modify an object in place, a powerful feature requiring careful use. For instance, `String#downcase!` downcases a string, but critically returns `nil` if the string is already lowercase and no change occurs. This specific behavior can lead to unexpected outcomes when `downcase!` is used within conditional logic, such as a `case` statement, as a `nil` return will prevent any `when` clause from matching. Developers should therefore exercise caution with `!` methods, particularly when using them in comparisons or when an in-place state change is not explicitly desired.

Ruby provides ! to change state of some object in place. Hence if you see some functions have ! appended, it means the state of the caller of the function is expected to be changed. This is a very interesting Ruby feature. But sometimes one should be cautious when using this kind of functions because you would get unexpected behavior if using improperly.

Let's take an example of String#downcase!. According to the documentation.

Downcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.

If there is a String platform = "Suse", after calling platform.downcase!, the platform should become "suse". This is exactly what we expected. How about the return value? It's also "suse" and that's fine. In some cases, we would call platform.downcase! in some comparison conditions.

For example, below code snippet is to check the platform and action accordingly based on different platforms.

platform = "Suse"
case platform.downcase!
  when 'aix'
    puts "For AIX"
  when 'suse'
    puts "For suse"
end

The output will be "For suse". What if we change the code a bit.

platform = "suse"
case platform.downcase!
  when 'aix'
    puts "For AIX"
  when 'suse'
    puts "For suse"
end

Now nothing is printed out. "For suse" is not printed at all. What's going on? Reading the documentation one more time. It says that nil will be returned if the content is not changed. This means if the string to be downcased is already in lowercase, nothing will be changed and nil will be returned. Hence, platform.downcase! will return nil and no when condition is matched with nil and nothing will be printed.

The general advice is to avoid calling xxx! if you don't expect state change in place and if you are using them in comparison conditions.

RUBY EXCLAMATION MARK DOWNCASE

  RELATED

  COMMENTS

0

No comment for this article.