🐕

Rails(Docker)に必要なGemを追加する (CI/CDまでの道③)

2022/01/14に公開2

はじめに

前回に引き続き、今回はRails環境にhaml, Rspec, Rubocop, I18nのGemを導入していきたいと思います。各自必要なものを導入してください。
Hamlの導入でGemの追加方法の基本については説明していますので、理解してからGemfileから消していただければと思います。

作成に使用するリポジトリはこちらとなります。

CI/CDの道シリーズ

環境

  • WSL2 (Ubuntu20.04)
  • Docker 20.10.9
  • docker-compose 1.29.1
  • Git 2.25.1
  • VSCode

Hamlの導入

hamlの導入方法

こちらを参考に行っていきます。

まずは/Gemfileの最後に以下の行を追加します。

Gemfile
gem 'haml-rails'

コンテナを起動してbundle isntallを行います。
そのあと、すでに書かれているerbのファイルをすべてhamlファイルに変換します。

$ docker-compose up --build

# 起動できたらコンテナの中に入る
# 別のターミナルをひらく
$ docker exec -it rails sh

# hamlに変換
$ rails haml:erb2haml

# ※Would you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n)にyと答える

app/views/test/index.html.hamlを確認するとhamlに変換されているのが確認できます。

app/views/test/index.html.haml
%h1 Hello World
%h2 CSSが適応されると色が変わる
%button.btn.btn-primary{:type => "button"} Bootstrap適応

localhost:3000/testにアクセスして表示されればOKです。

Rspecの導入

RailsアプリへのRspecとFactory_botの導入手順

こちらを参考に導入します。

まずはGemfileに以下を追加します。

Gemfile
group :development, :test do
  gem "rspec-rails"
  gem "factory_bot_rails"
end

group :depelopment, :testに2つ追加しています。(開発環境でしか利用しないため)

あとはhamlと同じ流れでインストールしていきます。
最後のコマンドで必要なファイルを生成します。

$ docker-compose --build

# コンテナの中に入る
# 別のターミナルをひらく
$ docker exec -it rails sh
$ bundle exec rails generate rspec:install

今回はrequestとmodelのテストのみ行いますのでそれ以外を無効にする設定をconfig/application.rbに書きます。classのなかに追加します。

config/application.rb
config.generators do |g|
  g.test_framework :rspec, 
        view_specs: false, 
        helper_specs: false, 
        controller_specs: false, 
        routing_specs: false
end

次にFactoryBotの設定をしていきます。
FactoryBot.createのように書くのは大変なので、createだけで書けるように設定します。

spec/rails_helper.rb

spec/rails_helper.rb
(省略)
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods

end
(省略)

config.include...を追加します。Rspec.config doの下でよいです。

ここまでできたらRspecが利用できるか確認します。

spec/requestsディレクトリを作成してtest_request_spec.rbというファイルを作成し、以下の内容を書きます。/testにアクセスできるかを確認しています。

spec/requests/test_request_spec.rb

spec/requests/test_request_spec.rb
require 'rails_helper'

RSpec.describe "Test", type: :request do

	describe 'GET /test' do
		subject(:result) { get test_path }

		it 'アクセスできること' do
			expect(result).to eq 200
		end
	end
end

ここでテストをしたところRailsコンテナにnode_modulesがないためActionView::Template::Error:が発生したため、docker-compose.ymlを以下に変更します。

docker-compose.yml

docker-compose.yml
version: "3.9"
services:
  rails:
    build: .
    container_name: rails
    command: ash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
      - /myapp/node_modules
      - public-data:/myapp/public
    ports:
      - "3000:3000"
    env_file:
      - .env
    depends_on:
      - db
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker

  webpacker:
    build: .
    container_name: webpacker
    volumes:
      - .:/myapp
      - /myapp/node_modules
      - public-data:/myapp/public
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"


  db:
    image: mysql:8.0.27
    container_name: db
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
    driver: local
  bundle:
    driver: local
  public-data:

