Ruby
Rails

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

More than 5 years have passed since last update.

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になっています。

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

# 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した関連レコードの値をメソッドチェインで利用して、検索条件に含める事ができました。

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

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

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

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

ちょっと面倒な気がする。

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

## find_by_xxxメソッド無くなった (ぐあっと書いたら嘘書いてたので修正)

これは、一切使ってなかったので問題無し。


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で呼ばれなくなってる事が、期待通りの結果にならない理由のようです。

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