Rails incompatible character encodings: UTF-8 and ASCII-8BIT

steven_yue · 2013年06月13日 · 最后由 steven_yue 回复于 2013年06月16日 · 6774 次阅读

大家好啊,

我用omniauth-weibo-oauth2 做了个用微博注册的功能,主要流程就是从微薄获得用户名,和邮箱 (如果有的话),然后转到我的网站自身的注册页面 (这个时候用户名已经根据微薄的用户名填好了),完成后面的注册

基本过程就是将返回的env["omniauth.auth"] 存到一个 devise 的 session 里 session["devise.oauth_data"],然后在 User中添加一个下面这样的方法:

def self.new_with_session(params, session)
    # puts "Here"
    # puts session["devise.oauth_data"]
    super.tap do |user|
      if session["devise.oauth_data"].present?
        user.email = session["devise.oauth_data"].info.email if user.email.blank?
        user.username = session["devise.oauth_data"].info.nickname.dup.force_encoding('UTF-8') if user.username.blank?
        user.oauth = true
        user.provider = session["devise.oauth_data"].provider
      end
    end
  end

这样能成功注册,但是当用户名是中文的时候,就总会出编码错误:ActionView::Template::Error (incompatible character encodings: UTF-8 and ASCII-8BIT):仍然能注册成功 。让我头痛的是,怎么会在 create 以后出错。backtrace 显示的错误是这样的:

app/views/devise/registrations/new.html.erb:24 block in _app_views_devise_registrations_new_html_erb__FRAGMENT__
actionpack-3.2.13/lib/action_view/helpers/capture_helper.rb:40 block in capture
actionpack-3.2.13/lib/action_view/helpers/capture_helper.rb:187 with_output_buffer
actionpack-3.2.13/lib/action_view/helpers/capture_helper.rb:40 capture
actionpack-3.2.13/lib/action_view/helpers/form_helper.rb:378 form_for
simple_form-2.1.0/lib/simple_form/action_view_extensions/form_helper.rb:29 block in simple_form_for
simple_form-2.1.0/lib/simple_form/action_view_extensions/form_helper.rb:48 with_simple_form_field_error_proc
simple_form-2.1.0/lib/simple_form/action_view_extensions/form_helper.rb:28 simple_form_for
app/views/devise/registrations/new.html.erb:21 _app_views_devise_registrations_new_html_erb__FRAGMENT__

其中提到的错误来源是注册表格的这一行:

<%= f.input :username, label: t("form.username"), :required => true %>

首先,不明白 devise 怎么会在 create user 成功后又跳到 registration new form?然后是关于 UTF-8 的问题,我试着在 username 上 force_encoding, 像这样:

user.username = session["devise.oauth_data"].info.nickname.dup.force_encoding('UTF-8')

还是不行。求各位大侠帮忙啊。谢谢大家!

你可以在模板出错的略前面一点的地方插入个 binding.pry inspect 一下那个字符串,或者手动执行下 helper 看看确切的错误出在哪一步

#1 楼 @luikore 现在这个注册后的 redirect 都有问题,正常情况下 (username 是字符的时候),注册成功后会 redirect 到首页上,中文 username 的时候,注册成功后,又会去 render registrations/new,我尝试用 devise wiki 上的方法,直接更改注册后的 redirect path,我是在application controller下,添加这个方法

def after_sign_in_path_for(resource_or_scope)
   root_path
 end

这个函数是执行了,但就是不会 redirect 到 root。不知道为什么。。。我觉得注册后只要它不再 render registrations/new 就应该解决了

昨天才遇到几乎同样的问题,google 后的解决方法 str.force_encoding("GBK").encode("UTF-8")

#2 楼 @steven_yue 大概根源原因可能是中文 username 注册失败吧,我觉得应该把 user 的信息弄出来看看是什么才知道

#3 楼 @goophy 用了 force_encoding("GBK") 结果报:

Encoding::InvalidByteSequenceError (incomplete "\x91" on GBK)

#6 楼 @goophy 放弃了,最后 override 了 devise registration controller 解决了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号