13

Is there a solution to use String.force_encoding() in Ruby 1.8.7 (or Rails 2.x) so that it works like in Ruby 1.9? I read something about require active_support, but this does not work

$> gem list --local | grep 'rails\|activesupport'

 activesupport (3.0.3, 2.3.8, 2.3.5)
 rails (2.3.8, 2.3.5)

$> ruby -v

ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]

$> rails -v

Rails 2.3.8

irb:

> require "rubygems"
=> true 
> require "active_support"
=> true 
> "asdf".force_encoding("UTF-8")
NoMethodError: undefined method `force_encoding' for "asdf":String
> String.respond_to?(:force_encoding)
=> false
f00860
  • 3,486
  • 7
  • 41
  • 59

2 Answers2

21

This will give you String#to_my_utf8 in both Ruby 1.8.7 and Ruby 1.9:

require 'iconv'
class String
  def to_my_utf8
    ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', self + ' ')[0..-2]
  end
end

And then...

?> "asdf".to_my_utf8
=> "asdf"

Inspired by Paul Battley and also remembering some of my older work on the remote_table gem.

Seamus Abshere
  • 8,326
  • 4
  • 44
  • 61
  • 1
    Out of curiosity: why add two spaces and then remove them after the conversion? – Theo Jan 03 '11 at 15:19
  • 3
    That's Paul Battley's contribution... as he says, "The ‘dangerous’ bytes are those in the range 194-253"... if the string ends with one of those, the conversion sometimes blows up. – Seamus Abshere Jan 03 '11 at 15:49
  • Why do you need rubygems? Also, where do you suggest placing the top code? in the controller of every controller you can to use it in? – AnApprentice Jan 23 '11 at 02:50
  • 1
    I'd say just put require "iconv" once, somewhere, as a matter of style. Good point... we don't need rubygems! – Seamus Abshere Jan 24 '11 at 14:55
  • It seems like this solution can't handle unicode é characters, could that be true? – Jasper Kennis Jul 03 '12 at 08:54
14

The only thing force_encoding does in 1.9 is that it changes the encoding field of the string, it does not actually modify the string's bytes.

Ruby 1.8 doesn't have the concept of string encodings, so force_encoding would be a no-op. You can add it yourself like this if you want to be able to run the same code in 1.8 and 1.9:

class String
  def force_encoding(enc)
    self
  end
end

There will of course be other things that you have to do to make encodings work the same across 1.8 and 1.9, since they handle this issue very differently.

Theo
  • 131,503
  • 21
  • 160
  • 205
  • Probably a stupid question, but where in my code should I be adding this? – RealCasually May 09 '12 at 06:25
  • Anywhere will do, more or less. Put it in a file and add a `require` for that file along with all your other `require`s at the top of your "main" `.rb`. – Theo May 10 '12 at 07:06