はじめに
Rails Tips の 52 回目です。昨日、サーバを立ち上げようとしたらデータベースのエラーになってしまいました。ひとまずデータベースを作成しましょう。
データベースの作成
homebrew でインストールした postgresql の/opt/homebrew/var/postgresql@16/pg_hba.conf を確認したところ、local からのアクセスは trust になっていました。development で実行している限りはパスワードなどの設定は必要ないです。
# TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all trust # IPv4 local connections: host all all 127.0.0.1/32 trust # IPv6 local connections: host all all ::1/128 trust
実際、config/database.yml を確認してみると、特にパスワードなどの設定も書かれていません。
default: &default adapter: postgresql encoding: unicode # For details on connection pooling, see Rails configuration guide # https://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> development: <<: *default database: hkob_blog_development # The specified database role being used to connect to PostgreSQL. # To create additional roles in PostgreSQL see `$ createuser --help`. # When left blank, PostgreSQL will use the default role. This is # the same name as the operating system user running Rails. #username: hkob_blog # The password associated with the PostgreSQL role (username). #password: # Connect on a TCP socket. Omitted by default since the client uses a # domain socket that doesn't need configuration. Windows does not have # domain sockets, so uncomment these lines. #host: localhost
この状態で、db:create してみましょう。
$ bin/rails db:create Created database 'hkob_blog_development' Created database 'hkob_blog_test'
無事に成功できています。再度 bin/rails s をすると今度は正しく Rails の画面が表示されました。
generator の設定
コントローラを作成する前に generator の設定が必要でした。config/initializers の下に generators.rb を作成し、以下の内容を記述します。test_framework を rspec に接停止、fixtures、request_spec のみ true にします。
Rails.application.config.generators do |g| g.test_framework :rspec g.stylesheets false g.javascripts false g.helper false g.channel assets: false g.fixtures true g.view_specs false g.routing_specs false g.controller_specs false g.request_specs true g.helper_specs false end
4.2 Railsで「Hello」と表示する
そろそろ、Rails ガイドの内容に戻ります。最初に config/routes.rb
に /articles
のルーティングを設定します。これは /articles
というパスに get でアクセスした場合には、articles_controller
の index
アクションを呼び出すという意味です。
get "/articles", to: "articles#index"
このためには articles_controller を作成する必要があります。g controller を実行すると以下に示すファイルが作成されています。generator.rb でかなりのものを false にしたので必要最低限のものしか作成されていません。
$ bin/rails g controller articles index --skip-routes create app/controllers/articles_controller.rb invoke haml create app/views/articles create app/views/articles/index.html.haml invoke rspec create spec/requests/articles_spec.rb
ここで、spec/requests/articles_spec.rb が作成されるのですが、先日作った雛形のものではありません。
require 'rails_helper' RSpec.describe "Articles", type: :request do describe "GET /index" do it "returns http success" do get "/articles/index" expect(response).to have_http_status(:success) end end end
実は、先日用意したテンプレートは integration_test のものでした。ここで以下のように integration_test の generator を再度実行し、上書きをします。
> bin/rails g integration_test articles invoke rspec conflict spec/requests/articles_spec.rb Overwrite /Users/hkob/Library/CloudStorage/Dropbox/rails/hkob_blog/spec/requests/articles_spec.rb? (enter "h" for help) [Ynaqdhm] force spec/requests/articles_spec.rb
作成した request spec の index の部分だけを生かしました。以下の修正をしています。
- 1行目の rubocop の
# rubocop:disable all
を消しました。 - describe の後ろを文字列ではなく Controller のクラス名にしました。
- まだログインしていないので所有などの概念はないため権限周りの部分は外しています。
Hello, Rails!
が表示されることを確認します。
require "rails_helper" RSpec.describe ArticlesController, type: :request do # let!(:article) { articles :can_delete } # let!(:object) { article } # let!(:attrs) { object.attributes } # let(:not_mine) { articles :not_mine } # let(:return_path) { articles_path } # context "login by hkob" do # user_login :hkob describe "GET #index" do subject { -> { get articles_path } } it_behaves_like "レスポンスコード確認", 200 it_behaves_like "描画結果に文字列が含まれている?", %w[Hello Rails!] end
保存すると guard のテストが実行され、以下のようなエラーになります。当然、まだ shared_example を用意していないので当然ですね。先に用意しておくべきでした。以前紹介したものを使うたびに shared_example.rb に追加していきましょう。
21:17:54 - INFO - Running: spec/requests/articles_spec.rb An error occurred while loading ./spec/requests/articles_spec.rb. Failure/Error: it_behaves_like "レスポンスコード確認", 200 ArgumentError: Could not find shared examples "レスポンスコード確認" # ./spec/requests/articles_spec.rb:15:in `block (2 levels) in <top (required)>' # ./spec/requests/articles_spec.rb:13:in `block in <top (required)>' # ./spec/requests/articles_spec.rb:3:in `<top (required)>' No examples found. Finished in 0.00003 seconds (files took 1.74 seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples
shared examle の追加
まだファイルも用意していなかったので、spec/support
ディレクトリを作成し、その下に shared_exmpale
.rb を追加します。
$ mkdir -p spec/support $ touch spec/support/shared_example.rb
使っている shared_example はこちらの過去の記事に書かれています。
- レスポンスコード確認 shared_example : 小林研 Rails Tips (20)
- 描画結果に文字列が含まれている?・いない? shared_example : 小林研 Rails Tips (21)
shared_example を保存すると再度テストが実行され、二つのうちの一つは通ったことが確認できます。失敗しているのは「Hello Rails?」がページに含まれているのテストが失敗しています。
Finished in 0.17995 seconds (files took 1.56 seconds to load) 2 examples, 1 failure Failed examples: rspec ./spec/requests/articles_spec.rb:16 # ArticlesController GET #index behaves like 描画結果に文字列が含まれている? レスポンスの文字列が「["Hello", "Rails!"]」を含むこと
このテストを通過させるために、ガイドの通りに app/views/articles/index.html.haml を以下のように修正しましょう。
%h1 Hello, Rails!
view が書きかわったら以下のようにテストが全部通過しました。
21:30:14 - INFO - Running: spec/requests/articles_spec.rb ArticlesController GET #index behaves like レスポンスコード確認 レスポンスのステータスが 200 であること behaves like 描画結果に文字列が含まれている? レスポンスの文字列が「["Hello", "Rails!"]」を含むこと Finished in 0.07406 seconds (files took 1.54 seconds to load) 2 examples, 0 failures
実際にブラウザで http://localhost:3000/articles
を確認すると確かに Hello, Rails! が表示されていることが確認できました。
おわりに
Rails ガイドではテストを記述していませんが、この記事では必ずテストを書き、テスト失敗を確認した上で実装を記述していきます。