Rails 4からRails 5へ:いかにあったか

むかしむかし、クラウドサービスプロバイダーが存在し、進歩に追いつくことを望んでいました。 そして彼は、Rails 4.2.8からRails 5.0.2にアップグレードすることにしました。 そして、それがどのように、それが途中で落ちたのか、加速して額に当たったのか、これからどんな経験が得られたのか-猫の下で読んでください。







ほとんどの機能と問題は決して相互に関連していないため、断片的に説明します。 したがって、つまらないものや知られているものに出会ったら、次のポイントに進んでください。おそらく、もっと面白いでしょう。







ストーリーの目的:普遍的な遷移アルゴリズムはありません。見つかった情報と、Gemfileのバージョンを微調整するだけでRails 5に行くことができない理由についてのさまざまな程度の詳細を共有したいだけです。







既往歴



平均的なアプリケーションがあります:Ruby 2.2.3、数百の宝石の尾を持つ3つ、〜1500アクション、postgres、elastic、radish。 一般的に、特別なことは何もありません。 テストが90%+でカバーされていない限り。 これは、一部の最新のアプリケーションの特徴ではないようです。







最初から始める



Rails 5.2は間近に迫っていますが、メジャーバージョンの更新を急いでいる人はいません。 したがって、インターネットには、移行の機能に関する情報が必要なほど多くありません。 ここに多かれ少なかれ有益な記述があります5.0および5.1のリリースがあります(ところで、まだそれらをカウントしていないのは誰ですか?)。 Rails 5にアップグレードするための基本的な手順を示すオフガイドがあります。それは良いことですが、特に更新中に落ちるgem、それらの互換性、その他の経済性に関する詳細情報が必要です。 公平に言えば、より詳細に調べれば、2組の高貴な熊手に沿って歩くことはできなかったでしょう(詳細については後述)。 したがって、以下ではガイドからのいくつかのポイント(つまり、いくつかの基本的な変更)に言及しますが、それは私たちにとって非常に重要であることが判明しました。







重大な問題の原因またはTLではなく、DR





宝石の更新



何かが落ちるためには、何かを更新する必要があります。 当然、rails gemとその依存関係から始める必要があります。 ここでは、1日か2日過ごすことができますが、レシピはありません。 GemfileGemfile.lockの周りのタンバリンとのダンスがたくさんあり、プロジェクト内のすべてのかなりの半分を更新する必要があるという段階的な理解があるため、少なくとも動けなくなります。 手順は次のとおりです。









そのままの錫



今、すべてについて。







alias_method_chainは見られています



まだ知らない人のために: prepend



を行う必要があります。 要するに:誰もが知っているinclude



に、これはクラスの前ではなくクラスの後にモジュールを追加します。 おまけとして-メソッドの有無にかかわらずsuper



を取得します。 ここで詳細と例を参照してください。







多くの新しいデフォルト設定



それらはrails app:update



を介して生成されrails app:update



。 しかし、このタスクは非常に馬鹿げており、ファイルを作成するだけです。すでにファイルの1つを持っている場合は、自分でそれを保持してください。







宝石device_async



デバイスの新しいバージョンの場合、これは不要であり、 off.manuluの数行のコードに置き換えられます。 公平に言えば、これはRails 4.2以降で機能しますが、5つのレールでは最終的にgemが機能しなくなり、すべてをActiveJobに書き換える必要があります。







宝石缶



CanCanCanに置き換える必要があります 。 CanCanのサポートは不足しており、多くの廃止予定が次々と登場しているため、Rails 5.1では問題になります。 一般的に、交換に大きな問題はないはずです。 inherited_resourcesの下でCanCanドリルを行ったため、もう少し苦労しました。







ジェムグレープスワガー



持っていた 拡張 パッチバージョン。 彼は、リクエストでAPIキーを置き換える方法を知っていました。 しかし、Swaggerの最後のメジャーバージョンでは、彼は高貴な事件を見ました。 そのため、3.0への移行後、馴染みのあるランドマークを見つけることができず、古いパッチは愚かに挿入する場所がありませんでした。 その結果、カスタムHTTPヘッダー用のドキュメント化された機能があることが判明しましたが、うまくいかず、少し密輸しなければなりませんでし 。 これですべてが機能します。







has_manyアソシエーションに無効なオブジェクトを挿入します



無効なオブジェクトの関連付けがhas_manyに挿入されると、すべてがRails 5にドロップされます(オブジェクトは永続化されて無効になり、メモリ内でのみ作成されます)。 以前は、保存が行われ、データベースの元のオブジェクトが関連付けに追加され、メモリからの変更がスキップされた(または検証がスキップされた)か、xsに何が起こったのかが深く掘り下げられていませんでした