テストを実行します。別のターミナルを開いて以下のコマンドを実行します。

$ docker exec -it rails sh
$ rspec ./spec/requests/test_request_spec.rb

以下のようになれば成功です。

/myapp $ rspec ./spec/requests/test_request_spec.rb 
.

Finished in 9.39 seconds (files took 0.9067 seconds to load)
1 example, 0 failures

Rubocopの導入

【Rails】RuboCop 導入編(2020年10月版)

こちらを参考にします。

Gemfileに以下を追加します。

Gemfile
group :development do
  (省略)
  gem 'rubocop', require: false
  gem 'rubocop-performance', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-rspec'
end

group :developmentに4つ追加します。下に追加してください。

コンテナを起動して、必要なファイルを生成します。

$ docker-compose --build
# 別のターミナルを開く
$ docker exec -it rails sh
$ bundle exec rubocop --auto-gen-config

成功するとrobocop.to_do.ymlrobocop.ymlが作成されます。

rubocop.to_do.ymlを削除します。
そのあとrubocop.ymlの内容を以下に変更します。

rubocop.yml
Style/Documentation:
  Enabled: false

# 除外するファイル
AllCops:
  Exclude:
    - db/schema.rb
    - tmp/**/*
    - vendor/bundle/**/*
    - Rakefile
    - config.ru
    - lib/*
    - bin/**/*
    - db/**/*
    - Gemfile
    - test/**/*
    - node_modules/**/*
    - config/application.rb
    - config/environments/*
  NewCops: enable

では、Rubocopが動くかを確認します。

# コンテナの中で以下のコマンド
$ rubocop -A

# エラーが0になる
$ rubocop -A

1回目はエラーが自動で修正されますので、2回実行します。
以下になればOK

27 files inspected, no offenses detected

また、Couldn't create cache directory. Continuing without cache. Permission denied @ dir_s_mkdir - /.cacheというのがログに多発します。これはユーザーを追加することで消すことができます。

【Ruby on Rails】 Permission denied @ dir_s_mkdir の解消法

今回はDockerfileでUSER appとしてデフォルトユーザーをしているためrubocop -Aで権限エラーが出ることはないと思います。

I18nの導入

[初学者]Railsのi18nによる日本語化対応
【Rails】 I18n入門書~日本語化対応の手順と応用的な使い方

こちらを参考にしました。

まずはGemfileに以下を追加します。下に追加しました。

Gemfile
gem 'rails-i18n'

インストールします。

$ docker-compose --build

次に/config/locales/ja.ymlを作成して以下の内容を追加します。

/config/locales/ja.yml
ja:
  word:
    greeting:
      hello: "こんにちは"

次にconfig/application.rbのclassの中に以下を追加します。

config/application.rb
(省略)
module Myapp
  class Application < Rails::Application
    config.i18n.default_locale = :ja # 追加
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1
(省略)

これで設定ができました。実際に"こんにちは"と表示してみます。
app/views/test/index.html.hamlを以下に変更します。

app/views/test/index.html.haml
%h1 Hello World
%h2 CSSが適応されると色が変わる
%button.btn.btn-primary{:type => "button"} Bootstrap適応
= I18n.t("word.greeting.hello")

一度buildしなおします。

$ docker-compose --build

localhost:3000/testにアクセスします。成功するとこんにちはと表示されます。

おわりに

作成したものはこちらのリポジトリに用意しています。

今回は最低限必要なGemを追加してみました。
Dockerは権限関係がかなり難しくまだわからないことも多いです。

次回は本番環境用にNginxを追加します。

参考

GitHubで編集を提案

Discussion

masamasa

USERをappにするとファイルのパーミッションの関係でrspecが失敗します。
docker exec -it rails shでコンテナに入ったときにrootである必要がありました。

masamasa

docker-compose --buildではなくdocker-compose up --buildの間違いだと思います。