Checking whether two strings are isomorphic
Looking at your isomorphism helper function…

The flow of control is kind of nasty.  In particular, burying an unless in here…

if …
  raise Exception.new(…) unless …
elsif …
  raise
end


… is too tricky, because:


You already have an if-elsif expression, and it would be better to work it into the same chain.
It's at the end of a very long line, where it is barely visible.
unless, being a negation, is automatically less preferable to an affirmative if.


Switching the naming convention from string_a, string_b to char_one, char_two is not ideal.  Why not char_a, char_b?  Or better yet, just a, b?

Doing Hash lookups in reverse using value? is not efficient.  You would be better off making a "forward" map and an "inverse" map.  See below for an even better way to decompose the problem.

As for the use of exceptions internally, I think it's a bad idea.  It's just a cumbersome way to return false with commentary.  You could just write a comment to avoid the overhead.  Better yet, if you write the code well, I don't think there is a need for any comment.  For example, in the implementation below, b != expected_b is pretty self-explanatory.

module Isomorphism

  def self.isomorphic?(string_a, string_b)
    surjective?(string_a, string_b) &amp;&amp; surjective?(string_b, string_a)
  end

  protected
  def self.surjective?(string_a, string_b)
    return false if string_a.size != string_b.size
    surjection = {}

    string_a.chars.zip(string_b.chars).each do |a, b|
      expected_b = surjection[a]
      if expected_b &amp;&amp; (b != expected_b)
        return false
      end
      surjection[a] = b
    end
    true
  end

  # Alternate implementation: shorter, but won't detect failure as quickly
  def self.surjective?(string_a, string_b)
    return false if string_a.size != string_b.size
    pairs = string_a.chars.zip(string_b.chars)
    surjection = Hash[pairs]
    pairs.all? { |a, b| surjection[a] == b }
  end

end