LoginSignup
202
138

More than 1 year has passed since last update.

Ruby on Rails 7の主要な新機能・機能追加・変更点

Last updated at Posted at 2021-12-25

はじめに

Ruby on Rails(以下Rails)の最新バージョンである7.0(以下Rails 7)が2021年12月15日にリリースされました。

Rails 7では、JavaScriptフロントエンドの大幅な刷新、CSS BundlingによるTailwind CSSやPostCSSのサポートを含めた、メジャーバージョンアップグレードにふさわしい機能強化が行われています。

本記事では、Railsの公式ブログRailsガイド、GitHubのRailsプロジェクトのIssuesPull Requestsの内容をもとに、Rails 7の主要な新機能・機能追加・変更点の紹介を行います。

※ 以前のバージョンのRailsの主要な新機能・機能追加・変更点については以下を参照してください。

注意点

Rubyのバージョン

Rails 7を動かすには、Ruby 2.7.0以上が必要になります。可能であれば、Ruby 3.0系列にアップグレードを行ってください。Ruby 3.1については、Rails 7.0.0では非対応ですが、今後サポートされる予定です。

セキュリティアップデート

Rails 7のリリース後は、Railsのバージョン7.0系列と、6.1系列がセキュリティアップデートの対象となります。それより前の6.0系列、5.2系列についても深刻なセキュリティ問題に対する修正は行われますが、サポート期間が短くなっていますので、注意してください。

参考

新機能

JavaScriptフロントエンドの刷新(ESM importmap / Hotwire / Stimulus / Turbo)

ES6(ECMAScript 6)/ ESM(ECMAScript modules) 、HTTP/2、import mapsを使用することで、Node.jsをインストールせずにモダンなJavaScriptをRailsアプリケーションで利用することが可能になりました。

以前のRailsのバージョンでは、Webpacker経由でWebpackを使用してJavaScriptファイルを依存するライブラリと共に結合・処理してその結果のファイルを使用していました。

最近では、ES6 / ESMのブラウザサポートによってJavaScriptのコンパイル・結合が不要になり、HTTP/2で配信することで小さな複数のファイルのままでもネットワーク経由での読み込み速度が落ちなくなりました。また、import mapsを使用することでライブラリの名前解決を行なって直接CDNなどから取得できるようになりました。

Rails 7では上記の技術的進歩を踏まえた上で、標準ではWebpacker / Node.jsを使用しなくても良いようになっています。(以前のように使用することも可能です。)

デフォルトでは、HotwireStimulusTurboといったライブラリがインストールされ、リッチなUI/UXを実現するSPA(シングルページアプリケーション)を実装する際に利用することができます。(Webpackerはデフォルトではインストールされなくなりました。)

CSS BundlingによるTailwind CSSやPostCSSなどのサポート

cssbundling-railsというGemをインストールすることで、 Tailwind CSSBootstrapBulmaPostCSSDart Sass を使用して、CSSファイルを結合・処理し、Railsのアセットパイプラインに載せることが可能になりました。

使用するCSSライブラリは、アプリケーションの新規作成時に以下のようにして、--cssオプションで指定することができます。例えば、Tailwind CSSを指定するには以下のようにします。

rails new myapp --css tailwind

また、既存のアプリケーションでは、Gemfileに以下の行を追加して、

Gemfile
gem 'cssbundling-rails'

以下のコマンドを実行することで、インストールと初期設定を行うことが可能です。

$ bin/bundle install
$ bin/rails css:install:tailwind

これにより、tailwind.config.jsなどの設定ファイルが生成されます。

開発時にはyarn build:css --watchコマンドを実行することで、リアルタイムでCSSファイルの処理を行いながらブラウザで結果を確認することができます。デプロイ時には、assets:precompile実行時にCSSファイルの処理が行われます。

参考

Active Recordの属性の暗号化

アプリケーション内でActive Recordの属性を暗号化した状態でDBに保存したり、読み出しを行うことができるようになりました。これによって、意図せずにユーザーの機密情報をアプリケーションのログや外部に公開してしまわないように、属性レベルできめ細かい制御が行うことができます。

設定を行うにはbin/rails db:encryption:initのコマンドを実行して、ランダムなキーを生成し、その結果をbin/rails credentials:editで開いたエディタの画面に貼り付けて保存します。

