rails omniauth and UTF-8 errors
I had a recent error using omniauth trying to populate some fields from Google's login
Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8
"omniauth"=>
{"user_info"=>
{"name"=>"Joe McÙisnean",
"last_name"=>"McÙisnean",
"first_name"=>"Joe",
"email"=>"someemail@gmail.com"},
"uid"=>
"https://www.google.com/accounts/o8/id?id=AItOawnQmfdfsdfsdfdsfsdhGWmuLTiX2Id40k",
"provider"=>"google_apps"}
In my user model
def apply_omniauth(omniauth)
#add some info about the user
self.email = omniauth['user_info']['email'] if email.blank?
self.name = omniauth['user_info']['name'] if name.blank?
self.name = omniauth['user_info'][:name] if name.blank?
self.nickname = omniauth['user_info']['nickname'] if nickname.blank?
self.nickname = name.gsub(' ','').downcase if nickname.blank?
unless omniauth['credentials'].blank?
user_tokens.build(:provider => omniauth['provider'],
:uid => omniauth['uid'],
:token => omniauth['credentials']['token'],
:secret => omniauth['credentials']['secret'])
else
user_tokens.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
end
end
I'm not hugely knowledgeable about UTF encoding, so I'm not sure where I should be specifying the encoding? But I'm guessing it's here before it get's put into the user model and created, I'm unsure what to do about it?
UPDATE:
Rails 3.0.10 Omniauth 0.2.6 Ruby 1.9.2 PG 0.11.0
Default encoding is UTF-8
That didn't seem to be it, so I dug further and found this in the view:
Showing /Users/holden/Code/someapp/app/views/users/registrations/_signup.html.erb where line #5 raised:
incompatible character encodings: ASCII-8BIT and UTF-8
Extracted source (around line #5):
2: <%= f.error_messages %>
3:
4: <%= f.input :name, :hint => 'your real name' %>
5: <开发者_如何学C;%= f.input :nickname, :hint => 'Username of your choosing' %>
6:
7: <% unless @user.errors[:email].present? or @user.email %>
8: <%= f.input :email, :as => :hidden %>
UPDATE UPDATE:
It seems to be the omniauth gem which is returns the ASCII-8BIT chars, so my next question is how can I parse the hash and convert it back into UTF8 so my app doesn't explode?
session[:omniauth] = omniauth.to_utf8
Another part to this crazy ride is when I type this into the console
d={"user_info"=>{"email"=>"someemail@gmail.com", "first_name"=>"Joe", "last_name"=>"Mc\xC3\x99isnean", "name"=>"Joe Mc\xC3\x99isnean"}}
It automatically converts it to UTF-8, but it explodes when shoved into a session
=> {"user_info"=>{"email"=>"someemail@gmail.com", "first_name"=>"Joe", "last_name"=>"McÙisnean", "name"=>"Joe McÙisnean"}}
This is a painful nightmare if there ever was one.
Omniauth proved to be the problem producing the ASCII-8BIT
I ended up forcing the Omniauth hash into submission using:
omniauth_controller.rb
session[:omniauth] = omniauth.to_utf8
added recursive method to force convert the rogue ASCII-8BIT to UTF8
some_initializer.rb
class Hash
def to_utf8
Hash[
self.collect do |k, v|
if (v.respond_to?(:to_utf8))
[ k, v.to_utf8 ]
elsif (v.respond_to?(:encoding))
[ k, v.dup.force_encode('UTF-8') ]
else
[ k, v ]
end
end
]
end
end
Special thanks to tadman
recursively convert hash containing non-UTF chars to UTF
精彩评论