Contrary to popular belief, and many misleading beginners' ruby guides, bang methods do not mean "this method mutates the object".
That's usually the case, but not always.
A better interpretation of the convention for bang methods is "this is a more dangerous version of its non-bang counterpart".
For example:
String#gsub!
is the "dangerous" version of String#gsub
, since it mutates the object.
ActiveRecord::Base#save!
is the "dangerous" version of ActiveRecord::Base#save
, since it raises an exception if validation fails.
exit!
is the "dangerous" version of exit
, since the former exits immediately, whereas the latter actually raises an exception - which could be rescued elsewhere in the code.
Furthermore, note that there are plenty of ruby methods that do mutate the object but aren't bang methods. For example, String#delete
and Array#pop
.
This article goes into more detail on the matter.
So, (warning: opinionated response!) I would argue that:
- It's fine for
String#force_encoding
to be a non-bang method. This is not completely inconsistent with other conventions in the language.
- If it were a bang method, it would require a non-bang counterpart for consistency.
- I, personally, don't think the use case for a non-mutating
String#force_encoding
is common enough to warrant its creation. In the rare case that you actually wanted to do this, you could write: string.dup.force_encoding(...)
.