はじめに

今年(2017年)の4月末にRails on Rails (Rails)のバージョン5.1がリリースされましたが、わずか7ヵ月後の11月末に早くもバージョン5.2のベータ版がリリースされています。

Rails 5.1が、Webpack / Yarnのサポートなどフロントエンドの新機能を中心としたリリースだったのに対し、Rails 5.2は、ファイルアップロード用のActive Storageなどバックエンドの新機能を中心としたリリースになるようです。

本記事では、Rails 5.0の記事Rails 5.1の記事に引き続いて、GitHubのRailsプロジェクトIssuesPull Requestsの履歴、Railsの公式ブログの記事をもとに、Rails 5.2の主要な新機能について、まとめています。

Active Storage

Active Storageはファイルアップロードの新機能で、以前から利用されてきたPaperclipCarrierwaveなどのサードパーティのGemの代わりとなるものです。

アップロード・参照先としては、Amazon S3, Google Cloud Storage, Microsoft Azure Blob Storageなどのクラウドサービスを標準で利用することができ、また、ダイレクトアップロードという、ブラウザから直接クラウドサービスへアップロードできる機能や、ミラーリング機能を備えます。

アップロードするファイルが画像の場合はオンデマンドでサイズの変換(MiniMagickを使用)が可能であり、動画やPDFの場合はプレビューを生成することが可能です。どのファイルの場合も、メタデータの取得はジョブによって非同期で行われます。

Railsアプリケーションから使用する場合は、以下のコマンドを実行し、ファイル情報と関連づけの格納に必要なテーブルをDBに作成します。

$ bin/rails active_storage:install
$ bin/rails db:migrate

ファイル情報と関連づけに使用するモデルは以下のようになっています。
(各モデルは、ActiveStorageの内部で定義されており、実装し直す必要はありません。)

  • Blob
    • ファイル情報(Content-Type、サイズ、クラウドでの識別用のkeyやメタデータなど)を格納
  • Attachment
    • ファイルと他のモデルとの関連づけ用の中間テーブル

Railsアプリケーション側のモデルからは、以下のようにhas_many_attachedメソッドを使用します。以下はArticleモデルにimagesという名前で複数のファイルをアップロードする場合の例です。

class Article < ApplicationRecord
  has_many_attached :images

単一のファイルをアップロードする場合は、has_one_attachedメソッドを使用します。

class Article < ApplicationRecord
  has_one_attached :image

その他の詳細な内容や各クラウドへアップロードする場合の設定に関しては、公式のドキュメントや、こちらのスライドを参照してください。

Redisキャッシュストア

Railsではこれまでメモリ、ファイル、Memcachedを利用したキャッシュ機構を提供していましたが、これに加えて、Redisを利用したキャッシュ機構を提供するようになりました。

Redisへのキャッシュは使われてから最も長い時間が経ったもの、参照される頻度が最も低いものを優先的に無効にします。

(Rails 5.2ではキャッシュのキーの再利用圧縮も行われるようになったので、Redisによるキャッシュと組み合わせると、以前より高い効率でのキャッシュが可能になりました。)

標準ではキャッシュの読み書きに失敗した場合は、例外でなくnil(キャッシュにヒットしなかった)とみなすので、設定を正しく行えばこれまでのアプリケーションと変わりなく使用することができます。

Redisのバックエンドとしては、素のRedisだけでなく, hiredis, Redis::Distributedをサポートします。

Railsアプリケーションで利用するには、各環境の設定ファイルで以下のように設定を行います。

# config/environments/production.rb
config.cache_store = :redis_cache_store

より詳しい内容(各バックエンドを利用する方法など)については、公式ドキュメントを参照してください。

HTTP/2 Early Hints

Early Hintsは、Webサーバーにリクエストが完了する前にヘッダで必要なJavaScriptやスタイルシート(アセット)のURLを伝えることができ、より高速なページの表示を可能にします。

ドラフト文書であるAn HTTP Status Code for Indicating Hints によると、最初にステータス103でLinkヘッダにアセットのURLを埋め込んだレスポンスを返し、次に実際のボディと同じLinkヘッダを含むレスポンスを返します。アセットの各ファイルはサーバーからHTTP/2 Server Pushによってクライアントに送信されます。

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script
HTTP/1.1 200 OK
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script

Railsでは、HTTPのLinkヘッダに、javascript_include_tag / stylesheet_link_tag に記述されたファイルのURLを埋め込みます。

使用するには、h2opumaの新しいバージョン(3.11.0以上)のセットアップを行った後に、bin/rails s--early-hintsオプションをつけて起動します。

Bootsnap

Bootsnapと呼ばれるRailsアプリケーションの起動時間を短縮するライブラリが、Gemfile に含まれるようになりました。

Bootsnapのサイトによると起動時間が半分程度になるそうです。

Content Security Policy

Content Security Policy (CSP)は、サーバーがHTTPヘッダにContent-Security-Policyの内容を含むレスポンスを返すことで、ブラウザ側でクロスサイトスクリプティング(XSS)やパケット盗聴攻撃を防ぐ仕組みのことです。

Rails 5.2ではサードパーティのgem(secureheadersなど)を使用しなくても、CSPの設定が簡単にでき、セキュリティを強化できるようになりました。

RailsアプリケーションでCSPを設定するには、config/initializers/content_security_policy.rb で以下のように設定します。

Rails.application.config.content_security_policy do |policy|
  policy.default_src :self, :https # サイト自身のドメイン(サブドメインを除く)からhttpsで取得
  policy.style_src   :self, :https, :unsafe_inline # インラインの<style>要素を許可(危険)
  ...
end

コントローラで設定をカスタマイズするには、content_security_policyメソッドを使用します。

class ArticlesController < ApplicationController
  content_security_policy do |policy|
    policy.upgrade_insecure_requests true # httpをhttpsへリダイレクト(対応ブラウザの場合)
  end
end

暗号化されたCredentials

これまで、複数存在していたRailsアプリケーション内の機密情報(config/secrets.ymlや、SECRET_BASE_KEY)を1つのファイル(config/credentials.yml.enc)内に暗号化して格納できるようになりました。

(これによって、Rails 5.1で導入された、encrypted secretsも置き換えられてしまいました。)

ファイルの復号には、環境変数RAILS_MASTER_KEYを使用し、bin/rails credentials:editコマンドで内容を編集を行うことができます。

config/credentials.yml.encの中身は例えば、以下のようになっています。

aws:
  access_key_id: XXXXXXXXXXXXXXXX
  secret_access_key: XXXXXXXXXXXXXXXXXXX
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

ファイルを保存すると、自動的に再度暗号化されます。

まとめ

Rails 5.2はファイルアップロードを簡単に行えるActive StorageやRedisキャッシュストアなど、バックエンド周りの新機能を追加したバージョンとなるようです。
また、Content Security Policyの設定や暗号化されたCredentialsの管理も可能になっており、よりセキュアなアプリケーションの構築が可能になっています。
来年のリリースに向けて、新機能を試してみたり、既存のアプリケーションのアップグレードをしてみてはいかがでしょうか。

参考サイト