カテゴリー: BackEnd

Rails 6の変更点と新機能

はじめに

2019年8月16日に約3年ぶりのメジャーバージョンアップである Rails 6 がリリースされました。今回は Rails 5 から Rails 6 にかけての変更点と新しく追加されたコンポーネントについて紹介します。

概要

Rails 6 がリリースされたのは2019年8月15日で2016年6月30日にリリースされた Rails 5 から約3年2ヶ月ぶりのメジャーバージョンアップです。今回のバージョンアップでは15,000以上ものコミットが行われました。

変更点について全てを紹介することはできませんので、今回は以下の変更点について触れていきます。詳細についてはリリースノートをご覧ください。

  • Rubyのサポートバージョン
  • Webpacker
  • 複数データベース接続
  • 並列テスト

Rubyのサポートバージョン

Rails がメジャーバージョンアップする際はサポートする Ruby のバージョンが大幅に上がります。実際に、Rails 5系 では Ruby 2.2 以上をサポートしていましたが、Rails 6系 では Ruby 2.5 以上となりました。

Ruby 2系 以降では毎年マイナーバージョンアップが行われており、バージョンアップから3〜4年ほどでサポートが切れます。それに合わせて Rails は約3年毎にメジャーバージョンアップを行っています。

Webpacker

もともと Rails では JavaScript や CSS などのビルドに Sprockets を使用していましたが、近年のフロントエンド開発ツールの進化に伴い Sprockets の代わりに webpack を使用するケースが増えていきました。

そこで、DHH は webpack のラッパライブラリである Webpacker を開発しました。これにより、Rails から webpack のビルドができるようになり、webpack で生成したライブラリを使用することができるようになりました。

Webpacker 自体は Rails 5.1 から使用することができましたが、Rails 6 では Webpacker がデフォルトになりました。これによる変更点は以下のとおりです。

  • 新規Railsアプリケーションの作成時にwebpackのインストールが自動で行われるようになった
  • Action Cableのジェネレータが生成するコードがCoffeeScriptからJavaScriptに変わった
  • scaffoldのジェネレータがJavaScriptのコードを生成しなくなった
  • rails-ujsやAction Cableなどで使われているRails内のJavaScriptライブラリがnpmで公開されているものになった

今回の変更により Rails 6 では CoffeeScript が一切使われなくなりました。

Webpackerの設定

Webpacker の設定は config/webpacker.yml で行います。ここでは、生成されたファイルの出力先やビルド対象ファイルの指定などを行います。プロジェクト作成時の webpacker.yml の内容は以下のとおりです。

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  check_yarn_integrity: false
  webpack_compile_output: false

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  resolved_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

また、 webpack 自体の設定は config/webpack/ ディレクトリの環境ごとの JavaScript ファイルで行います。こちらもプロジェクト作成時の development.js の内容を表示します。

process.env.NODE_ENV = process.env.NODE_ENV || 'development'

const environment = require('./environment')

module.exports = environment.toWebpackConfig()

Webpackerでのビルド

Webpacker では webpack を操作するための binstub が提供されています。代表的なコマンドをいくつか紹介します。

bin/webpack --debug

上記はデバッグモードでビルドする場合のコマンドです。

bin/webpack-dev-server

上記は webpack-dev-server のラッパコマンドです。このコマンドではファイルの更新時に自動的にビルドされるだけでなくブラウザがリロードされるため、開発中はこちらのコマンドを使うのが良いでしょう。

bin/rails webpacker:compile

上記は本番環境向けのビルドタスクです。 webpack が正しくインストールされているかのチェックと webpack でのビルドを行います。

ビルドしたJavaScriptファイルを読み込む

Webpacker でビルドした JavaScript ファイルを読み込むには javascript_pack_tag を使用します。例えば、application.js を読み込むには以下のように記述します。

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

ほかにも、スタイルシートの読み込み用には stylesheet_pack_tag が、画像ファイルの読み込み用には image_pack_tag があります。

split chunksを使用する場合

split chunks を使用する場合は javascript_pack_tag が使用できません。その場合は代わりに javascript_packs_with_chunks_tag を使用します。

JavaScript以外のアセット

Webpacker のスタイルシートや画像ファイルなどの JavaScript 以外のアセットの管理は発展途上であり、その点は Sprockets に軍配が上がります。そのため、デフォルトでは Webpacker と Sprockets が併用して使用されています。もちろん、 Webpacker のみを使用するように変更することができます。

複数データベース接続

Rails 6 以前は複数のデータベースに接続するには establish_connection メソッドを明示的に呼び出すか、Octopus などのサードパーティ製のコンポーネントに頼る必要がありました。Rails 6 では Active Record に複数データベースへの接続機能が実装され、これにより気軽に2つ以上のデータベースにコネクションを張ることができるようになりました。

データベースの設定は引き続き config/database.yml に記述しますが、Rails 6 からは1階層増えて接続情報に名前をつけられるようになりました。ここでつけた名前はリードレプリカ構成にする場合や異なるデータベースに接続する際に使います。

