

## 環境

ruby2.2.7  
rails4.2.9

## 事象

以下のようにform_forでパラメータを飛ばすとパラメータの中身がascii-8bitになりEncoding::CompatibilityErrorが出てしまいます。

[code]

    = form_for @hoge, :url => {:action => :update} do |f|
      = hidden_field_tag('authenticity_token', form_authenticity_token)
      = f.submit "保存する"
    
[/code]

パラメータの中身は以下です。utf8の箇所をみてください。

[code]

    Processing by HogeController#update as HTML
      Parameters: {"utf8"=>"\xE2\x9C\x93", "authenticity_token"=>"jWj10656mdI5VHn+sa}
    
[/code]

rails4.1.16だと意図通りになっています。

[code]

    Processing by HogeController#update as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"jWj10656mdI5VHn+sa}
    
[/code]

なにが原因そうなのかすら検討もつきません。よろしくお願いします。  
「何か追加で情報があれば検討つくかもしれない」ということなら追加で出しますのでご教授願います。

ちなみにGemfileは以下です

[code]

    source 'http://rubygems.org'
    
    gem 'rails', '4.2.9'
    gem 'rake' , '10.0.4'
    
    gem 'mysql2', '0.3.14'
    
    gem 'switch_point', '0.8.0'
    gem 'google-api-client', '0.8.0'
    gem 'tzinfo', '~> 1.1'
    gem "paranoia", "~> 2.2"
    gem 'jquery-rails', '~> 3.0'
    gem 'will_paginate', '~> 3.0'
    gem 'selectable_attr_rails', '0.3.14'
    gem 'selectable_attr', '0.3.17'
    gem 'acts_as_tree''
    gem 'rmagick', '2.16.0'
    gem 'date_validator'
    gem 'crummy', '1.2'
    gem 'pdfkit', '0.5.2'
    gem 'sanitize', '2.0.6'
    gem 'jpmobile', '3.0.2' # :git => "git://github.com/jpmobile/jpmobile.git" , :tag => "v1.0.0.pre"
    gem 'garb', '0.9.1'
    gem 'settingslogic', '2.0.8'
    gem 'unicorn', '4.8.3'
    gem 'omniauth-facebook', '4.0.0'
    
    gem 'delayed_job', '~> 4.0.3'
    gem 'delayed_job_active_record', '~> 4.0.2'
    gem 'daemons', '1.1.8'
    gem 'rack_after_reply'
    
    gem "romankana", "~> 0.1.3"
    gem 'kaminari'
    gem 'active_decorator'
    gem "RubyInline"
    
    source 'http://gems.github.com/'
    gem 'googlecharts', '1.6.8'
    
    gem "redis", "2.2.1"
    gem "redis-rails"
    gem "redis-objects"
    gem 'activerecord-session_store'
    
    gem 'rack-pjax'
    gem 'fluent-logger'
    gem 'fingerprintjs-rails'
    
    gem 'natto'
    gem 'active_hash'
    gem 'public_suffix'
    
    gem "msgpack"
    
    gem 'react-rails', '~> 1.0'
    gem 'slim-rails'
    gem 'business_time'
    
    gem 'test-unit', '~> 3.0'
    
    gem 'rails-observers'
    
    gem 'actionpack-page_caching'
    
    gem 'activeresource', require: 'active_resource'
    
    gem 'sass-rails',   '5.0.6'
    gem 'compass-rails', '3.0.2'
    gem 'uglifier', '>= 1.0.3'
    gem 'execjs'
    
[/code]

## 追記1

config/appication.rbに以下を追加

[code]

    config.middleware.insert_before ActionDispatch::ParamsParser, "ForceParamsEncoding"
    
[/code]

lib/test.rbというファイルを作成

[code]

    class ForceParamsEncoding
      def initialize(app)
        @app = app
      end
    
      def call(env)
        @request = Rack::Request.new(env)
        params = @request.params
        params.each do |k, v|
          if v.class == Array
            array = []
            array << force_encoding_utf_1(v[0])
            params[k] = array
          elsif v.class == Hash
            params[k] = force_encoding_utf_1(v)
          else
            params[k] = v.force_encoding("UTF-8")
          end
        end
        @app.call(env)
      end
    
      def force_encoding_utf_1(value)
        value.each do |k, v|
          if v.class == Array
            array = []
            array << force_encoding_utf_2(v[0])
            value[k] = array
          elsif v.class == Hash
            value[k] = force_encoding_utf_2(v)
          else
            value[k] = v.force_encoding("UTF-8")
          end
        end
        return value
      end
    
      def force_encoding_utf_2(value)
        value.each do |k, v|
          if v.class == Array
            array = []
            array << force_encoding_utf_1(v[0])
            value[k] = array
          elsif v.class == Hash
            value[k] = force_encoding_utf_1(v)
          else
            value[k] = v.force_encoding("UTF-8")
          end
        end
        return value
      end
    end
    
[/code]

（メモなので一旦めちゃくちゃ汚いコードになってます。）

で `require "#{Rails.root}/lib/test"` と無理やり直すように一旦、対応しました。

何か別途方法わかる方いたら随時投げてくださると助かります。

## 追記2

gemが悪さしているというコメントいただいたのでそこは追記3として追加したいと思いますが。。  
一旦無理やり直したので追加します。追記1よりはマシかなと。

[code]

    lib/rack/utils.rb
    
    
         def parse_nested_query(qs, d = nil)
           params = KeySpaceConstrainedParams.new
    
           (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
             k, v = p.split('=', 2).map { |s| unescape(s) }
    　　　　　#unescape(s)部分をURI.decode_www_form_component(s, Encoding::UTF_8)とすると直りました。unescapeのメソッドがなんかおかしくなっている可能性が高いかなと。
    
             normalize_params(params, k, v)
           end
           return params.to_params_hash
         rescue ArgumentError => e
           raise InvalidParameterError, e.message
         end
    
[/code]


CC BY-SA 3.0
2017-08-16T11:15:07.437
37247
2018-03-20T07:38:39.930
2017-08-18T10:20:10.760
24370
24370
question
ruby-on-rails encoding
rails4.2でEncoding::UndefinedConversionError - "\xE6" from ASCII-8BIT to UTF-8:というエラーになります。


原因が判明しました。ご指摘いただいたようにgemが悪さをしていました。

[code]

    gem 'jpmobile', '3.0.2'
    
[/code]

こいつを最新にしたところ直りました。

[code]

    gem 'jpmobile', '~> 4.2'
    
[/code]


CC BY-SA 3.0
2017-08-18T10:20:35.507
37311
2017-08-18T10:20:35.507
24370
37247
answer