$ bin/rails db:encryption:init
Add this entry to the credentials of the target environment: 

active_record_encryption:
  primary_key: 5jQ2IWs63zd7Memm3dQ4O36Sefo32WTF
  deterministic_key: H7THwnF0ZU1LSYBZsENx7gRywujlb01j
  key_derivation_salt: 2Rbbe0FOLtbQWvvUanvETAIcwRFHgIs9

暗号化された属性を定義するには、以下のようにモデルで、encryptsの後に属性名を記述します。

class User < ApplicationRecord
  encrypts :name
end

暗号化を指定した属性は、他の属性と同様に保存と読み出しが可能ですが、DB内には暗号化された状態で保存されます。

> user = User.new(name: 'John')
> user.save
INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "{\"p\":\"Fz3+bYdP\",\"h\":{\"iv\":\"2kWLG6TXjNmBy1Is\",\"at\":\"eUn3MOTa4qDR93ABt3rGSA==\"}}"], ["created_at", "2021-12-25 02:55:14.599457"], ["updated_at", "2021-12-25 02:55:14.599457"]]
> user = User.find_by(name: 'John')
SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "{\"p\":\"NzM54tpR\",\"h\":{\"iv\":\"947dl7Uq1O8EuXhE\",\"at\":\"FKlBF3hEO6QKJF3KSZMl4A==\"}}"], ["LIMIT", 1]]

参考

SQLクエリにコメントを自動で付与できるように

SQLのクエリに自動的にアプリケーション側の情報(Active Recordのメソッドが呼び出された、コントローラやジョブなどを含む)をコメントとして付与する機能が追加されました。

元々、MarginaliaというBasecampで使用されていたGemの機能が、ActiveRecord::QueryLogsに移植された形です。

以下のようにRailsの設定で出力する情報をタグとして設定できます。

config.active_record.query_log_tags = [ :application, :controller, :action, :job ]

これによって例えば以下のコントローラを使用していて、GET /booksにアクセスした際に

class BooksController < ApplicationController
  def index
    @books = Book.all
  end
end

以下のようなSQLのログがコメントとともに出力されるようになります。

SELECT * FROM books /*application:MyApp;controller:books;action:index*/

この機能を使うことで、例えばスロークエリが発生した際に、SQLのログを見ただけでアプリケーション側のどの部分の処理でそのクエリが発生したかを特定することができるようになります。
出力できるタグの詳細や他の設定に関しては、以下を参考にしてください。

参考

非同期のSQLクエリによる結果の取得

ActiveRecord::Relation#load_asyncを使用することによって、非同期でSQLクエリを実行し、結果を取得することができるようになりました。

これによって、例えば以下のコードのようにコントローラの同じアクション内で、複数の相互に依存しないクエリを並列に実行することができるようになり、レスポンスを返す時間を短縮することができるようになります。

def index
  @articles = Article.per(params[:per]).page(params[:page]).load_async
  @categories = Category.active.load_async
end

参考

機能追加

バルクインサートで自動的にタイムスタンプを記録できるように

Active Recordのinsert_allupsert_allメソッドなどでバルクインサート・バルクアップサートでレコードを作成、更新する際に、created_atupdated_atなどのタイムスタンプを自動でセットできるようになりました。

この機能を使用するには、以下の例のようにメソッドのrecord_timestampsオプションにtrueを渡す必要があります。

Article.insert_all([{ title: "What's new in Rails 7" }], record_timestamps: true)

参考

Active Recordにin_order_ofメソッドが追加

レコードを指定した順番で取得できるin_order_ofメソッドがActive Recordに追加されました。
以下の例では、ユーザーをIDが1、5、3の順番になるように取得しています。

User.in_order_of(:id, [1, 5, 3])
# SELECT "users".* FROM "users" ORDER BY FIELD("users"."id", 1, 5, 3)

参考

Active Recordにstructurally_compatible?メソッドが追加

Active Recordのリレーションが他のリレーションとデータの構造が同じかどうかチェックするstructurally_compatible?メソッドが追加されました。このメソッドを使用することで、andメソッドやorメソッドを使用する前にエラーが起きないかどうかを事前にチェックすることができます。