database.yml の設定例を以下に記載します。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: 
  host: localhost

development:
  primary:
    <<: *default
    database: rails6_development
  another_db:
    <<: *default
    database: rails6_development_another
    migrations_paths: db/another_db_migrate

データベース毎にマイグレーションファイルを分けたい場合は another_db のように migrations_paths を指定します。

※ mysql2 のインストールに失敗する場合はこちらが参考になります。

マイグレーションの実行

マイグレーションファイル作成のコマンドは Rails 6 以前と基本的に変わりません。メインのデータベース以外のデータベースのマイグレーションファイルを作成するには –db オプションを指定します。

bin/rails g migration create_another_users_table --db another_db

このようにすると –db オプションで指定したディレクトリにマイグレーションファイルが作成されます。

リードレプリカ構成におけるデータベースの設定

リードレプリカ構成にするにはスレーブ側のデータベースの定義に replica: true を指定します。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: 
  host: localhost

development:
  primary:
    <<: *default
    database: rails6_development
  readonly:
    <<: *default
    database: rails6_development
    replica: true

こうすることでアプリケーションからの更新系のクエリを受付なくなります。

リードレプリカ構成におけるモデルの設定

リードレプリカの設定はモデルで行います。例えば、database.yml で定義した readonly をスレーブデータベースとして接続するには aplication_record.rb に以下のように connects_to を指定します。

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  
  connects_to database: { writing: :primary, reading: :readonly }
end

接続先データベースの変更

特定の処理で接続するデータベースを変える場合は connected_to メソッドを使用します。database.yml で定義した another_db に接続するには以下のようにします。

ActiveRecord::Base.connected_to(database: :another_db) do
  AnotherUser.create(name: 'yamada')
end

並列テスト

2014年以降、Rails ではユニットテストよりもE2Eテストを強化する方針に転換しました。しかし、E2Eテストでは内部でブラウザエンジンを実行するためオーバーヘッドが大きくなり、その結果テストの実行時間が長くなる傾向にありました。

そこで、Rails 6 ではテストを並列に実行する機能が実装されました。この並列テストでは複数のワーカを起動し、それぞれのワーカで並列にテストを行うようになっています。

ワーカの実行

ワーカはプロセス、もしくはスレッドで実行できます。Linux や macOS などの fork が使用できる環境では fork でプロセスを生成します。逆に、Windows などの fork が使用できない環境ではスレッドを使用します。

データベースの作成

ワーカをプロセスとして実行した場合はワーカ毎に前処理でデータベースが作成されます。そのためワーカ間でのデータベースへの競合は発生しません。しかし、ワーカをスレッドとして実行した場合は前処理でデータベースの作成が行われず、複数のスレッドが同じデータベースを使用するため競合が発生する可能性があります。そのため、スレッドを使用する場合はアプリケーション側で排他制御を意識する必要があります。

Rails 6で追加されたコンポーネント

Rails 6 では新たに Action Text と Action Mailbox というコンポーネントが追加されました。これらのコンポーネントはたしかに便利ですが使わないサービスも多いのではないかと思います。なので、どのようなサービスなのかを簡単に紹介するに留めます。

今回追加されたコンポーネントは Rails 5.2 で追加された Active Storage と密接な関係にあります。そこで、まず始めに Active Storage について簡単におさらいし、その後で新しいコンポーネントについて触れていきます。

Active Storage

Active Storage はファイルアップロードのためのコンポーネントです。ローカルへのアップロードはもちろん、Amazon S3 や Google Cloud Storage などへのアップロードも可能です。

carrierwave などのコンポーネントでは既存のテーブルにファイル情報を保持するカラムを追加する必要がありましたが Active Storage ではファイル情報を管理するテーブルが作られ、Active Record のモデルと紐付けられます。

Action Text

Action Text は WYSIWYG エディタと Rails アプリケーションを連携させるためのコンポーネントです。このコンポーネントでは主に以下の機能を提供します。

  • 入力した内容を保存するカラムの追加
  • テキスト内で入力されたファイルの保存
  • サニタイズ処理

Action Mailbox

Action Mailbox はメール受信処理のコンポーネントです。主にメールの受信、メールごとの処理、処理が終わったメールの削除を行います。メールの受信に関しては SendGrid や Mailgan などのクラウドサービスからのメール受信をサポートしています。

メールを受信してからの処理の流れは以下の通りです。

  1. 各ルートでメールを受信する
  2. 受信したメールを保存する
  3. 振り分け処理用のジョブを登録する
  4. 振り分け処理を実行する
  5. 振り分けたメールを処理する
  6. メール削除用のジョブを登録する

これらの内、4と5についてはユーザが実装する必要があります。

さいごに

今回のバージョンアップでは webpack との連携や複数データベースのサポートなど実際のサービス開発に大きな影響を与える内容が多いのではないでしょうか。今現在 Rails はあまり人気がない印象ですがバージョンアップを機に盛り上がってくれればと思います。

おすすめ書籍

     

Hiroki Ono

シェア
執筆者:
Hiroki Ono
タグ: RubyRails

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

2週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

4週間 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前