Class ActiveSupport::Multibyte::Chars
In: vendor/rails/activesupport/lib/active_support/multibyte/chars.rb
Parent: Object

Chars enables you to work transparently with multibyte encodings in the Ruby String class without having extensive knowledge about the encoding. A Chars object accepts a string upon initialization and proxies String methods in an encoding safe manner. All the normal String methods are also implemented on the proxy.

String methods are proxied through the Chars object, and can be accessed through the chars method. Methods which would normally return a String object now return a Chars object so methods can be chained.

  "The Perfect String  ".chars.downcase.strip.normalize # => "the perfect string"

Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made. If certain methods do explicitly check the class, call to_s before you pass chars objects to them.

  bad.explicit_checking_method "T".chars.downcase.to_s

The actual operations on the string are delegated to handlers. Theoretically handlers can be implemented for any encoding, but the default handler handles UTF-8. This handler is set during initialization, if you want to use you own handler, you can set it on the Chars class. Look at the UTF8Handler source for an example how to implement your own handler. If you your own handler to work on anything but UTF-8 you probably also want to override Chars#handler.

  ActiveSupport::Multibyte::Chars.handler = MyHandler

Note that a few methods are defined on Chars instead of the handler because they are defined on Object or Kernel and method_missing can‘t catch them.

Methods

<=>   =~   gsub   handler   handler=   method_missing   new   respond_to?   split   to_str  

Included Modules

Comparable

External Aliases

string -> to_s

Attributes

string  [R] 

Public Class methods

Set the handler class for the Char objects.

[Source]

     # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 106
106:     def self.handler=(klass)
107:       @@handler = klass
108:     end

Create a new Chars instance.

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 53
53:     def initialize(str)
54:       @string = str.respond_to?(:string) ? str.string : str
55:     end

Public Instance methods

Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the object on the right side of the operation. It accepts any object that implements to_s. See String.<=> for more details.

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 60
60:     def <=>(other); @string <=> other.to_s; end

Like String.=~ only it returns the character offset (in codepoints) instead of the byte offset.

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 72
72:     def =~(other)
73:       handler.translate_offset(@string, @string =~ other)
74:     end

Gsub works exactly the same as gsub on a normal string.

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 69
69:     def gsub(*a, &b); @string.gsub(*a, &b).chars; end

Returns the proper handler for the contained string depending on $KCODE and the encoding of the string. This method is used internally to always redirect messages to the proper classes depending on the context.

[Source]

     # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 112
112:     def handler
113:       if utf8_pragma?
114:         @@handler
115:       else
116:         ActiveSupport::Multibyte::Handlers::PassthruHandler
117:       end
118:     end

Try to forward all undefined methods to the handler, when a method is not defined on the handler, send it to the contained string. Method_missing is also responsible for making the bang! methods destructive.

[Source]

     # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 78
 78:     def method_missing(m, *a, &b)
 79:       begin
 80:         # Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers.
 81:         if m.to_s =~ /^(.*)\!$/ && handler.respond_to?($1)
 82:           result = handler.send($1, @string, *a, &b)
 83:           if result == @string
 84:             result = nil
 85:           else
 86:             @string.replace result
 87:           end
 88:         elsif handler.respond_to?(m)
 89:           result = handler.send(m, @string, *a, &b)
 90:         else
 91:           result = @string.send(m, *a, &b)
 92:         end
 93:       rescue Handlers::EncodingError
 94:         @string.replace handler.tidy_bytes(@string)
 95:         retry
 96:       end
 97:       
 98:       if result.kind_of?(String)
 99:         result.chars
100:       else
101:         result
102:       end
103:     end

Make duck-typing with String possible

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 45
45:     def respond_to?(method, include_priv = false)
46:       super || @string.respond_to?(method, include_priv) ||
47:         handler.respond_to?(method, include_priv) ||
48:         (method.to_s =~ /(.*)!/ && handler.respond_to?($1, include_priv)) ||
49:         false
50:     end

Works just like String#split, with the exception that the items in the resulting list are Chars instances instead of String. This makes chaining methods easier.

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 64
64:     def split(*args)
65:       @string.split(*args).map { |i| i.chars }
66:     end

The magic method to make String and Chars comparable

[Source]

    # File vendor/rails/activesupport/lib/active_support/multibyte/chars.rb, line 38
38:     def to_str
39:       # Using any other ways of overriding the String itself will lead you all the way from infinite loops to
40:       # core dumps. Don't go there.
41:       @string
42:     end

[Validate]