関係の連結



彼はどこかで離婚し、もう働いていません。







バグではなく、uniqの廃止



Uniqはdistinctに置き換えられ、5.1ではReilationのuniqが最終的にカットされます。 私が理解しているように、ついに実現したのは、リレーション、配列を模倣することは機能ではなく、多くのがらくたであるということです。







宝石postgres_ext



決定的に切り抜く必要があります。 彼が行う方法知っているのは、raw-sqlおよび/またはArelを使用して簡単に置き換えることです。 現時点では、gem自体はRails 5と互換性がありません。新しいレールで使用しようとすると、たとえばSTIクラスでcount



を呼び出す場合など、最も予期しない場所でエラーが発生しcount









 ArgumentError: wrong number of arguments (given 1, expected 2) # /Users/username/.rvm/gems/ruby-2.3.3@gemset/gems/arel-7.1.4/lib/arel/visitors/reduce.rb:12:in `visit' # /Users/username/.rvm/gems/ruby-2.3.3@gemset/gems/postgres_ext-3.0.0/lib/postgres_ext/arel/4.1/visitors/postgresql.rb:22:in `block in
      
      





宝石simple_form



何らかの理由で、私たちと一緒に彼にはほとんど何も起こりませんでした。 彼は仕事を続けました。 include_blank



を実行し、フィールドをrequire



機能が低下しました。







ActiveRecordのその他





コントローラーのパラメーター



現在、これはHashWithIndifferentAccess



ではなく、独立したクラスActionController::Parameters



であり、下位互換性のためにハッシュを模倣していますmerge



、ハッシュとして使用される場合、つまりmerge



update



などを行う場合、多くのことを誓います つまり、アイデアを正しく理解した場合、 params



2つの目標があります。クライアントからparams



ものを保存し、 Strong Parametersを使用してコンテンツをフィルタリングすることです。 他の変更を加えないでください。 つまり、 params



でデータを直接変更すると、独自のデータを追加するのと同じように味が悪くなります。 これらのアクション用に個別のオブジェクトをparams.to_h



か、 params.to_h



またはparams.to_unsafe_hash



を呼び出してから、以前と同じようにハッシュを処理します。







エラーによるモデルへのエラーの追加[] =



ActiveModel::Errors#[]=



Rails 5.1で見られますが、最終的にはmodel.errors.add(:name, "can't be blank")



を使用する必要model.errors.add(:name, "can't be blank")



。 もちろん、これに関するログ内のメッセージは存在します。







アレルについて少し



オブジェクト自体を転送するためにid



フィールドのArelからのeq



(および、おそらく同様の述語)で(他のフィールドではすべて問題ありません)、4レールで識別子(pk)がこのオブジェクトから引き出され、リクエストで置換されました。そして、5つのレールではこれは起こりません。 pkをプルしようとする代わりに、オブジェクトは単にNULLで置換され、「account_id = NULL」のようなものが取得されます。 例:







 #  Rails 4 MyModel.arel_table[:my_field].eq(MyModel.first).to_sql => "my_models"."my_field" = 1 MyModel.arel_table[:id].eq(MyModel.first).to_sql => "my_models"."id" = 1 #  Rails 5 MyModel.arel_table[:my_field].eq(MyModel.first).to_sql => "my_models"."my_field" = 1 MyModel.arel_table[:id].eq(MyModel.first).to_sql => "my_models"."id" = NULL
      
      





したがって、意味を常に明示的に示すようにしてください。







skip_callbackについて



4つのレールのskip_callback(:create, :after, :my_method)



を使用すると、パラメーターを転送でき、コールバックチェーンにそのようなメソッドがなくてもクラッシュしません。5つのレールでは、次のメソッドが見つからなかった場合、同じメソッドが実行されますスキップする必要があります。 したがって、奇妙な転倒が発生する可能性があり、「少年はいたのか?」を理解するために、産業考古学を掘り下げる必要があります。







レンダリングの小さな革命



変更:text



mime_type



を明示的に示す:text



およびその他の形式。 置換:nothing



:head



など つまり、彼らはその起源に戻り、名前を本質に近づけ、主婦が理解するのにアクセスできないようにします。







テスト実行の順序を変更する



現在、デフォルトの実行順序は:random



です。 テストが実行シーケンスに依存している場合、これはあまり良くありませんが、古い動作を返すのは非常に簡単です:







 Rails.application.configure do config.active_support.test_order = :sorted end
      
      





オブザーバー



