Rails4.2へのアップデートで苦労したこと



最近、とあるアプリケーションをRails4.2にアップデートしたので、忘れないうちに記録を残しておきます。


## 環境
Ruby: 2.2.1
Rails: 4.1.8 -> 4.2.1

## 事前準備
まずはRails Guidesを読まねば始まらない。

 * http://railsguides.jp/4_2_release_notes.html
 * http://railsguides.jp/upgrading_ruby_on_rails.html#rails-4.1%E3%81%8B%E3%82%89rails-4.2%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89


## トラブル1: foreigner
Rails4.2.1から[外部キーがサポート](http://railsguides.jp/4_2_release_notes.html#%E5%A4%96%E9%83%A8%E3%82%AD%E3%83%BC%E3%81%AE%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88)されるようになったが、元々導入していた foreigner と競合してしまった。


#### 対処方法
https://github.com/matthuhiggins/foreigner/issues/155 にも書かれている通り、foreigner を外すのが最善だと思われる。


具体的には Gemfile から foreigner を外し、migration ファイルを

```ruby
change_table :articles, bulk: true do |t|
  t.foreign_key :authors
end
```

から

```ruby
add_foreign_key :articles, :authors
```

に書き換えていく。


## トラブル2: ssl_requirement
ssl_requirement が url_for に alias_method_chainで patch を当てていた。
https://github.com/bartt/ssl_requirement/blob/v1.4.2/lib/url_for.rb

 
#### 対処方法
ssl_requirement は 3年以上開発が停止しており、only Rais3.x compatible なので、利用を諦めて force_ssl に置き換えることとした。

force_ssl だと https -> http のリダイレクトが出来ないが、これは諦めるしかない。



## トラブル3: DalliError
Unexpected exception in Dalli: NameError という謎のエラーが発生した。

```log
E, [2015-04-09T16:24:10.732376 #20655] ERROR -- : Unexpected exception in Dalli: NameError: uninitialized constant Arel::SqlLiteral
E, [2015-04-09T16:24:10.732479 #20655] ERROR -- : This is a bug in Dalli, please enter an issue in Github if it does not already exist.
E, [2015-04-09T16:24:10.732568 #20655] ERROR -- : /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:263:in `const_get'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:263:in `block in constantize'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `each'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `inject'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `constantize'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/core_ext/marshal.rb:10:in `rescue in load_with_autoloading'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/core_ext/marshal.rb:6:in `load_with_autoloading'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/server.rb:424:in `deserialize'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/server.rb:488:in `generic_response'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/server.rb:257:in `get'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/server.rb:60:in `request'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/options.rb:18:in `block in request'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/options.rb:17:in `request'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/client.rb:329:in `perform'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/client.rb:53:in `get'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:287:in `block in read_entry'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/dalli/client.rb:244:in `with'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:81:in `with'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:287:in `read_entry'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/cache/strategy/local_cache.rb:104:in `read_entry'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:91:in `block in fetch'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:350:in `block in instrument'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:166:in `instrument'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:350:in `instrument'
        /home/kotaroito/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/dalli-2.7.2/lib/active_support/cache/dalli_store.rb:90:in `fetch'
        /home/kotaroito/webapp/releases/20150409062836/app/controllers/categories_controller.rb:11:in `show'
```

コードを注意深く追いかけると、memcached から getしたデータを deserialize する際に、「"Arel::SqlLiteral" なんていう定数はないよ！」と怒られていることが分かる。


今度は [arel](https://github.com/rails/arel) を追いかけてみるが、[arel/sql_literal.rb](https://github.com/rails/arel/tree/v6.0.0/lib/arel)は見つからない。。。
「もしやバージョンアップで名前が変わったのか？」と思って、[v5.0.0](https://github.com/rails/arel/blob/v5.0.0/lib/arel/sql_literal.rb) を調べたらその通り！


つまり、gem の名前空間が変更になったためにシリアライズしたデータが読み出せなくなった、というオチでした。


#### 対処方法
原因が分かったので、キャッシュが expire するまで静かに見守ることにした。


## まとめ
 * foreigner 使えなくなったので外した
 * ssl_requirement 使えなくなったので外した
 * アップデート直後は、Dalliで Unexpected exception でるかも