rails4.2でEncoding::UndefinedConversionError - "\xE6" from ASCII-8BIT to UTF-8:というエラーになります。
環境
ruby2.2.7
rails4.2.9
事象
以下のようにform_forでパラメータを飛ばすとパラメータの中身がascii-8bitになりEncoding::CompatibilityErrorが出てしまいます。
= form_for @hoge, :url => {:action => :update} do |f|
= hidden_field_tag('authenticity_token', form_authenticity_token)
= f.submit "保存する"
パラメータの中身は以下です。utf8の箇所をみてください。
Processing by HogeController#update as HTML
Parameters: {"utf8"=>"\xE2\x9C\x93", "authenticity_token"=>"jWj10656mdI5VHn+sa}
rails4.1.16だと意図通りになっています。
Processing by HogeController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"jWj10656mdI5VHn+sa}
なにが原因そうなのかすら検討もつきません。よろしくお願いします。
「何か追加で情報があれば検討つくかもしれない」ということなら追加で出しますのでご教授願います。
ちなみにGemfileは以下です
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'
追記1
config/appication.rbに以下を追加
config.middleware.insert_before ActionDispatch::ParamsParser, "ForceParamsEncoding"
lib/test.rbというファイルを作成
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
(メモなので一旦めちゃくちゃ汚いコードになってます。)
で require "#{Rails.root}/lib/test"
と無理やり直すように一旦、対応しました。
何か別途方法わかる方いたら随時投げてくださると助かります。
追記2
gemが悪さしているというコメントいただいたのでそこは追記3として追加したいと思いますが。。
一旦無理やり直したので追加します。追記1よりはマシかなと。
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