Rails8.0 つかってみる

rails-new
コマンドを使用してサンプル用アプリケーションを作成してみる。
せっかくなので Rails8 系で。
rails-new -r 8.0 tut-rails --devcontainer
rails-new コマンドのヘルプ
% rails-new --help
A CLI tool to generate a new Rails project
Usage: rails-new [OPTIONS] <ARGS>...
rails-new [OPTIONS] [ARGS]... <COMMAND>
Commands:
rails-help Prints `rails new --help`
help Print this message or the help of the given subcommand(s)
Arguments:
<ARGS>... arguments passed to `rails new`
Options:
-u, --ruby-version <RUBY_VERSION> [default: 3.3.4]
-r, --rails-version <RAILS_VERSION> [default: 7.2.0]
-h, --help Print help
-V, --version Print version
作成したアプリケーションをVSCodeからコンテナに接続。
vscode ➜ /workspaces/tut-rails8 (main) $ rails -v
Rails 8.0.1
vscode ➜ /workspaces/tut-rails8 (main) $ ruby -v
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [aarch64-linux]
【参考】

アプリケーション確認
とりあえず、DBの初期化をしようと思ったらすでに作成済みらしい。
vscode ➜ /workspaces/tut-rails8 (main) $ rails db:create
Database 'storage/development.sqlite3' already exists
Database 'storage/test.sqlite3' already exists
早速アプリケーションの起動
rails s
できた!

作成されるコンテナの確認
rails-new
コマンドで作成されたコンテナを確認。
% docker ps -a | grep tut_rails
09eb828f8785 tut_rails-rails-app "/bin/sh -c 'echo Co…" 2 hours ago Up 5 minutes tut_rails-rails-app-1
622cb6ffa759 selenium/standalone-chromium "/opt/bin/entry_poin…" 2 hours ago Up 5 minutes 4444/tcp, 5900/tcp, 9000/tcp tut_rails-selenium-1
Rails7系以前の時は redis
のコンテナも作成されていた気がするけど、8系では作成されず。
詳しくは調べていないけど、これは8系でRedisへの依存がなくなったことがちゃんと反映されていそう。

Gitリポジトリの作成
とりあえず、作成直後の状態でGitHubにリポジトリをプッシュ。
デフォルトで作成されているWorkFlowで以下のエラーが発生。
/home/runner/work/tut-rails/tut-rails/db/schema.rb doesn't exist yet. Run
bin/rails db:migrate
to create it, then try again.
とエラーが出ており、db/schema.rb
ファイルがないことが原因っぽい。
スキーマを作成して再プッシュ。
bin/rails db:migrate
無事成功!

VSCode 拡張機能の確認
デフォルトでインストールされる拡張機能

認証機能を試す
認証機能の生成
Rails8 から追加された以下のコマンドを実行
$ bin/rails generate authentication
invoke erb
create app/views/passwords/new.html.erb
create app/views/passwords/edit.html.erb
create app/views/sessions/new.html.erb
create app/models/session.rb
create app/models/user.rb
create app/models/current.rb
create app/controllers/sessions_controller.rb
create app/controllers/concerns/authentication.rb
create app/controllers/passwords_controller.rb
create app/channels/application_cable/connection.rb
create app/mailers/passwords_mailer.rb
create app/views/passwords_mailer/reset.html.erb
create app/views/passwords_mailer/reset.text.erb
create test/mailers/previews/passwords_mailer_preview.rb
insert app/controllers/application_controller.rb
route resources :passwords, param: :token
route resource :session
gsub Gemfile
bundle install --quiet
generate migration CreateUsers email_address:string!:uniq password_digest:string! --force
rails generate migration CreateUsers email_address:string!:uniq password_digest:string! --force
invoke active_record
create db/migrate/20250108054757_create_users.rb
generate migration CreateSessions user:references ip_address:string user_agent:string --force
rails generate migration CreateSessions user:references ip_address:string user_agent:string --force
invoke active_record
create db/migrate/20250108054758_create_sessions.rb
invoke test_unit
create test/fixtures/users.yml
create test/models/user_test.rb
マイグレーションファイルが出来上がったのでマイグレーションの実行
bin/rails db:migrate
ユーザレコードの作成
# ユーザレコードの作成
5.times do |n|
User.create!(
email_address: "user#{n+1}@example.com",
password: "password"
)
end
bin/rails db:seed
作成されたユーザレコードを確認してみる
$ rails c
tut-rails8(dev)> User.last
=>
#<User:0x0000ffff7675b7c0
id: 5,
email_address: "[FILTERED]",
password_digest: "[FILTERED]",
created_at: "2025-01-08 05:58:21.539516000 +0000",
updated_at: "2025-01-08 05:58:21.539516000 +0000">
tut-rails8(dev)> User.count
=> 5
メールアドレス、パスワードの暗号化文字列はフィルターされてるみたい。
無事にユーザーが作成できました。

