Rails 6の機能:新機能とその重要性
公開: 2022-03-11ほとんどのRubyonRailsファンが知っているかもしれませんが、Rails 6は間もなく登場し、待望の多くの機能と変更をもたらします。 この記事の目的は、Rails 6に追加された主要な機能を理解し、それらがアプリケーションの改善にどのように役立つかを概説し、貴重な開発時間を節約することです。
手始めに、Rails6にはRuby2.5以降とアップグレードされたデータベースが必要であることを忘れないでください。 したがって、まだアップグレードしていない場合は、それに応じてシステムをアップグレードする計画があることを確認してください。
では、これらの新機能は何ですか? これは、今後使用する可能性のあるRails6の主な機能の簡単な要約です。
Rails6でのテスト
プロのRubyonRails開発者として、私たちはコードを最大限にカバーすることを目指しています。 ただし、テストケースが「重く」なり、テストケースを実行するためだけに数分、場合によっては数時間待たなければならない場合、テストは退屈な作業になります。
並列テスト
さて、Rails6にはここで答えがあります。 ActiveSupport::TestCase
にparallelize
化メソッドが追加され、フォークされたプロセスでテストスイートを並列化できるようになりました。
したがって、テストのプロセスを並列化するために必要なことは、これをtest_helper.rb
に追加することです。
parallelize(workers: 2)
または、テストを実行するために以前に使用したコマンドを置き換えることもできます。 たとえば、 bin/rails test OR bin/rspec spec
は、 PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec
に置き換えることができます。
したがって、Travis、Gitlab、CircleCIなどのさまざまなCIプラットフォームでテストスイートを実行するためのコマンドを変更できます。
各プロセスが作成/破棄されるときのフックもあり、次のように使用できます。
class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end
注:詳細については、Railsガイドで詳細を確認してください。
アクションケーブルテスト
効率的なテストについて話していたので、Rails5の最も顕著な機能の1つであるアクションケーブルがどのように改善されたかについても理解しましょう。 これで、接続、チャネル、ブロードキャストなど、あらゆるレベルでアクションケーブルをテストできます。
接続テストの目的は、接続の識別子が適切に割り当てられているかどうか、または不適切な接続要求が拒否されているかどうかを確認することです。
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end
チャネルテストは、ユーザーがチャネルにサブスクライブでき、チャネルにストリームがあるかどうかを確認するために作成できます。
class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end
チャネルへのブロードキャストは、次のようにテストできます。
# app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end
注:テスト方法に関するその他のヒントは、こちらにあります。
一括挿入とアップサート
ある時点で、一度に複数のレコードを挿入する必要があり、そうすることで多くの回避策が見つかりました。 さて、Rails 6には、 update_all
と同様に、すぐに使用できる新しいメソッドinsert_all
が付属しています。
コールバックは発生せず、単一のSQLクエリを実行します。 Postgresのような多くの最新のデータベースによって公開されているupsert操作を使用できるようにする追加のメソッドupsert_all
があります。 これで、挿入クエリを減らし、コードをより最適化することができます。 また、 activerecord-import
ような以前に使用されたgemに別れを告げます。
これらのメソッドによって単一のINSERT
クエリが準備され、モデルをインスタンス化したり、Active Recordのコールバックや検証を呼び出したりすることなく、単一のSQLステートメントがデータベースに送信されます。 アップサートクエリをスキップまたは実行するオプションを使用して、主キー(一意のインデックスまたは一意の制約に違反している場合)の基準を定義することもできます。
いくつかの例を以下に示します。
result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )
メソッドinsert
、 insert!
とupsert
は、 insert_all
、 insert_all!
それぞれ、 upsert_all
。
注:さまざまなデータベースに関する一括クエリについて説明している非常に優れた記事があります。 追加情報が必要な場合は、必ずチェックしてください。
複数のデータベース間の切り替え
多くの大きなアプリケーションが高く評価する主な機能の1つは、これです。Rails6は、アプリケーションの複数のデータベースのサポートをついに追加しました。
もちろん、アプリケーションを複数のマイクロサービスに分割し、それぞれに個別のデータベースを持たせるか、モノリシックルートを使用するか、アプリケーションに複数の読み取りレプリカを追加するかどうかにかかわらず、設計の選択は依然としてあなた次第です。
ただし、このように簡単に実行できることで、開発の面で多くの時間を節約できる可能性があります。
したがって、新しいdatabase.yml
ファイルは次のようになります。
development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true
別のデータベースに切り替える方法を指定する興味深い方法は次のとおりです。
class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end
これがGitHubの公式ページで、これも適切に文書化されています。 個人的には、将来のRailsアップデートでもデータベースシャーディング機能を利用できることを楽しみにしています(このようなもの)。

