Rails4へのアップデート時に引っかかったポイントいくつか

Rails 4.0.0がリリースされたので今参加しているプロジェクトのアプリのアップデートが出来るかを試してみました。

やってみた結果としては、2.3 -> 3.0や、3.0 -> 3.1に比べると大分楽にバージョンアップできる感じです。

たまたま今のプロジェクトで引っかかった問題について、メモがてらまとめておきます。

## rake rails:update
diffを見ながらconfigファイルを書き換える。
そんなに大きな変更は無い。
rails4からはinitializerに色々移せって感じで、application.rbが軽量化されてるけど、元のままでも別に問題無い。
設定項目の重複だけ注意。

## strong_parameters
元々、gemで先行導入して取り入れていたので概ね問題無く移行できました。

attr_accesibleを利用したセキュリティ対策は、外部のgemに分離されているため、
`config.active_record.whitelist_attributes = false`が残っていると警告されます。
attr_accesibleを使いたい場合は、protected_attributesというgemで対応できますが、素直にstrong_parametersに移行する方が良いんじゃないでしょうか。

気を付けておきたいのはdeviseです。
deviseのカスタムコントローラー等を利用していると、strong_parametersの対応を忘れてしまって、いきなりログインできなくなったり、ユーザー登録出来なくなったりします。
というか私は、いきなりテストが落ちてしばらく悩みましたw

後、rails_adminはとりあえず大丈夫でした。

## ActiveRecordの関連の記述方法
has_many等の関連は、conditionsというオプションでベースとなるレコードの情報を利用して条件指定を追加できる機能がありましたが、deprecatedになっています。

こんな感じで書けって事らしい。

```rb:
# before
has_many :comments, conditions: ->(record) { ["comments.writer_id = ?", record.owner_id] }

# after
has_many :comments, ->(record) { where(writer_id: record.owner_id) }
```

## ActiveRecordのfinderメソッドとSunspot
SunspotというSolrから検索した結果とActiveRecordを連携させるgemを利用しています。
Rails4で動作こそしますが、内部で`scoped`を利用しているため、deprecatedがガンガン出ます。
Rails4からは`all`を使うのが正しいですね。

現時点(2013/7/8)でpull requestは既に上がっていますが、まだマージされていないので、ちゃんと直るのはもうちょっと先じゃないかな。
わざわざフォークするのも面倒だし、様子見中です。

## ActiveRecordのincludesで読み込んだ関連の値を利用するためのreferencesメソッド
今まで以下のような感じでincludesでeager loadingした関連レコードの値をメソッドチェインで利用して、検索条件に含める事ができました。

```rb:
Comment.includes(:post).where("posts.published = ?", true)
```

4.0.0ではこの記述はdeprecatedとなり、includesで読み込んだレコードの値を利用したい時は明示的にreferencesを呼ぶようになりました。

```rb:
Comment.includes(:post).where("posts.published = ?", true).references(:posts)
```

以前のままだとSQLのパーサー書くのが大変になるかららしいです。
ちょっと面倒な気がする。

これの影響で、Sunspotでまたdeprecatedが出ます。

<del>## find_by_xxxメソッド無くなった</del> (ぐあっと書いたら嘘書いてたので修正)
<del>これは、一切使ってなかったので問題無し。<del>

## find_all_by_xxxとかがdeprecatedになった。
これは、一切使ってなかったので問題無し。
`find_by`を使うようにする。

## rspecでトランザクションが上手く動かない
rspecとdatabase_cleanerを利用しているのですが、トランザクションのロールバックを期待して記述していたテストケースが急に落ちるようになりました。
どうもfixtureの読み込み処理が修正されたのが原因らしいです。

rspec v2.14
database_cleaner githubのmaster
を利用していますが、詳細まで追っかけてないので詳しくは不明です。
どなたかご存知でしたら解決策を教えてください…。

追記 (2013/7/9)
@yuki24 さんのコメントを受けて、再現するテストケースとログを用意してみました。
データベースはmysql2です。

