こんにちは。プログラミングスクールHappiness Chainでメンターをしているryoです。
今回は、最近リリースされたRails7.1の変更点に関して、記載していきます。
※以下公式リリースノートの和訳と、個人的な感想を少し記載しています。
※ こちら執筆途中になりますので、ご了承ください。
Railsアプリ新規作成時に、Dockerfileの自動生成
rails new sample-project
をすると以下のDockerfileが自動生成される。
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.2.2
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git libvips pkg-config
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
# Copy application code
COPY . .
# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
# Final stage for app image
FROM base
# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libsqlite3-0 libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails
# Run and own only the runtime files as a non-root user for security
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]
本番環境にチューニングされたチューニングされたDockerfile(適切なlayer、image sizeを最小化するためにmulti-stage buildの利用)ということで、実際にrails newしましたけど、multi-stage buildの記載になってたり、bootsnapでのpre compileとassetのprecompileなど既に記載されてて、そこまでDockerfileをいじる必要なさそう。
独自の認証機能の改善された
has_secure_password
を保管するための機能として以下の通り。
-
normalizes
- カラムを保存時に正規化してくれる(検索時も)
user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
user.email # => "cruise-control@example.com"
user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
user.email # => "cruise-control@example.com"
-
authenticate_by
- パスワード以外のカラムでレコードを見つけ、パスワードで認証し、成功の場合は、レコードを返し、失敗の場合nilを返す(受け取ったパスワードは常にdigest化する)
- これにより、ブルーフォース攻撃の軽減となる
class User < ActiveRecord::Base
has_secure_password
end
User.create(name: "John Doe", email: "jdoe@example.com", password: "abc123")
User.authenticate_by(email: "jdoe@example.com", password: "abc123").name # => "John Doe" (in 373.4ms)
User.authenticate_by(email: "jdoe@example.com", password: "wrong") # => nil (in 373.9ms)
-
generates_token_for
- passwordをリセットする際に使うようなtokenを発行することができる。
class User < ApplicationRecord
has_secure_password
generates_token_for :password_reset, expires_in: 15.minutes do
# Last 10 characters of password salt, which changes when password is updated:
password_salt&.last(10)
end
end
user = User.first
token = user.generate_token_for(:password_reset)
User.find_by_token_for(:password_reset, token) # => user
# 16 minutes later...
User.find_by_token_for(:password_reset, token) # => nil
has_secure_passwordに関しては、
パスワード更新時に、自動的に検証できるようになった
(passwordに新しいパスワード、password_challengeに現在のパスワードを渡すことで、パスワードの更新が可能)
# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
has_secure_password
end
user = User.new(name: "rafael", password: "railsrocks", password_confirmation: "railsrocks")
user.save # => true
user.update(password: "pwn3d", password_challenge: "") # => false, challenge doesn't authenticate
user.update(password: "railsGetsEvenBetter", password_challenge: "railsrocks") # => true
-
has_secure_password
- パスワード更新時に、自動的に検証できるようになった
(passwordに新しいパスワード、password_challengeに現在のパスワードを渡すことで、パスワードの更新が可能)
- パスワード更新時に、自動的に検証できるようになった
# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
has_secure_password
end
user = User.new(name: "rafael", password: "railsrocks", password_confirmation: "railsrocks")
user.save # => true
user.update(password: "pwn3d", password_challenge: "") # => false, challenge doesn't authenticate
user.update(password: "railsGetsEvenBetter", password_challenge: "railsrocks") # => true
rails標準の認証が、以前よりも楽にセキュアに書けるようになった印象。
非同期クエリサポートの拡張
遅いクエリ、特に計算に重点を置いたクエリを、非同期で実行できるようになった。
追加されたメソッドは以下の通り。
- async_count
- async_sum
- async_minimum
- async_maximum
- async_average
- async_pluck
- async_pick
- async_ids
- async_find_by_sql
- async_count_by_sql
これはとてもありがたい。