アクションメールボックス
Rails 6のもう1つの興味深い機能は、アクションメールボックスの追加です。これにより、受信メールをメールボックスなどのコントローラーにルーティングしてRailsで処理する機能が追加されます。
アクションメールボックスは、Mailgun、Mandrill、Postmark、およびSendGridの入力機能を備えています。 組み込みのExim、Postfix、およびQmailの入力を介して受信メールを直接処理することもできます。 これで、詳細に立ち入ることなく、潜在的なメリットを想像できるでしょう。 ヘルプデスクからのメールを直接処理してサポートチケットを自動化する場合があります。Rails6を使用すると、顧客は電子メールなどを介して直接返信できます。 フロアは、この機能を探索し、アプリケーションに最適なアプローチを考え出すために開かれています。
アクションメールボックスの使用方法を理解するための小さな例を次に示します。
COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end
また、電子メールを構成する新しい方法は次のとおりです(Sendgridを例にとると)。
# config/environments/production.rb config.action_mailbox.ingress = :sendgrid
rails credentials:edit
を使用して、 action_mailbox.ingress_password
の下にあるアプリケーションの暗号化された資格情報にパスワードを追加します。ここで、ActionMailboxは自動的にパスワードを検出します。
action_mailbox: ingress_password: …
SendGrid Inbound Parseを構成して、ユーザー名actionmailbox
と以前に生成したパスワードを使用して受信メールを/rails/action_mailbox/sendgrid/inbound_emails
に転送します。 アプリケーションがhttps://example.com
にある場合は、次のURLを使用してSendGridを構成します。
https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i
これをさらに詳しく調べたい場合は、Railsにすでにこれに関するガイドがあります。
Zeitwerk
ZeitwerkはRubyの新しいコードローダーです。 従来のファイル構造では、Zeitwerkはプロジェクトのクラスとモジュールをオンデマンドでロードします。つまり、独自のファイルのrequire呼び出しを作成する必要はありません。 Rails 6で有効にするには、次のようにします。
config.autoloader = :zeitwerk
Zeitwerkの詳細については、こちらをご覧ください。
オプティマイザーのヒント
一部のクエリの実行に時間がかかりすぎるのではないかと心配ですか? これで、クエリのタイムアウトを定義する方法もあります。
次のステートメントは、クエリの実行に通常よりも時間がかかる場合に、 StatementTimeout
例外を発生させます。
User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all
これはMySQLでサポートされており、データベースでサポートされているかどうかを調べる必要があります。
データベースの切り捨て
データのシードについてはどうですか? 次のステートメントは、すべてのデータベーステーブルを切り捨ててから、データのシードに進むことができます。
rails db:truncate_all
シードするデータベースを削除する必要はもうありません。 あなたはおそらくこれがエレガントで迅速な解決策であることに同意するでしょう。
アクションテキスト
おそらく、WYSIWYGエディターで動作する多くのアプリケーションのもう1つの注目すべき機能は、Rails6アプリケーションにネイティブにTrixエディターのサポートが追加されたことです。 これは確かに多くのプロジェクトにとって良いアップグレード/追加になるでしょう。
ほとんどのWYSIWYGHTMLエディターは、範囲が非常に広いです。各ブラウザーの実装には独自のバグと癖があり、JavaScript開発者は不整合を解決する必要があります。 contenteditable
は、コンテンツ編集可能コンテンツをI / Oデバイスとして扱うことにより、これらの不整合を回避します。入力がエディターに送られると、Trixはその入力を内部ドキュメントモデルの編集操作に変換し、そのドキュメントをエディターに再レンダリングします。 これにより、Trixはすべてのキーストロークの後に何が起こるかを完全に制御できます。
インストール:
rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end
アクションテキストの詳細については、こちらの公式ドキュメントをご覧ください。
安全
いくつかのセキュリティ強化がなければ、深刻なアップグレードは完了しません。 Rails6もセキュリティの面で失望していません。 最初の注目すべきセキュリティアップグレードは、ホスト認証のサポートの追加です。
Host Authorizationは、リクエストの送信先となるホストを明示的に許可することにより、DNS再バインド攻撃から保護する新しいミドルウェアです。 これが意味するのは、アプリケーションにアクセスできるホストを定義できるということです。
別のセキュリティアップグレードは、Cookieの署名/暗号化された値をコピーし、それを別のCookieの値として使用しようとする攻撃を阻止することを目的としています。 これは、目的フィールドにCookie名を隠し、Cookie値とともに署名/暗号化することで実現します。 次に、サーバー側の読み取りで、Cookie名を確認し、攻撃されたCookieを破棄します。 action_dispatch.use_cookies_with_metadata
を有効にして、この機能を使用します。この機能は、新しい目的と有効期限のメタデータが埋め込まれたCookieを書き込みます。
デフォルトのBundlerとしてのWebpack
フロントエンド開発用の多くの最新のJavaScriptフレームワークのデファクトスタンダードであるように、Rails 6は、Rails Assetパイプラインに代わって、webpackergemを介してデフォルトのJavaScriptバンドラーとしてWebpackを追加しました。 これは比較的簡単な追加であり、詳細については説明しません。 Webpackは、過労のフロントエンド開発者にいくらかの救済をもたらすと言えば十分です。
競合状態の防止
Rails 6には、コード内のSELECT / INSERT競合状態を防ぐために使用される新しいメソッドがあります(多くの読者は、プロジェクトをスケーリングするときに競合状態に遭遇するという不幸に見舞われたと思います)。 追加情報が必要な場合に備えて、GitHubスレッドを次に示します。
基になるテーブルには、固有の制約で定義された関連する列が必要です。 #find_or_create_by
からSELECT→INSERTの間の競合状態を回避しますが、実際にはINSERT→SELECTの間には別の競合状態があります。これは、これら2つのステートメント間のDELETEが別のクライアントによって実行された場合にトリガーできます。 ただし、ほとんどのアプリケーションでは、これが発生する可能性が大幅に低い状態です。
Rails6のクレデンシャル
Rails 5.2の時代から、クレデンシャルは機密情報を処理するための新しい「Railsの方法」と呼ばれ、悪名高い.envファイルを完全に取り除くことを約束しています。 クレデンシャルを使用すると、サードパーティサービスの暗号化されたキーをソース管理に直接チェックインできます。
ただし、これまでRailsはすべての環境で同じ暗号化ファイルを使用していたため、特に大きなプロジェクトやレガシーコードを処理する場合は、開発と本番環境で異なるキーを処理するのが少し難しくなりました。
Rails 6では、これは環境ごとのクレデンシャルのサポートによって最終的に解決されます。 繰り返しになりますが、詳細については、公式のGitHubスレッドで調べることができます。
Rails 6は良いアップデートですか?
はい。実際、Rails 6はメジャーアップデートとして説明できますが、ゲームチェンジャーと呼ぶ人はほとんどいません。 Ruby on Railsは何年も前から存在しているため、革命的な変化を期待する人はほとんどいませんが、その6番目の化身は多くのことをもたらします。
Rails 6で展開された機能の中には、マイナーな改善のように見えるものもあれば、開発時間を大幅に節約し、セキュリティや堅牢性などを改善する可能性があるものもあります。 結論:Railsは成熟しており、多くの開発者はその将来に熱心に取り組んでいます。Rails6のリリースにより、Railsはさらに良くなりました。
もちろん、このRails 6の機能のリストは不完全であり、変更の完全なセットを表示するには、変更ログを確認する必要があります。 さらに、考慮すべき多くの非推奨があります。 最後に、すべての変更を確認して自分で更新することを主張する場合は、リリースノート全体をお読みください。