v4.0.0: https://github.com/joker1007/transaction_test
v3.2.13: https://github.com/joker1007/transaction_test3


4.0.0 のtest.log
```
[1m[36mActiveRecord::SchemaMigration Load (0.2ms)[0m [1mSELECT `schema_migrations`.* FROM `schema_migrations`[0m
  [1m[35m (0.2ms)[0m SELECT @@FOREIGN_KEY_CHECKS
  [1m[36m (0.1ms)[0m [1mSET FOREIGN_KEY_CHECKS = 0[0m
  [1m[35m (0.1ms)[0m SELECT DATABASE() as db
  [1m[36m (0.3ms)[0m [1mselect table_name from information_schema.views where table_schema = 'transaction_test_test'[0m
  [1m[35m (5.2ms)[0m TRUNCATE TABLE `posts`;
  [1m[36m (0.1ms)[0m [1mSET FOREIGN_KEY_CHECKS = 1[0m
  [1m[35m (0.1ms)[0m BEGIN
  [1m[36m (0.1ms)[0m [1mCOMMIT[0m
  [1m[35m (0.0ms)[0m BEGIN
  [1m[36m (0.2ms)[0m [1mSELECT COUNT(*) FROM `posts`[0m
  [1m[35mSQL (0.2ms)[0m INSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:08:29', 'title0', '2013-07-09 05:08:29')
  [1m[36mSQL (0.1ms)[0m [1mINSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:08:29', 'title1', '2013-07-09 05:08:29')[0m
  [1m[35mSQL (0.1ms)[0m INSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:08:29', 'title2', '2013-07-09 05:08:29')
  [1m[36m (0.1ms)[0m [1mSELECT COUNT(*) FROM `posts`[0m
  [1m[35m (0.8ms)[0m ROLLBACK
```

3.2.13 のtest.log
```
Connecting to database specified by database.yml
  [1m[36m (0.1ms)[0m [1mSELECT @@FOREIGN_KEY_CHECKS[0m
  [1m[35m (0.1ms)[0m SET FOREIGN_KEY_CHECKS = 0
  [1m[36m (0.1ms)[0m [1mSELECT DATABASE() as db[0m
  [1m[35m (0.2ms)[0m select table_name from information_schema.views where table_schema = 'transaction_test3_test'
  [1m[36m (5.7ms)[0m [1mTRUNCATE TABLE `posts`;[0m
  [1m[35m (0.1ms)[0m SET FOREIGN_KEY_CHECKS = 1
  [1m[36m (0.1ms)[0m [1mBEGIN[0m
  [1m[35m (0.1ms)[0m SAVEPOINT active_record_1
  [1m[36m (0.1ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m
  [1m[35m (0.0ms)[0m BEGIN
  [1m[36m (0.1ms)[0m [1mSELECT COUNT(*) FROM `posts` [0m
  [1m[35m (0.1ms)[0m SAVEPOINT active_record_2
  [1m[36mSQL (0.1ms)[0m [1mINSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:07:08', 'title0', '2013-07-09 05:07:08')[0m
  [1m[35mSQL (0.2ms)[0m INSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:07:08', 'title1', '2013-07-09 05:07:08')
  [1m[36mSQL (0.1ms)[0m [1mINSERT INTO `posts` (`created_at`, `title`, `updated_at`) VALUES ('2013-07-09 05:07:08', 'title2', '2013-07-09 05:07:08')[0m
  [1m[35m (0.1ms)[0m ROLLBACK TO SAVEPOINT active_record_2
  [1m[36m (0.1ms)[0m [1mSELECT COUNT(*) FROM `posts` [0m
  [1m[35m (0.7ms)[0m ROLLBACK
  [1m[36m (0.1ms)[0m [1mROLLBACK[0m
```

色々試してみた所、`DatabaseCleaner.strategy`が`:truncation`だと4.0.0でも正常に終了するようです。
`:trunsaction`時はsavepointを利用する事でARのtransactionを実現していた部分が、4.0.0で呼ばれなくなってる事が、期待通りの結果にならない理由のようです。

引っかかった点といえば、こんな所です。