概要
今までRails7を触ったことがなかったため、感触を確かめるのも兼ねて改めてRailsチュートリアルをやってみました。
第1章
RailsチュートリアルではGitHub Codespaceを使用していますが、手元でDockerを用いて環境構築を行いました。
開発環境整備
まずは、Railsチュートリアル用のリポジトリをクローンします。 ディレクトリ名は今後の管理を楽にするため短いものへ変更しておきます。
git clone https://github.com/yasslab/codespaces-railstutorial.git app
クローンが完了したら、app
ディレクトリ内にDockerfile
、ルートにdocker-compose.yml
を配置して、docker compose up
を実行します。
演習用環境なので、DBは立てるだけにしました。
FROM ruby:3 RUN apt-get update -qq WORKDIR /app COPY Gemfile Gemfile.lock /app/ RUN bundle install CMD ["rails", "server", "-b", "0.0.0.0"]
services: db: image: esolang/sqlite3:latest app: build: ./app depends_on: - db ports: - "3000:3000" volumes: - ./app:/app
http://localhost:3000にアクセスすると、以下のようにチュートリアルの画面が表示されました。
bundle install
をDockerfile
で実行済みなので、これで環境構築は完了になります。
演習でのruby
、rails
、bundle
のバージョン確認はappコンテナにログインして実行しました。
$ docker compose exec app bash root@933ea42ad62a:/app# ruby -v ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux] root@933ea42ad62a:/app# rails -v Rails 7.0.4.3 root@933ea42ad62a:/app# bundle -v Bundler version 2.4.12
1.3.4 Hello, world! の演習
本編は書いてある通り行っただけなので割愛。 演習は下記のようにしました。
class ApplicationController < ActionController::Base def hello render html: '¡Hola, mundo!' end def goodbye render html: 'goodbye, world!' end end
Rails.application.routes.draw do root "application#goodbye" end
第2章
docker-compose.yml
とDockerfile
を使い回して環境を作りました。
railsコマンドはappコンテナ内ですべて実行しました。
演習
user
の最初のmicropost
を表示する課題については、条件をつけずにuser
を新規作成すると以下のエラーが出たので、.exists?
で紐づくmicropost
存在確認をしました。
class UsersController < ApplicationController before_action :set_user, only: %i[ show edit update destroy ] # ... # GET /users/1 or /users/1.json def show @first_post = @user.microposts.first end # ... end
<h1>Editing user</h1> <%= render "form", user: @user %> <%= render @first_post if @user.microposts.exists? %> <br> <div> <%= link_to "Show this user", @user %> | <%= link_to "Back to users", users_path %> </div>
user
作成・更新時のname
,email
のバリデーションは以下のようにしました。
class User < ApplicationRecord has_many :microposts validates :name, presence: true validates :email, presence: true end
第3章
2章と同じく、docker-compose.yml
とDockerfile
を使い回して環境を作りました。
Contactのページの追加はまず、テストコードに以下を追加しました。 この時点ではRedになります。
require "test_helper" class StaticPagesControllerTest < ActionDispatch::IntegrationTest # ... test "should get contact" do get static_pages_contact_url assert_response :success assert_select "title", "Contact | #{@base_title}" end end
static_pages_contact_url
がないとのことなので、routes.rb
に追加します。
# rails test Running 4 tests in a single process (parallelization threshold is 50) Run options: --seed 31081 # Running: ..E. Finished in 0.592640s, 6.7495 runs/s, 10.1242 assertions/s. 1) Error: StaticPagesControllerTest#test_should_get_contact: NameError: undefined local variable or method `static_pages_contact_url' for #<StaticPagesControllerTest:0x00007f6e1a73d720> test/controllers/static_pages_controller_test.rb:28:in `block in <class:StaticPagesControllerTest>' 4 runs, 6 assertions, 0 failures, 1 errors, 0 skips
Rails.application.routes.draw do get 'static_pages/home' get 'static_pages/help' get 'static_pages/about' get 'static_pages/contact' root 'application#hello' end
再度テストを実行すると、StaticPagesController
にcontact
アクションがないとのことなので追加します。
# rails test Running 4 tests in a single process (parallelization threshold is 50) Run options: --seed 36012 # Running: E... Finished in 0.620830s, 6.4430 runs/s, 9.6645 assertions/s. 1) Error: StaticPagesControllerTest#test_should_get_contact: AbstractController::ActionNotFound: The action 'contact' could not be found for StaticPagesController test/controllers/static_pages_controller_test.rb:28:in `block in <class:StaticPagesControllerTest>' 4 runs, 6 assertions, 0 failures, 1 errors, 0 skips
class StaticPagesController < ApplicationController def home end def help end def about end def contact end end
再度テストを実行すると、テンプレートがないとのことなので追加します。
# rails test Running 4 tests in a single process (parallelization threshold is 50) Run options: --seed 30891 # Running: ...E Finished in 1.012043s, 3.9524 runs/s, 5.9286 assertions/s. 1) Error: StaticPagesControllerTest#test_should_get_contact: ActionController::MissingExactTemplate: StaticPagesController#contact is missing a template for request formats: text/html test/controllers/static_pages_controller_test.rb:28:in `block in <class:StaticPagesControllerTest>' 4 runs, 6 assertions, 0 failures, 1 errors, 0 skips
ファイル追加後、再度テストを実行すると、タイトルがおかしいとのことなので、追加します。
# rails test Running 4 tests in a single process (parallelization threshold is 50) Run options: --seed 19525 # Running: .F.. Finished in 0.693485s, 5.7680 runs/s, 11.5359 assertions/s. 1) Failure: StaticPagesControllerTest#test_should_get_contact [/app/test/controllers/static_pages_controller_test.rb:30]: --- expected +++ actual @@ -1 +1 @@ -"Contact | Ruby on Rails Tutorial Sample App" +"| Ruby on Rails Tutorial Sample App" . Expected 0 to be >= 1. 4 runs, 8 assertions, 1 failures, 0 errors, 0 skips
<% provide(:title, "Contact") %>
再度テストを実行すると、無事Greenになりました。
# rails test Running 4 tests in a single process (parallelization threshold is 50) Run options: --seed 49162 # Running: .... Finished in 0.618450s, 6.4678 runs/s, 12.9356 assertions/s. 4 runs, 8 assertions, 0 failures, 0 errors, 0 skips
コンテンツを追加して、ブラウザでhttp://localhost:3000/static_pages/contactアクセスすると以下のように表示できました。
(もう少し段階を踏むのであれば、assert_response :success
が通ることを確認してから、assert_select "title", "Contact | #{@base_title}"
が通ることを確認するテストを追加するのでしょうが、今回はやることが明白だったためまとめました)