Post.where("id = 1").structurally_compatible?(Post.where("author_id = 3"))
# => true
Post.joins(:comments).structurally_compatible?(Post.where("id = 1"))
# => false

参考

ActiveModel::APIの追加

ActiveModel::Modelの実装を新しくできたActiveModel::APIに移し、Active Recordのモデルのように振る舞うもの以外でも使いやすいようにしました。内部的な変更のため、ActiveModel::Modelはこれまで通り使用することができます。

参考

weekday_options_for_selectヘルパメソッドの追加

曜日選択のoptionタグを生成するweekday_options_for_selectタグが追加されました。

weekday_options_for_select
# => "<option value=\"Sunday\">Sunday</option>\n<option value=\"Monday\">Monday</option>\n
# <option value=\"Tuesday\">Tuesday</option>\n<option value=\"Wednesday\">Wednesday</option>\n
# <option value=\"Thursday\">Thursday</option>\n<option value=\"Friday\">Friday</option>\n
# <option value=\"Saturday\">Saturday</option>"
weekday_options_for_select(nil, index_as_value: true)
# => "<option value=\"0\">Sunday</option>\n<option value=\"1\">Monday</option>\n
# <option value=\"2\">Tuesday</option>\n<option value=\"3\">Wednesday</option>\n
# <option value=\"4\">Thursday</option>\n<option value=\"5\">Friday</option>\n
# <option value=\"6\">Saturday</option>"

国際化にも対応しており、rails-i18nのja.ymlファイルを使用すれば日本語の曜日選択のoptionタグを生成できるようです。

参考

データベースの設定オプションでタスクをオフにできるように

データベース設定ファイルのオプションでdatabase_tasks: falseを使用することで、そのデータベースに対するタスクをオフにできるようになりました。

複数データベースを使用していて、例えば読み取り専用のDBに対してマイグレーションを実行したくない場合などで便利に使えると思います。

例:

production:
  primary:
    database: my_database
    adapter: mysql2
  animals:
    database: my_animals_database
    adapter: mysql2
    database_tasks: false

参考

変更点

button_toがHTTPメソッドとしてPATCHを使用するように

以前のバージョンでは、button_toタグはHTTPメソッドとして、POSTを使用するようになっていましたが、Rails 7からはPATCHを使用するようになりました。以前の挙動に合わせるには、button_toメソッドのオプションとして、method: :postを渡す必要があります。

参考

SassとCSSジェネレータの非標準化

最近ではCSSフレームワークを使うようになっていて、Sassは使用されなくなってきているのでsass-rails Gemが標準ではGemfileに含まれないようになりました。

自動生成されるCSSファイルも拡張子が.scssではなく.cssのファイルになっています。また、モデルごとにCSSファイルを生成しないようになりました。

参考

Springの非標準化

spring Gemが標準ではGemfileに含まれないようになりました。

マシンが高速な場合はSpringによる高速化の恩恵を受けることが少なくなったためとのことです。

参考

Zeitwerkモードでの起動が必須に

Rails 6.0と6.1では、ファイルの自動ロードのモードとして、zeitwerkモードとclassicモードを選択することができましたが、Rails 7ではzeitwerkモードのみ選択できるようにして、classicモードを廃止しました。

これに伴い、設定のconfig.autoloader=が削除されており、また、classicモードで使用していたActiveSupport::Dependenciesが削除されました。

参考

Byebugの代わりにruby/debugを使用するように

以前のバージョンでは、デバッグ用のGemとしてbyebugを使用していましたが、Rails 7ではRuby標準のdebugが標準でGemfileに含まれるようになりました。

参考

ActiveSupport::DigestがSHA-256を使用するように

ダイジェスト値を生成する際にこれまでアルゴリズムとしてSHA-1を使用していたのが、SHA-256に変更になりました。キャッシュのキーなど様々な箇所で影響があるので、以前の挙動のままにしたい場合は、以下のように設定を行います。

config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA1

参考

Active Storageの画像処理でlibvipsを使用するように

Active Storageで画像処理に使われるGemで、以前のバージョンではmini_magickが使用されていましたが、Rails 7からはvipsが標準になりました。

参考

202
138
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
202
138