Zenn
Open7

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]

【参考】

https://railsguides.jp/getting_started_with_devcontainer.html
https://qiita.com/okonomi/items/bdfbefb3e78b421bc361

まきのすけまきのすけ

アプリケーション確認

とりあえず、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

無事成功!

まきのすけまきのすけ

認証機能を試す

認証機能の生成

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

ユーザレコードの作成

db/seeds.rb
# ユーザレコードの作成
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
config/routes.rb
  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リンクを追加

app/views/home/index.html.erb
<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 ではエラーになりました。

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#indexroot にしているため、home_index_url が存在しない。
  • 未ログインのため、Home#index が実行できない。

この対応のため、以下の修正を行う。

test/test_helper.rb
  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
test/test_helper.rb
  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

無事にテストまで通りました。


【参考】

https://zenn.dev/canesro/articles/0733a791680eb3
https://www.airteams.net/media/articles/1830

作成者以外のコメントは許可されていません