View, Controller の実装
HomeController
を生成し、ルーティングを修正
$ bin/rails generate controller Home index
create app/controllers/home_controller.rb
route get "home/index"
invoke erb
exist app/views/home
create app/views/home/index.html.erb
invoke test_unit
create test/controllers/home_controller_test.rb
invoke helper
create app/helpers/home_helper.rb
invoke test_unit
root to: "home#index"
この状態で http://127.0.0.1:3000 へアクセスすると http://127.0.0.1:3001/session/new に飛ばされた。
デフォルトで未ログイン時はログイン画面に飛ばされるっぽい?
試しにログインしてみると、エラー。
You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install.
bin/rails generate authentication
実行時に bcrypt
が Gemfile に追加されているけど、bundle install
を実行していなかったのが原因ぽい。
とのことなので、bundle install
を再実行。
アプリケーションを再実行して、再度ログインすると、無事にログインできた!
ログアウト機能の実装
app/views/home/index.html.erb
に以下を追加。
ログイン中のユーザーアドレスを表示し、Sign out
リンクを追加
<p><%= Current.user.email_address %></p>
<%= link_to 'Sign out', session_path, data: { turbo_method: :delete } %>
link_to で DELETE メソッドを飛ばす
<%= link_to 'Sign out', session_path, method: :delete %>
にすると、Started GET "/session" for 127.0.0.1 at 2025-01-09 02:08:02 +0000
でリクエストが飛ばされてしまった。
Rails7 以降?は <%= link_to 'Sign out', session_path, data: { turbo_method: :delete } %>
にする必要がありそう?
Rails7 時点ではJavascriptを有効化するのにいろいろ操作が必要そうだったが、今回は data
オプションに turbo_method
を追加するだけで無事にリクエストが飛んだ。
Sign out
をクリックすると、再度 http://127.0.0.1:3001/session/new に遷移。
テストファイルの修正
当たり前ですが、自動生成した test/controllers/home_controller_test.rb
ではエラーになりました。
require "test_helper"
class HomeControllerTest < ActionDispatch::IntegrationTest
test "should get index" do
get home_index_url
assert_response :success
end
end
-
home#index
をroot
にしているため、home_index_url
が存在しない。 - 未ログインのため、
Home#index
が実行できない。
この対応のため、以下の修正を行う。
require "test_helper"
class HomeControllerTest < ActionDispatch::IntegrationTest
+ def setup
+ @user = User.first
+ end
test "should get index" do
- get home_index_url
+ log_in_as(@user)
+ get root_url
assert_response :success
end
end
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
module ActiveSupport
class TestCase
# Run tests in parallel with specified workers
parallelize(workers: :number_of_processors)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
+ def log_in_as(user)
+ post session_url, params: { email_address: user.email_address, password: "password" }
+ end
end
end
無事にテストまで通りました。
【参考】