今まで(またはすでに)5つのレールでそれらをサポートしている人はいません。 元のオブザーバーは4本のレールで停止しました。 ウィザードでは、5のサポートを宣言しましたが、何も機能しません。 5レールのオブザーバー代わる日本人がます(コピーアンドペーストやブランド変更に非常に似ています)が、これも機能しません。 最善の方法は、ネイティブのARコールバックを使用することです。







ActiveRecordのバグ



カップルを見つけました:









宝石の肩マッチャー



それを3.1.1に更新し、多くの異なる小さなものを得ました:









移行



インデックス名の形成方法と、後方互換性を完全に破った他のいくつかの方法を変更しました。 したがって、すべての移行に対して、それらが作成されたバージョンを明確に示す必要があります。 クラスパラメーターを使用して指定します。







 class OldMigrationName < ActiveRecord::Migration[4.2] ... end class NewMigrationName < ActiveRecord::Migration[5.0] ... end
      
      





また、 references



のオプションでforeign_key



を指定することもできました。 そして、ジェネレーターのデフォルト設定を少し変更しました :デフォルトでは、pk(このid)は整数ではなくuuidになります。







何らかの理由で、移行内のパターンの定義にも問題がありました。 つまり、フォームの一部で:







 class SomeMigration < ActiveRecord::Migration class StubForModel < ActiveRecord::Base has_one :something end def up StubForModel.destroy_all end def down # do nothing end end
      
      





誰かがBase



見つけられないと誓っています。 理由がわかるまで、注意してください。 解決方法-説明を更新します。







コントローラー内のコールバックのシーケンス



Rails 4でのcsrf



トークン(偽造からの保護)のチェックは常に上がり、コントローラーの最初のコールバックによって行われました。 Rails 5では、どこにも上がらず、定義された場所に従って実行されprepend: true



。上げる必要がある場合は、 prepend: true



明示的に指定する必要がありprepend: true









すべては問題ありませんが、最初に与えられたガイドを注意深く読んだようには見えませんでした。 認証が失敗しました。 デバイス全体を掘り起こし、ほとんど魔法を信じていました。 しかし、最初はデバイスがパラメータからトークンを正常に認証して切り取り、その後偽造から保護され、湾曲した(実際に欠落している)トークンに非常に怒っていることが判明しました。







マンキパッチ



「他の人への彼の例は科学です...」









なぜ私はこれをすべてやっているのですか: core_ext



はすべきではありません。 絶対に。 そして、新しいレールへの移行は、それらから始めて、できる限りカットして、非常にうるさい外観で他のすべてを見て、この拡張の出現前の歴史(間違いなく非常にまだらになっている)を覚えておくための大きな理由です。 そのため、移行中にいつ落ちるかを理解するのがはるかに簡単になります。







Rubyバージョンのアップグレード



正直なところ、私たちは習得していません。 2.2.3の後、2.4.0を強力にスタックして、私たちは未知のゴミの束をすくい取り、2つの段階に進むことを決めました:最初に、Ruby 2.3.3、これは非常に革命的なものはなく、新しいレールへの移行です。 そして-ルビーを更新します。 したがって、これまでのところ、新しいルビーについては何も言えません。 gemのネイティブ拡張をコンパイルした場合、移行の問題のほとんどは回避さ​​れ、深刻な障害はないという経験豊富な仲間の意見がない限り。







マジック(時間と欲求があるかどうかを考えるタスク)



新しいレールへの移行に関係なく、移行中に発掘されて機能したはずの奇妙なコードに過ぎませんが、そうすべきではありません(ARクラスの3つのファイルの要約)。







  class Base TYPES = {first: First, second: Second} end class First < Base; end class Second < Base; end
      
      





このことは、このジャンルのすべての法律により、機能しません(ただし、一般的にRails 4/5のクリーンプロジェクトでは機能しません)。 相続人のいずれかにアクセスすると、自動ロードはクラスの周期的なロードに入り、クラッシュします。 最初に基本クラスを使用し、次に相続人を使用する場合、すべてが正常です。 しかし、何らかの理由で、Rails 4では機能しましたが、Rails 5では落ちましたが、他のすべてよりも早くBase



をダウンロードする明示的な呼び出しを見つけることができず、自動ロードに関連するものはまったく触れませんでした。 他の誰かがそれがどのように機能するか、またはRails 5の自動ロードに何が起こったのかを知っているなら、私に知らせてください。







終わり



読んでくれてありがとう。 少なくとも何かがあなたの役に立つことを願っています(または既に便利になっていること)、そして移行のための時間を少なくとも少しは節約しました。







トピックに関するあなたの知識と経験ではなく、コメントで共有することをheしないでください。








All Articles