20200116のRailsに関する記事は21件です。

ログイン機能の実装(ウィザード形式にするために)

1.deviseの導入及びユーザーのデフォルトでのログインが可能になるまで

以下の手順で導入

GEMFILE.
gem 'devise'
ターミナル.
rails g devise:install

任意のコントローラー(***)を用意して、ルーティングの設定をします。
この場合は、トップページに当たる部分のルーティングの設定をしています。

config/routes.rb
Rails.application.routes.draw do
  root to: "***#index"
end
ターミナル.
rails g controller ***

今回はindexアクションにおいて、特にモデルとのやり取りなどは行わないので、コントローラ内の記述はしません。(任意でトップページのビューは作成したものを使用)

次いでdeviseにおけるデフォルトのログイン機能を実装します。

ターミナル.
rails g devise user

今回は、deviseのデフォルトで用意されているemailとpasswordを最初のビュー場で登録させてから、次のページにてuserのprofileを登録するようにしたいと思います。
その為、そのまま下記のコマンドを実行していきます。

ターミナル.
rails db:migrate

※ただし、今回とは異なりuserモデルの方に名前等を追加したい場合には、下記のコマンド実行前にマイグレーションファイルの編集をしてカラムの追加の必要性が発生します。
その場合には下記のようにコントローラー及びモデルのバリデーションの記述を一部追加する必要性がある

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:追加カラム名, :追加カラム名])
  end
end
app/models/user.rb
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  validates :追加カラム名, :追加カラム名 ,presence: true
end

上記を任意の状況に応じて実行後、追加したカラムを入力できるように、新規登録画面のビューを編集する必要があります。デフォルトではdeviseのビューファイルは隠れているので、以下のコマンドを実行します。

ターミナル.
rails g devise:views
app/views/devise/registrations/new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :追加カラム名 %><br />
    <%= f.text_field :追加カラム名 %>
  </div>

  <div class="field">
    <%= f.label :追加カラム名 %><br />
    <%= f.number_field :追加カラム名 %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

<%# 以下省略 %>

※追加するカラムがない場合にはrails db:migrateを実行後にここまでの操作を省略して、以下から続きを実行
任意のビューに下記の記述を追加してログインしていない場合には新規登録またはログインを実行させる画面に移行させる記述を追記していきます。

app/views/***/index.html.erb
<% if user_signed_in?%>
  <h2>ログインしています</h2>
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<% else %>
  <h2>ログインしていません</h2>
  <%= link_to "新規登録", new_user_registration_path %>
  <%= link_to "ログイン", new_user_session_path %>
<% end %>

2.ウィザード形式でのユーザーの新規登録を実行出来るようにする

今回やっていくこととしては、ユーザー登録の画面でユーザー情報を入力させ、それをsessionに保持させておきます。そして次のプロフィール情報を登録する画面で名前や年齢、性別を入力させ、最後のステップでsessionに保持していたユーザー情報と、それに関連するプロフィール情報をテーブルに保存する流れで行なっていきます。
まず、まだ作成していないプロフィールモデルの作成を実行します。

ターミナル.
rails g model profile

次いで、Userモデルとのリレーションのために、外部キーとしてuser_idが入るようにして、コマンドを実行します。

db/migrate/20XXXXX.rb
class CreateProfiles < ActiveRecord::Migration[5.2]
  def change
    create_table :profiles do |t|
      t.string :name, null: false
      t.integer :age, null: false
      t.string :gender, null: false
      t.references :user
      t.timestamps
    end
  end
end
ターミナル.
rails db:migrate

マイグレートを実行後、テーブルやカラム作成されているか確認して、モデルのバリデーションおよびアソシエーションを設定します。
Userモデルに対してoptional: trueを設けています。optional: trueは外部キーがnullであることを許可するオプションです。
同様にUserモデルについてもアソシエーションを設定します。

app/models/profile.rb
class Profile < ApplicationRecord
  belongs_to :user, optional: true
  validates :name, :age, :gender ,presence: true
end
app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_one :profile
end

次いでdeviseのコントローラを作成し、編集できる形にします。

ターミナル.
rails g devise:controllers users

現状rake routesを行うとdevise管理化のコントローラーが呼ばれてしまっているということが確認できます。
そこで以下のようにroutes.rbを編集して、どのコントローラを参照するのか明示してあげます。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations',
  }
  root to: "***#index"
end

編集後に再度rake routesをすると、参照するコントローラが変更されていることが確認できます。(今回はユーザ新規登録に必要なregistrationsコントローラのみに適用)

そしてここからの流れを再度確認すると
●userモデルのインスタンスの作成
●バリデーションチェックしたユーザー情報をsessionに保持してprofileモデルのインスタンスの生成
●バリデーションチェックしたバリデーションチェックしたプロフィール情報とsessionで保持していたユーザー情報を保存
という流れで実装していく必要があります。

userモデルのインスタンスの作成

app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
# 省略
  def new
    @user = User.new
  end
# 省略
end

newアクションに対応するフォーム形成

app/views/devise/registrations/new.html.erb
<h2>ユーザー情報登録</h2>

<%= form_for(@user, url: user_registration_path) do |f| %>
  <%= render "devise/shared/error_messages", resource: @user %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Next" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

上記で元のところからの変更点は、resourceという文字列部分(このdeviseのログイン機能で実装されるモデルが入るresourceとは、仮引数のようなもので実装する状況に応じたモデル名に変更する必要がありそうです)やボタンをnextにするなど細かい部分を修正しています。
変更後にビューが反映されているかを確認します。
確認後はユーザー登録フォーム上で"Next"をクリックすると、次の情報を登録するページに遷移しますが、その前にcreateアクション内で追記する必要があるので下記のように編集を実施します。

createアクションの編集

app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]

# 省略

   def create
    @user = User.new(sign_up_params)
    unless @user.valid?
      flash.now[:alert] = @user.errors.full_messages
      render :new and return
    end
    session["devise.regist_data"] = {user: @user.attributes}
    session["devise.regist_data"][:user]["password"] = params[:user][:password]
    @profile = @user.build_profile
    render :new_profiles
  end

# 省略

  protected

  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
  end

end

上記の編集によってどのようになったかを項目ごとに確認していきます。

1ページ目で入力した情報のバリデーションチェック

まず、Userモデルのインスタンスを生成し、最初の画面から送られてきたパラメータをインスタンス変数@userに代入します。そのインスタンス変数に対してvalid?メソッドを適用することで送られてきたパラメータが指定されたバリデーションに違反しないかどうかチェックしています。falseになった場合は、エラーメッセージとともにnewアクションへrenderさせます。

1ページで入力した情報をsessionに保持させること

次いで入力した情報をsessionに保持させます。
今回のようにウィザード形式にする場合には最後のページまで遷移した後に保存するというようにするために、今回はsessionという機能を用います。
バリデーションチェックが完了したら、session["devise.regist_data"]に値を代入します。この時、sessionにハッシュオブジェクトの形で情報を保持させるために、attributesメソッドを用いてデータを整形しています。また、paramsの中にはパスワードの情報は含まれていますが、attributesメソッドでデータ整形をした際にパスワードの情報は含まれていません。そこで、パスワードを再度sessionに代入する必要があります。

次画面にてプロフィール情報登録で使用するインスタンスを生成、当該ページへ遷移すること

次画面では、このユーザーモデルに紐づくプロフィール情報を入力させるため、該当するインスタンスを生成しておく必要があります。そのために、build_profileで今回生成したインスタンス@userに紐づくProfileモデルのインスタンスを生成します。ここで生成したProfileモデルのインスタンスは、@profileというインスタンス変数に代入します。そして、プロフィール情を登録させるページを表示するnew_profileアクションのビューへrenderしています。

次にnew_profileアクションとcreate_profileアクションのルーティングを設定します。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  devise_scope :user do
    get 'profiles', to: 'users/registrations#new_profile'
    post 'profiles', to: 'users/registrations#create_profile'
  end
  root to: "***#index"
end
app/views/devise/registrations/new_profile.html.erb
<h2>プロフィール情報登録</h2>

<%= form_for @profile do |f| %>
  <%= render "devise/shared/error_messages", resource: @profile %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.label :age %><br />
    <%= f.text_field :age %>
  </div>

  <div class="field">
    <%= f.label :gender %><br />
    <%= f.text_field :gender %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

ルーティング先のビューも下記のように作成して、画面遷移の確認をします。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  devise_scope :user do
    get 'profiles', to: 'users/registrations#new_profile'
    post 'profiles', to: 'users/registrations#create_profile'
  end
  root to: "***#index"
end

最後にcreate_profileアクションで、ユーザー情報とプロフィール情報全てをテーブルに保存するように実装します。

create_profileアクションの再編集
app/controllers/users/registrations_controller.rb
#省略

  def create_profile
    @user = User.new(session["devise.regist_data"]["user"])
    @profile = Profile.new(profile_params)
    unless @profile.valid?
      flash.now[:alert] = @profile.errors.full_messages
      render :new_profile and return
    end
    @user.build_profile(@profile.attributes)
    @user.save
    sign_in(:user, @user)
  end

#省略

  protected

  def profile_params
    params.require(:profile).permit(:name, :age, :gender)
  end

上記の編集によってどのようになったかを項目ごとに確認していきます。

2ページ目で入力したプロフィール情報のバリデーションチェック

最初の入力画面でのcreateアクションと同様に、valid?メソッドを用いて、バリデーションチェックを行います。

バリデーションチェックが完了した情報と、sessionで保持していた情報とあわせ、ユーザー情報として保存すること

build_profileを用いて送られてきたparamsを、保持していたsessionが含まれる@userに代入します。そしてsaveメソッドを用いてテーブルに保存します。

ログインをすること

ユーザーの新規登録ができても、ログインができているわけではありません。それをsign_inメソッドを利用してログイン作業を行いましょう。
上記が完了したらprofile_createに対応するビューを作成します。

app/views/devise/registrations/create_profile.html.erb
<h2>登録が完了しました</h2>
<%= link_to "トップへ戻る", root_path%>
sessionを削除すること

このようにすることでユーザー登録画面をウィザード形式にすることが可能となります。
次の記事ではSNS認証をこちらに追加していきたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【RSpec】同じパターンのテストシナリオをJSONで定義して外出しする

解決できるケース

以下のようなケースに適用できると思います。
あくまで飛び道具的な手法なので、常用は良いと思いません。

  • 同じ機能を複数のパラメータパターンで実行して結果を評価する場合、実装を軽量化できる。
  • JSONファイルにパラメータ部分のみを外出しするため、RSpecを書けない人でもテストケースのメンテナンスが可能

経緯

ある案件で給与計算モジュールを実装した際に、深夜・残業・休日の手当や、勤務時間に関するモジュールなどを実装し、それぞれテストケースを作りました。
ただ、それだと心もとないため、給与計算モジュール群の統合テストケースを実装することとなりました。

例えば、
「時給¥1000で10:00~15:00勤務」「時給¥1001円で18:00~24:00勤務」・・・など
一定のパラメータに複数パターンを入力して結果を評価するテストケースが必要になりました。
そこで、ケースはJSONファイルに書き出しておき、テストの実装はループでやってみようということで、以下のようなRSpecを作成しました。

実装

contextをtest_caseの数分ループすることで、同じようなテストケースをずらずら書き並べる必要がなくなっています。
※内容は例なので簡略化しています。

Rspec

  # 給与計算パターンの検証
  describe 'calculate salary' do

    # テストケースJSONファイルをロード
    test_cases = JSON.parse(IO.read(Rails.root.join("spec/json/salary_calculator_test_case.json")), symbolize_names: true)

    # テストケースの数分、テストを実行する
    test_cases.each do |test_case|

      # [:execution]がfalseのテストケースは無視する
      next unless test_case[:execution]

      # [:pattern]に設定してあるケース名を引用
      context "case [#{test_case[:pattern]}]" do

        # 勤務時間
        let(:worktimes) { test_case.key?(:worktimes) ? test_case[:worktimes] : [] }
        # 休憩時間
        let(:resttimes) { test_case.key?(:resttimes) ? test_case[:resttimes] : [] }
        # 給与
        let(:hourly_wage) { test_case.key?(:hourly_wage) ? test_case[:hourly_wage] : 1000 }

        # 計算処理の実行結果を評価対象とする
        subject { execute(worktimes, resttimes, amount)}

        # テスト結果の評価
        it 'calculate correctly ' do
            expect(subject).to eq test_case[:expect]
        end
      end
    end
  end

テストケースJSON

[
    {
        "pattern": "work 10:00-15:00/rest 12:00-13:00/hourly_wage ¥1000",
        "worktimes": [
            { "start": "2020-01-06 10:00:00", "end": "2020-01-06 15:00:00" }
        ],
        "resttimes": [
            { "start": "2020-01-06 12:00:00", "end": "2020-01-06 13:00:00" }
        ],
        "hourly_wage": 1000,
        "expect": 4000,
        "execution": true,
        "comment": "通常"
    },
    {
        "pattern": "work 18:00-24:00/rest 20:00-21:00/hourly_wage ¥1001",
        "worktimes": [
            { "start": "2020-01-06 18:00:00", "end": "2020-01-07 00:00:00" }
        ],
        "resttimes": [
            { "start": "2020-01-06 20:00:00", "end": "2020-01-06 21:00:00" }
        ],
        "hourly_wage": 1001,
        "expect": 5501
        "execution": true,
        "comment": "深夜手当あり"
    },
    {
        ...
    }
    ...
]

JSONのテストケース中には、以下の項目を含んでおくと便利でした。

  • "execution": テストケースを実行するかどうか。1ケースだけテストしたい時に他を全てfalseにして無駄な時間を食わずに済む。
  • "comment": テストでは使用しないが、メンテナンス時にわかりやすくなる。テストケースを定義した資料に記載されているケース名を転記して、わかりやすくしたり。

あとがき

ご参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]使用中のlocalhost3000のプロセスを切る

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです!

localhost:3000で別のサーバーを起動したい

localhost:3000でサーバーを起動しようとしたら別のRailsのプロジェクトで使用していたのを忘れていました。

$ rails s
/Users/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/railties-6.0.2.1/lib/rails/app_loader.rb:53: warning: Insecure world writable dir /Users in PATH, mode 040777
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
A server is already running. Check /Users/Desktop/project/tmp/pids/server.pid.
Exiting

3000のポートを使用している物を確認!

sudo lsof -nP -iTCP:3000 -sTCP:LISTEN
COMMAND   PID             USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    40429 tester.user        29u  IPv4 0xbed1da96d5b6b725      0t0  TCP *:3000 (LISTEN)
ruby    70168 tester.user        12u  IPv4 0xbed1da96d2fa3425      0t0  TCP 127.0.0.1:3000 (LISTEN)
ruby    70168 tester.user        13u  IPv6 0xbed1da96b93aa9e5      0t0  TCP [::1]:3000 (LISTEN)

プロセス番号(PID)を指定してプロセスを切る

kill -9 70168

これで完了!

参考記事

Rails sのプロセスが切れない時
Killing MailCatcher: Something's using port 1025

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者 アプリ開発

初めましてプログラミング初心者です
お店の空席確認ができるアプリを作成しています
ログインして席の番号をクリック
jsで席の番号の色が変わるように実装しました

ログアウトの機能も実装してあるのですが

リロードした時に番号の色が変わらずログアウトした時のみ色が変わるような実装がしたいです

セッションを使えば実装できるのでしょうか

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macOSをCatalinaにしたらRubyとRailsが消えた時【zsh: /usr/local/bin/rails: bad interpreter: System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: no such file or directory】の対処

Catalinaにした後Rubymineのプラグインを挿入後の再起動でRailsが消えた

エディターでRubymineを使用しているのですが、プラグインを挿入し再起動、%rails sなどのコマンドをしても、『Rails is not currently installed on this system. To get the latest version, simply type: $ sudo gem install rails』とエラーが発生。

rbenvのパスの設定が変わったと想定

ここら辺の環境設定ではプログラミング初心者はとても頭を悩ます分野。
プログラミングスクールのDive Into Codeに通っていた頃、メンターの皆様によく教わりました。
「bash~が〜」とか「システムでのRubyとローカルは違う〜」「rbenvのpathは〜」
色々教わりましたが、Rubyの構文やRailsの仕組み、そもそもブラウザの仕組みやHTMLやCSSを働きながら多方面の分野を勉強する為、環境構築はとても苦手でした。

極論:教授して頂いたコードをコピペ

ここでは一応腹落ちするまで教えて頂きましたが、30分ググったりして悩んだ場合は素直に教えてもらい先に進んだ方が良い。ただ自分のこの調べる力は、後々のエンジニアとしての『再現性』を豊にするの実感。
エンジニアの8~9割りはエラーやバグの解決に時間を要する為、プログラミング初心者は解決できなくともそこで挫折しないで良い経験だとして、力として欲しい。

「~/.zshrc」ファイルにrbenvのpath設定をしてあげる

話題を本題に戻します。
%which ruby をコマンドした場合、
/usr/bin/ruby の表示。
このままだと、いくら%rails sなどのRailsコマンドをしても、
【zsh: /usr/local/bin/rails: bad interpreter: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: no such file or directory
Rails is not currently installed on this system. To get the latest version, simply type:】のエラー表示が出る。
その後には、【 $ sudo gem install rails】とアドバイスされる。

結果論: $ sudo gem install railsのコマンドは要らない

元々railsのgemはインストールされている中で、pathが違った為のエラー。
なので、pathを通す為にコマンドしてあげれば良い。

%which rubyで【/Users/ユーザー名/.rbenv/shims/ruby】になるまで

https://teratail.com/questions/218281 このサイトを参考にしました。
ただここでは一時的な解決にしかならない為、エディターを再起動したり、違うターミナル開けた場合、同じエラーになりました。

対処法の結論

%echo 'export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"' >> ~/.zshenv
%echo 'eval "$(rbenv init -)"' >> ~/.zshenv
%echo 'source $HOME/.zshenv' >> ~/.zshrc
exec $SHELL
source $HOME/.zshenv

%Which ruby
/Users/ユーザー名/.rbenv/shims/ruby

%which rails
/Users/ユーザー名/.rbenv/shims/rails

もうOSのアップデートの度に、びっくりしなくて済みます。

参考にしたサイト

https://medium.com/@petehanner/getting-rails-to-work-with-catalina-zsh-84146e1d2099
備忘録としてコマンドだけをツイートしたのも残しておきます。
https://twitter.com/ARTS_papa/status/1217754991819030529

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Homebrew + rbenv + Bundler + dockerで開発環境をマネージドに構築する(番外編-Ruby on Railsアプリ)

後編〜からの続き

前提

  • 便宜上、既存のワーキングコピーがあります
  • ただし、 Dockerfiledocker-compose.yml は後編からガラッと変わります

Docker手順

Dockerfileのコマンド

コマンド 説明
FROM 使用するイメージとバージョン
RUN コマンドの実行。railsに必要な必要なnodejsとpostgeqsqlをインストールしている
WORKDIR そのままの意味。作業ディレクトリを設定します。
ADD ローカルのファイルをコンテナへコピーする(昔のCOPYコマンドになります)
ENTRYPOINT 一番最初に実行するコマンド(ここではentrypoint.shを参照)
EXPOSE コンテナがリッスンするport番号
CMD イメージ内部のソフトウェア実行(つまりRailsのことですね)
1. Dockerfileを作成する
Dockerfile
FROM ruby:2.6.5

# Setting environment
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
ENV APP_HOME /var/www/capistrano_sample_app_v1

# Install libraries
RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs \           
                       vim \
                       default-mysql-client
RUN gem install bundler -v '2.1.4'

# Create app home
RUN mkdir -p $APP_HOME

WORKDIR $APP_HOME

# Copy Gemfile from origin
ADD Gemfile $APP_HOME/Gemfile

RUN bundle _2.1.4_ install --path vendor/bundle

ADD . $APP_HOME
2. docker-composeを作成する
docker-compose.yml
version: '3'
services:
  mysql:
    # https://dev.mysql.com/doc/relnotes/mysql/5.7/en/
    image: mysql:5.7
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: capistrano_sample
      MYSQL_USER: developer
      MYSQL_PASSWORD: %masking%
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    command: mysqld --innodb_file_per_table=1 --innodb_file_format=barracuda --innodb_large_prefix=1
  redis:
    # https://github.com/RedisLabs/docker-library-redis
    image: redis:3.2-alpine
  # memcached:
    # https://github.com/autopilotpattern/memcached/releases
    # image: memcached:1.4-alpine
  app:
    build:
      context: .
      dockerfile: "Dockerfile"
    tty: true
    stdin_open: true
    ports:
      - "8080:8080"
    # environment:
      # RAILS_LOG_TO_STDOUT: "true"
      # STACKDRIVER_LOGGING_MODE: "agent"
    # command: /bin/sh -c "rm -f /capistrano_sample_app_v1/tmp/pids/server.pid && bundle exec rails s -p 8080 -b '0.0.0.0'"
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 8080 -b '0.0.0.0'"
    volumes:
      # ホストのカレントディレクトリをコンテナの/appにマウント
      - "./:/app"
    links:
      - mysql
      - redis
      # - memcached
3.docker build
Terminal
$ docker-compose up --build
Creating network "capistrano_sample_app_v1_default" with the default driver
Pulling mysql (mysql:5.7)...
5.7: Pulling from library/mysql
804555ee0376: Pull complete
c53bab458734: Pull complete
ca9d72777f90: Pull complete
2d7aad6cb96e: Pull complete
8d6ca35c7908: Pull complete
6ddae009e760: Pull complete
327ae67bbe7b: Pull complete
9e05241b7707: Pull complete
e822978df8f0: Pull complete
14ca71ed53be: Pull complete
026afe6fd35e: Pull complete
Digest: sha256:2ca675966612f34b4036bbcfa68cb049c03e34b561fba0f88954b03931823d29
Status: Downloaded newer image for mysql:5.7
Pulling redis (redis:3.2-alpine)...
3.2-alpine: Pulling from library/redis
4fe2ade4980c: Pull complete
fb758dc2e038: Pull complete
989f7b0c858b: Pull complete
42b4b9f869ad: Pull complete
17e06138ef20: Pull complete
c0ecd66db81e: Pull complete
Digest: sha256:e9083e10f5f81d350a3f687d582aefd06e114890b03e7f08a447fa1a1f66d967
Status: Downloaded newer image for redis:3.2-alpine
Building app
Step 1/11 : FROM ruby:2.6.5
 ---> a161c3e3dda8
Step 2/11 : ENV LANG C.UTF-8
 ---> Using cache
 ---> 5e1f7a284c55
Step 3/11 : ENV TZ Asia/Tokyo
 ---> Using cache
 ---> 36064309c74a
Step 4/11 : ENV APP_HOME /var/www/capistrano_sample_app_v1
 ---> Using cache
 ---> b6ad93523f4f
Step 5/11 : RUN apt-get update -qq &&     apt-get install -y build-essential                        libpq-dev                        nodejs                        vim                        default-mysql-client
 ---> Using cache
 ---> 27f7958c4205
Step 6/11 : RUN gem install bundler -v '2.1.4'
 ---> Using cache
 ---> 2152e68a959d
Step 7/11 : RUN mkdir -p $APP_HOME
 ---> Using cache
 ---> 34bf7f30bbcb
Step 8/11 : WORKDIR $APP_HOME
 ---> Using cache
 ---> 1be2dad77d77
Step 9/11 : ADD Gemfile $APP_HOME/Gemfile
 ---> Using cache
 ---> f2549fe43d36
Step 10/11 : RUN bundle _2.1.4_ install --path vendor/bundle
 ---> Using cache
 ---> 55ba3d1dbf0c
Step 11/11 : ADD . $APP_HOME
 ---> 4d459e27e55e
Successfully built 4d459e27e55e
Successfully tagged capistrano_sample_app_v1_app:latest
Creating capistrano_sample_app_v1_mysql_1 ... done
Creating capistrano_sample_app_v1_redis_1 ... done
Creating capistrano_sample_app_v1_app_1   ... done
Attaching to capistrano_sample_app_v1_redis_1, capistrano_sample_app_v1_mysql_1, capistrano_sample_app_v1_app_1
mysql_1  | 2020-01-16 09:55:41+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.29-1debian9 started.
redis_1  | 1:C 16 Jan 09:55:40.955 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
mysql_1  | 2020-01-16 09:55:45+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
redis_1  |                 _._                                                  
redis_1  |            _.-``__ ''-._                                             
redis_1  |       _.-``    `.  `_.  ''-._           Redis 3.2.12 (00000000/0) 64 bit
redis_1  |   .-`` .-```.  ```\/    _.,_ ''-._                                   
redis_1  |  (    '      ,       .-`  | `,    )     Running in standalone mode
redis_1  |  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
redis_1  |  |    `-._   `._    /     _.-'    |     PID: 1
redis_1  |   `-._    `-._  `-./  _.-'    _.-'                                   
redis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|                                  
redis_1  |  |    `-._`-._        _.-'_.-'    |           http://redis.io        
redis_1  |   `-._    `-._`-.__.-'_.-'    _.-'                                   
redis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|                                  
redis_1  |  |    `-._`-._        _.-'_.-'    |                                  
redis_1  |   `-._    `-._`-.__.-'_.-'    _.-'                                   
redis_1  |       `-._    `-.__.-'    _.-'                                       
redis_1  |           `-._        _.-'                                           
redis_1  |               `-.__.-'                                               
redis_1  | 
redis_1  | 1:M 16 Jan 09:55:40.961 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 16 Jan 09:55:40.961 # Server started, Redis version 3.2.12
redis_1  | 1:M 16 Jan 09:55:40.961 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 16 Jan 09:55:40.961 * The server is now ready to accept connections on port 6379
mysql_1  | 2020-01-16 09:55:45+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.29-1debian9 started.
mysql_1  | 2020-01-16 09:55:45+00:00 [Note] [Entrypoint]: Initializing database files
mysql_1  | 2020-01-16T09:55:45.597324Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
mysql_1  | 2020-01-16T09:55:45.635369Z 0 [Warning] InnoDB: Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html
mysql_1  | 2020-01-16T09:55:48.077398Z 0 [Warning] InnoDB: New log files created, LSN=45790
mysql_1  | 2020-01-16T09:55:48.646754Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
mysql_1  | 2020-01-16T09:55:48.952749Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 5f8348e1-3846-11ea-8ab5-0242ac130003.
mysql_1  | 2020-01-16T09:55:49.020134Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
mysql_1  | 2020-01-16T09:55:51.294446Z 0 [Warning] CA certificate ca.pem is self signed.
app_1    | from /var/www/capistrano_sample_app_v1/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap.rb:22:in `setup': The 'disable_trace' method is not allowed with this Ruby version. current: 2.6.5, allowed version: < 2.5.0
mysql_1  | 2020-01-16T09:55:51.879252Z 1 [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
app_1    | => Booting Puma
app_1    | => Rails 5.2.4.1 application starting in development 
app_1    | => Run `rails server -h` for more startup options
app_1    | Puma starting in single mode...
app_1    | * Version 3.12.2 (ruby 2.6.5-p114), codename: Llamas in Pajamas
app_1    | * Min threads: 5, max threads: 5
app_1    | * Environment: development
app_1    | * Listening on tcp://0.0.0.0:8080
app_1    | Use Ctrl-C to stop
mysql_1  | 2020-01-16 09:55:58+00:00 [Note] [Entrypoint]: Database files initialized
mysql_1  | 2020-01-16 09:55:58+00:00 [Note] [Entrypoint]: Starting temporary server
mysql_1  | 2020-01-16 09:55:58+00:00 [Note] [Entrypoint]: Waiting for server startup
mysql_1  | 2020-01-16T09:55:58.626438Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
mysql_1  | 2020-01-16T09:55:58.627939Z 0 [Note] mysqld (mysqld 5.7.29) starting as process 80 ...
mysql_1  | 2020-01-16T09:55:58.631949Z 0 [Warning] InnoDB: Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html
mysql_1  | 2020-01-16T09:55:58.632065Z 0 [Note] InnoDB: PUNCH HOLE support available
mysql_1  | 2020-01-16T09:55:58.632232Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
mysql_1  | 2020-01-16T09:55:58.632267Z 0 [Note] InnoDB: Uses event mutexes
mysql_1  | 2020-01-16T09:55:58.632275Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
mysql_1  | 2020-01-16T09:55:58.632281Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
mysql_1  | 2020-01-16T09:55:58.632286Z 0 [Note] InnoDB: Using Linux native AIO
mysql_1  | 2020-01-16T09:55:58.632901Z 0 [Note] InnoDB: Number of pools: 1
mysql_1  | 2020-01-16T09:55:58.633235Z 0 [Note] InnoDB: Using CPU crc32 instructions
mysql_1  | 2020-01-16T09:55:58.634985Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
mysql_1  | 2020-01-16T09:55:58.644127Z 0 [Note] InnoDB: Completed initialization of buffer pool
mysql_1  | 2020-01-16T09:55:58.646140Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
mysql_1  | 2020-01-16T09:55:58.660112Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
mysql_1  | 2020-01-16T09:55:58.702341Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
mysql_1  | 2020-01-16T09:55:58.702446Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
mysql_1  | 2020-01-16T09:55:58.916889Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
mysql_1  | 2020-01-16T09:55:58.917944Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
mysql_1  | 2020-01-16T09:55:58.917995Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
mysql_1  | 2020-01-16T09:55:58.919329Z 0 [Note] InnoDB: 5.7.29 started; log sequence number 2629932
mysql_1  | 2020-01-16T09:55:58.919668Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
mysql_1  | 2020-01-16T09:55:58.920063Z 0 [Note] Plugin 'FEDERATED' is disabled.
mysql_1  | 2020-01-16T09:55:58.922411Z 0 [Note] InnoDB: Buffer pool(s) load completed at 200116  9:55:58
mysql_1  | 2020-01-16T09:55:58.926524Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them.
mysql_1  | 2020-01-16T09:55:58.926589Z 0 [Note] Skipping generation of SSL certificates as certificate files are present in data directory.
mysql_1  | 2020-01-16T09:55:58.927349Z 0 [Warning] CA certificate ca.pem is self signed.
mysql_1  | 2020-01-16T09:55:58.927419Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory.
mysql_1  | 2020-01-16T09:55:58.929692Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
mysql_1  | 2020-01-16T09:55:58.938200Z 0 [Note] Event Scheduler: Loaded 0 events
mysql_1  | 2020-01-16T09:55:58.938729Z 0 [Note] mysqld: ready for connections.
mysql_1  | Version: '5.7.29'  socket: '/var/run/mysqld/mysqld.sock'  port: 0  MySQL Community Server (GPL)
mysql_1  | 2020-01-16 09:55:59+00:00 [Note] [Entrypoint]: Temporary server started.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
mysql_1  | 
mysql_1  | 2020-01-16 09:56:06+00:00 [Note] [Entrypoint]: Stopping temporary server
mysql_1  | 2020-01-16T09:56:06.599321Z 0 [Note] Giving 0 client threads a chance to die gracefully
mysql_1  | 2020-01-16T09:56:06.599402Z 0 [Note] Shutting down slave threads
mysql_1  | 2020-01-16T09:56:06.599412Z 0 [Note] Forcefully disconnecting 0 remaining clients
mysql_1  | 2020-01-16T09:56:06.599422Z 0 [Note] Event Scheduler: Purging the queue. 0 events
mysql_1  | 2020-01-16T09:56:06.599572Z 0 [Note] Binlog end
mysql_1  | 2020-01-16T09:56:06.600707Z 0 [Note] Shutting down plugin 'ngram'
mysql_1  | 2020-01-16T09:56:06.600763Z 0 [Note] Shutting down plugin 'partition'
mysql_1  | 2020-01-16T09:56:06.600771Z 0 [Note] Shutting down plugin 'BLACKHOLE'
mysql_1  | 2020-01-16T09:56:06.600777Z 0 [Note] Shutting down plugin 'ARCHIVE'
mysql_1  | 2020-01-16T09:56:06.600781Z 0 [Note] Shutting down plugin 'PERFORMANCE_SCHEMA'
mysql_1  | 2020-01-16T09:56:06.600812Z 0 [Note] Shutting down plugin 'MRG_MYISAM'
mysql_1  | 2020-01-16T09:56:06.600817Z 0 [Note] Shutting down plugin 'MyISAM'
mysql_1  | 2020-01-16T09:56:06.600831Z 0 [Note] Shutting down plugin 'INNODB_SYS_VIRTUAL'
mysql_1  | 2020-01-16T09:56:06.600836Z 0 [Note] Shutting down plugin 'INNODB_SYS_DATAFILES'
mysql_1  | 2020-01-16T09:56:06.601155Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLESPACES'
mysql_1  | 2020-01-16T09:56:06.601163Z 0 [Note] Shutting down plugin 'INNODB_SYS_FOREIGN_COLS'
mysql_1  | 2020-01-16T09:56:06.601167Z 0 [Note] Shutting down plugin 'INNODB_SYS_FOREIGN'
mysql_1  | 2020-01-16T09:56:06.601170Z 0 [Note] Shutting down plugin 'INNODB_SYS_FIELDS'
mysql_1  | 2020-01-16T09:56:06.601173Z 0 [Note] Shutting down plugin 'INNODB_SYS_COLUMNS'
mysql_1  | 2020-01-16T09:56:06.601176Z 0 [Note] Shutting down plugin 'INNODB_SYS_INDEXES'
mysql_1  | 2020-01-16T09:56:06.601179Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLESTATS'
mysql_1  | 2020-01-16T09:56:06.601182Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLES'
mysql_1  | 2020-01-16T09:56:06.601186Z 0 [Note] Shutting down plugin 'INNODB_FT_INDEX_TABLE'
mysql_1  | 2020-01-16T09:56:06.601189Z 0 [Note] Shutting down plugin 'INNODB_FT_INDEX_CACHE'
mysql_1  | 2020-01-16T09:56:06.601192Z 0 [Note] Shutting down plugin 'INNODB_FT_CONFIG'
mysql_1  | 2020-01-16T09:56:06.601195Z 0 [Note] Shutting down plugin 'INNODB_FT_BEING_DELETED'
mysql_1  | 2020-01-16T09:56:06.601198Z 0 [Note] Shutting down plugin 'INNODB_FT_DELETED'
mysql_1  | 2020-01-16T09:56:06.601201Z 0 [Note] Shutting down plugin 'INNODB_FT_DEFAULT_STOPWORD'
mysql_1  | 2020-01-16T09:56:06.601204Z 0 [Note] Shutting down plugin 'INNODB_METRICS'
mysql_1  | 2020-01-16T09:56:06.601207Z 0 [Note] Shutting down plugin 'INNODB_TEMP_TABLE_INFO'
mysql_1  | 2020-01-16T09:56:06.601211Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_POOL_STATS'
mysql_1  | 2020-01-16T09:56:06.601214Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_PAGE_LRU'
mysql_1  | 2020-01-16T09:56:06.601217Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_PAGE'
mysql_1  | 2020-01-16T09:56:06.601220Z 0 [Note] Shutting down plugin 'INNODB_CMP_PER_INDEX_RESET'
mysql_1  | 2020-01-16T09:56:06.601223Z 0 [Note] Shutting down plugin 'INNODB_CMP_PER_INDEX'
mysql_1  | 2020-01-16T09:56:06.601226Z 0 [Note] Shutting down plugin 'INNODB_CMPMEM_RESET'
mysql_1  | 2020-01-16T09:56:06.601229Z 0 [Note] Shutting down plugin 'INNODB_CMPMEM'
mysql_1  | 2020-01-16T09:56:06.601232Z 0 [Note] Shutting down plugin 'INNODB_CMP_RESET'
mysql_1  | 2020-01-16T09:56:06.601236Z 0 [Note] Shutting down plugin 'INNODB_CMP'
mysql_1  | 2020-01-16T09:56:06.601239Z 0 [Note] Shutting down plugin 'INNODB_LOCK_WAITS'
mysql_1  | 2020-01-16T09:56:06.601242Z 0 [Note] Shutting down plugin 'INNODB_LOCKS'
mysql_1  | 2020-01-16T09:56:06.601245Z 0 [Note] Shutting down plugin 'INNODB_TRX'
mysql_1  | 2020-01-16T09:56:06.601248Z 0 [Note] Shutting down plugin 'InnoDB'
mysql_1  | 2020-01-16T09:56:06.601457Z 0 [Note] InnoDB: FTS optimize thread exiting.
mysql_1  | 2020-01-16T09:56:06.602096Z 0 [Note] InnoDB: Starting shutdown...
mysql_1  | 2020-01-16T09:56:06.703296Z 0 [Note] InnoDB: Dumping buffer pool(s) to /var/lib/mysql/ib_buffer_pool
mysql_1  | 2020-01-16T09:56:06.703781Z 0 [Note] InnoDB: Buffer pool(s) dump completed at 200116  9:56:06
mysql_1  | 2020-01-16T09:56:08.246243Z 0 [Note] InnoDB: Shutdown completed; log sequence number 12441955
mysql_1  | 2020-01-16T09:56:08.249558Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
mysql_1  | 2020-01-16T09:56:08.249620Z 0 [Note] Shutting down plugin 'MEMORY'
mysql_1  | 2020-01-16T09:56:08.249628Z 0 [Note] Shutting down plugin 'CSV'
mysql_1  | 2020-01-16T09:56:08.249632Z 0 [Note] Shutting down plugin 'sha256_password'
mysql_1  | 2020-01-16T09:56:08.249635Z 0 [Note] Shutting down plugin 'mysql_native_password'
mysql_1  | 2020-01-16T09:56:08.249751Z 0 [Note] Shutting down plugin 'binlog'
mysql_1  | 2020-01-16T09:56:08.253458Z 0 [Note] mysqld: Shutdown complete
mysql_1  | 
mysql_1  | 2020-01-16 09:56:08+00:00 [Note] [Entrypoint]: Temporary server stopped
mysql_1  | 
mysql_1  | 2020-01-16 09:56:08+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
mysql_1  | 
mysql_1  | 2020-01-16T09:56:09.018888Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
mysql_1  | 2020-01-16T09:56:09.020190Z 0 [Note] mysqld (mysqld 5.7.29) starting as process 1 ...
mysql_1  | 2020-01-16T09:56:09.024040Z 0 [Warning] InnoDB: Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html
mysql_1  | 2020-01-16T09:56:09.024328Z 0 [Note] InnoDB: PUNCH HOLE support available
mysql_1  | 2020-01-16T09:56:09.024371Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
mysql_1  | 2020-01-16T09:56:09.024378Z 0 [Note] InnoDB: Uses event mutexes
mysql_1  | 2020-01-16T09:56:09.024382Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
mysql_1  | 2020-01-16T09:56:09.024388Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
mysql_1  | 2020-01-16T09:56:09.024395Z 0 [Note] InnoDB: Using Linux native AIO
mysql_1  | 2020-01-16T09:56:09.024922Z 0 [Note] InnoDB: Number of pools: 1
mysql_1  | 2020-01-16T09:56:09.025108Z 0 [Note] InnoDB: Using CPU crc32 instructions
mysql_1  | 2020-01-16T09:56:09.026850Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
mysql_1  | 2020-01-16T09:56:09.036547Z 0 [Note] InnoDB: Completed initialization of buffer pool
mysql_1  | 2020-01-16T09:56:09.038578Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
mysql_1  | 2020-01-16T09:56:09.061020Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
mysql_1  | 2020-01-16T09:56:10.650530Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
mysql_1  | 2020-01-16T09:56:10.650727Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
mysql_1  | 2020-01-16T09:56:10.920702Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
mysql_1  | 2020-01-16T09:56:10.922096Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
mysql_1  | 2020-01-16T09:56:10.922158Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
mysql_1  | 2020-01-16T09:56:10.922898Z 0 [Note] InnoDB: Waiting for purge to start
mysql_1  | 2020-01-16T09:56:10.973211Z 0 [Note] InnoDB: 5.7.29 started; log sequence number 12441955
mysql_1  | 2020-01-16T09:56:10.973628Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
mysql_1  | 2020-01-16T09:56:10.973931Z 0 [Note] Plugin 'FEDERATED' is disabled.
mysql_1  | 2020-01-16T09:56:10.979959Z 0 [Note] InnoDB: Buffer pool(s) load completed at 200116  9:56:10
mysql_1  | 2020-01-16T09:56:10.981172Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them.
mysql_1  | 2020-01-16T09:56:10.981228Z 0 [Note] Skipping generation of SSL certificates as certificate files are present in data directory.
mysql_1  | 2020-01-16T09:56:10.981958Z 0 [Warning] CA certificate ca.pem is self signed.
mysql_1  | 2020-01-16T09:56:10.982025Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory.
mysql_1  | 2020-01-16T09:56:10.982602Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
mysql_1  | 2020-01-16T09:56:10.982676Z 0 [Note] IPv6 is available.
mysql_1  | 2020-01-16T09:56:10.991740Z 0 [Note]   - '::' resolves to '::';
mysql_1  | 2020-01-16T09:56:10.991902Z 0 [Note] Server socket created on IP: '::'.
mysql_1  | 2020-01-16T09:56:10.994292Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
mysql_1  | 2020-01-16T09:56:11.005402Z 0 [Note] Event Scheduler: Loaded 0 events
mysql_1  | 2020-01-16T09:56:11.005836Z 0 [Note] mysqld: ready for connections.
mysql_1  | Version: '5.7.29'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
4. プロセスの確認
Terminal
$ docker-compose ps
              Name                            Command               State           Ports         
--------------------------------------------------------------------------------------------------
capistrano_sample_app_v1_app_1     /bin/sh -c rm -f /app/tmp/ ...   Up      0.0.0.0:8080->8080/tcp
capistrano_sample_app_v1_mysql_1   docker-entrypoint.sh mysql ...   Up      3306/tcp, 33060/tcp   
capistrano_sample_app_v1_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp      
5.appのコンテナにアクセスできるか確認
Terminal
$ docker exec -it capistrano_sample_app_v1_app_1 /bin/bash 
root@a72845229f9c:/var/www/capistrano_sample_app_v1# 
root@a72845229f9c:/var/www/capistrano_sample_app_v1# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2384   744 pts/0    Ss+  18:55   0:00 /bin/sh -c rm -f /app/tmp/pids/server.pid && bin/rails s -p 8080 -b '0.0.0.0'
root         7  0.2  6.3 1125704 130296 pts/0  Sl+  18:55   0:04 puma 3.12.2 (tcp://0.0.0.0:8080) [capistrano_sample_app_v1]
root        27  1.0  0.1   5748  3400 pts/1    Ss   19:28   0:00 /bin/bash
root        32  0.0  0.1   9388  2992 pts/1    R+   19:28   0:00 ps aux
root@a72845229f9c:/var/www/capistrano_sample_app_v1# ls
Capfile  Dockerfile  Gemfile  Gemfile.lock  README.md  Rakefile  app  bin  config  config.ru  db  docker-compose.yml  lib  log  package.json  spec  storage  tmp  vendor
root@a72845229f9c:/var/www/capistrano_sample_app_v1# bundle exec rails c
from /var/www/capistrano_sample_app_v1/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap.rb:22:in `setup': The 'disable_trace' method is not allowed with this Ruby version. current: 2.6.5, allowed version: < 2.5.0
Loading development environment (Rails 5.2.4.1)
irb(main):001:0> 
irb(main):002:0> Rails.env
=> "development"
irb(main):003:0> 
irb(main):004:0> quit
root@a72845229f9c:/var/www/capistrano_sample_app_v1# 
6.mysqlのコンテナにアクセスできるか確認
Terminal
$ docker exec -it capistrano_sample_app_v1_mysql_1 /bin/bash 
root@38fa1f53821a:/# mysql -udeveloper -p capistrano_sample
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show tables
    -> ;
Empty set (0.00 sec)

ここまでで、開発のためのコンテナの設定は完了しています
尚、コンテナを実行しているホストマシンのワーキングコピーで変更があった場合、
dockerを stop / start することで変更反映できます

7. Webアプリのコンテナをセットアップする
Terminal
$ docker exec -it capistrano_sample_app_v1_app_1 /bin/bash

# bundle exec rails db:migrate RAILS_ENV=development
8.URLアクセス

ローカルホストのRailsにアクセスする

スクリーンショット 2020-01-16 22.08.04.png

ワーキングスペースの開発など

1. bundle install
Terminal
$ bundle _2.1.4_ install --path vendor/bundle
Your Ruby version is 2.3.7, but your Gemfile specified 2.6.5となる場合
  • 上記、bundle installをしないと、systemのruby versionを見るようです
mysql2の原因でエラーが出た方はこちら参考に
Terminal
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib --with-cppflags=-I/usr/local/opt/openssl@1.1/include"


$ bundle _2.1.4_ install --path vendor/bundle
[DEPRECATED] The `--path` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set path 'vendor/bundle'`, and stop using this flag
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/.........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
...途中省略...
Fetching mysql2 0.5.3
Installing mysql2 0.5.3 with native extensions
...途中省略...
Bundle complete! 37 Gemfile dependencies, 148 gems now installed.
Bundled gems are installed into `./vendor/bundle`
2. 機能を追加してみる
Terminal
$ bundle exec rails generate scaffold v1::Event game:string description:string event_date:date join_limit:integer latitude:string longitude:string --skip-assets --skip-helper --skip-stylesheets --skip-view-specs --skip-jbuilder --skip-migration
      invoke  active_record
      create    app/models/v1/high_store.rb
      create    app/models/v1.rb
      invoke    rspec
      create      spec/models/v1/event_spec.rb
      invoke  resource_route
       route    namespace :v1 do
  resources :events
end
      invoke  scaffold_controller
      create    app/controllers/v1/events_controller.rb
      invoke    rspec
      create      spec/controllers/v1/events_controller_spec.rb
      create      spec/routing/v1/events_routing_spec.rb
      invoke      rspec
      create        spec/requests/v1/events_spec.rb

$ rm app/models/v1.rb

リポジトリ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】特定の文字列をリンクにする

運営しているサイトの掲示板において、返信時、冒頭に>>123のような記述が入るようにしているのですが、この部分をその番号のコメントへのリンクにすることができたので、やり方を書き残しておきます。

controller

app/controllers/comments_controller.rb
def index
  @comments = Comment.all
end

hepler

app/helpers/comments_helper.rb
module CommentsHelper
  def generate_link(txt)
    reply_txt = txt.slice(/>>[0-9]+/)
    id = reply_txt.slice(/[0-9]+/)
    link = ''
    link << "<a href='" << "##{id}'>#{reply_txt}</a>"
    content = txt.sub!(/>>[0-9]+/, '')
    [link: link, content: content]
  end
end

テキスト内の>>{数字}を抜き出して、aタグに変えて、他の文章と分離させた状態で値を返す処理をしています。

view

app/views/comments/index.html.erb
<% @comments.each do |i| %>
  <% if i.content.slice(/>>[0-9]+/) %>
    <% reply = generate_link(i.content)[0] %>
    <%= reply[:link].html_safe %><br><%= reply[:content] %>
  <% else %>
    <%= i.content %>
  <% end %>
<% end %>

.html_safeを利用しないと、<a href="hogehoge"等がそのまま表示されてしまいます。

注意点

helper関数を記述するファイルの冒頭に# frozen_string_literal: trueという記述があると、関数で文字列を操作することができずエラーになってしまうので注意です。

参考

文字列の一部を削除する
戻り値が複数ある場合の変数代入

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】turbolinksを無効化する

Chart.jsでグラフの描画に失敗することが多々あり、色々調べたところturbolinksが原因でした。
無効化したので、その方法をまとめます。

Gemを削除

Gemfile
#gem 'turbolinks', '~> 5'
$ bundle update

application.jsを編集

以下のコメントアウトされている記述を削除します。機能に影響する系のコメントです。

app/assets/javascripts/application.js
//= require turbolinks #この行を削除

application.html.erbを編集

以下の2行の'data-turbolinks-track': 'reload'部分を削除します。

app/views/layouts/application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

formを編集

form_withを使って作成したformがある場合、全てのformにlocal: trueオプションをつけます。これがないと、フォームがうまく動作しません。

参考

その辺にいるWebエンジニアの備忘録

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

よく使う、好きなGem

好きなGemをまとめます。

better-errors、binding_of_caller

エラー画面がわかりやすくなって、デバッグが捗ります。

annotate

スキーマ情報を、model内にコメントとして書き出してくれます

letter_opener_web

ローカル環境で送信したメールをブラウザ上で確認できるようになります。

dotenv-rails

環境変数を楽に扱えるようになります

paranoia

論理削除の実装が楽になるgemです

gon

Rubyの変数、配列、ハッシュなどをJavaScriptに簡単に引き渡すことができるようになります。

rails-i18n

エラーメッセージ等を日本語化するために使います

kaminari

ページネーションを楽に実装することができます

carrierwave、mini_magick

画像をリサイズしてアップロードし、DBと紐付けて管理することができるようになります

好きになれなかったGem達

devise

一番有名な認証用Gemです。
カスタマイズがしづらくて、結局あとあと工数が膨らみそうな印象を受けました。使ってない機能がたくさんあったりするのも気持ち悪い感じがするので、私には合わない感じがしました

guard-livereload

HTMLやCSS等を更新した時に、ブラウザをオートリロードするためのGemです。
デフォルトの設定で、SCSSファイル更新時のオートリロードできなかったのと、数年前からアップデートされていない感じがしたので使うのをやめました。
今はbrowser-syncでオートリロードしてます。
Railsでファイル変更時のオートリロードを実現

rails-erd

ER図を自動生成してくれるGemです。
便利ではあったものの、開発が止まっていて、Rails6に対応していなかったので、使わないことにしました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[未解決] Rails on Docker を Heroku へデプロイ時, db:create が通らない.

現在docker-composeを用いてRailsアプリケーションを開発しており,
本番環境へのリリースとしてHerokuへのデプロイを行っている途中でエラーが発生している状態です.

やったこと

こちらのQiita記事herokuのdocsを参照しながら以下のコマンドを実行していきました.
ここまでは何のエラーもなく通っています.
(herokuへログイン済み)

$ heroku container:push web

$ heroku container:release web

$ heroku addons:create cleardb:ignite

$ heroku config
=== myapp Config Vars
CLEARDB_DATABASE_URL: mysql://xxx

$ heroku config:set DATABASE_URL='mysql2://xxx'
Setting DATABASE_URL and restarting ⬢ myapp... done, v21
DATABASE_URL: mysql2://xxx

$ heroku config:set RAILS_ENV='production'
Setting RAILS_ENV and restarting ⬢ myapp... done, v22
RAILS_ENV: production


発生している問題

以上のコマンドに引き続きdb:createを実行した際に以下のエラーが発生しています.

$ heroku run rails db:create
Running rails db:create on ⬢ myapp... up, run.9235 (Free)
rails aborted!
NameError: Cannot load database configuration:
undefined local variable or method `root' for main:Object
(erb):19:in `block in <main>'
(erb):19:in `fetch'
(erb):19:in `<main>'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/application/configuration.rb:172:in `database_configuration'
/usr/local/bundle/gems/activerecord-5.2.4.1/lib/active_record/railtie.rb:39:in `block (3 levels) in <class:Railtie>'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/command.rb:48:in `invoke'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands.rb:18:in `<main>'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in `block in require'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:257:in `load_dependency'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in `require'
/katagami-ant/bin/rails:9:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
/usr/local/bundle/gems/spring-2.1.0/bin/spring:49:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
/katagami-ant/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'


考えうる原因

/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/application/configuration.rb:172:in `database_configuration'

エラーが発生したコードは以上の部分ということだったので, database_configurationについて調べてみると

Loads and returns the entire raw configuration of database from values stored in config/database.yml.

ということで, どうもconfig/database.ymlが怪しいと分かりました.
heroku configで設定した環境変数が読み込まれているかを確認するために,
initializers/の適当なファイルに以下を置いてみましたが問題ないようでした.

initializers/xx.rb
p ENV['DATABASE_URL']
p ENV['RAILS_ENV']
$ heroku run rails db:create
Running rails db:create on ⬢ myapp... up, run.2733 (Free)
"mysql2://xxx"
"production"
rails aborted!
NameError: Cannot load database configuration:
undefined local variable or method `root' for main:Object
...


関連のあるコード

docker-compose.yml
version: "3"
services:
  web:
    build: .
    command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p '3001' -b '0.0.0.0'"
    tty: true
    stdin_open: true
    # environment:
    #   - DATABASE=myapp_development
    #   - DATABASE_USER=root
    #   - DATABASE_PASSWORD=password
    #   - DATABASE_HOST=db
    volumes:
      - .:/katagami-ant
    ports:
      - 3001:3001
    depends_on:
      - db
      - redis

  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      - MYSQL_DATABASE=myapp_development
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - mysql_vol:/var/lib/mysql
    ports:
      - 3306:3306

  redis:
    image: redis
    ports:
      - 6379:6379
    volumes:
      - "./app/redis:/data"

volumes:
  mysql_vol:


config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  # username: <%= ENV.fetch("DATABASE_USER") { root } %>
  # password: <%= ENV.fetch("DATABASE_PASSWORD") { password } %>
  # host: <%= ENV.fetch("DATABASE_HOST") { db } %>
  # database: <%= ENV.fetch("DATABASE") { katagami-ant_development } %>

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>

実現したいこと

heroku run db:createを実行したい.

開発環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.1
BuildVersion:   19B88
$ docker -v
Docker version 19.03.1, build 74b1e89
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b

現状

Qiitaに質問を投稿しています...
https://teratail.com/questions/235499

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[解決済] Rails on Docker を Heroku へデプロイ時, db:create が通らない.

現在docker-composeを用いてRailsアプリケーションを開発しており,
本番環境へのリリースとしてHerokuへのデプロイを行っている途中でエラーが発生している状態です.

やったこと

こちらのQiita記事herokuのdocsを参照しながら以下のコマンドを実行していきました.
ここまでは何のエラーもなく通っています.
(herokuへログイン済み)

$ heroku container:push web

$ heroku container:release web

$ heroku addons:create cleardb:ignite

$ heroku config
=== myapp Config Vars
CLEARDB_DATABASE_URL: mysql://xxx

$ heroku config:set DATABASE_URL='mysql2://xxx'
Setting DATABASE_URL and restarting ⬢ myapp... done, v21
DATABASE_URL: mysql2://xxx

$ heroku config:set RAILS_ENV='production'
Setting RAILS_ENV and restarting ⬢ myapp... done, v22
RAILS_ENV: production


発生している問題

以上のコマンドに引き続きdb:createを実行した際に以下のエラーが発生しています.

$ heroku run rails db:create
Running rails db:create on ⬢ myapp... up, run.9235 (Free)
rails aborted!
NameError: Cannot load database configuration:
undefined local variable or method `root' for main:Object
(erb):19:in `block in <main>'
(erb):19:in `fetch'
(erb):19:in `<main>'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/application/configuration.rb:172:in `database_configuration'
/usr/local/bundle/gems/activerecord-5.2.4.1/lib/active_record/railtie.rb:39:in `block (3 levels) in <class:Railtie>'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/command.rb:48:in `invoke'
/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/commands.rb:18:in `<main>'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in `block in require'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:257:in `load_dependency'
/usr/local/bundle/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in `require'
/katagami-ant/bin/rails:9:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
/usr/local/bundle/gems/spring-2.1.0/bin/spring:49:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
/katagami-ant/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'


考えうる原因

/usr/local/bundle/gems/railties-5.2.4.1/lib/rails/application/configuration.rb:172:in `database_configuration'

エラーが発生したコードは以上の部分ということだったので, database_configurationについて調べてみると

Loads and returns the entire raw configuration of database from values stored in config/database.yml.

ということで, どうもconfig/database.ymlが怪しいと分かりました.
heroku configで設定した環境変数が読み込まれているかを確認するために,
initializers/の適当なファイルに以下を置いてみましたが問題ないようでした.

initializers/xx.rb
p ENV['DATABASE_URL']
p ENV['RAILS_ENV']
$ heroku run rails db:create
Running rails db:create on ⬢ myapp... up, run.2733 (Free)
"mysql2://xxx"
"production"
rails aborted!
NameError: Cannot load database configuration:
undefined local variable or method `root' for main:Object
...


関連のあるコード

docker-compose.yml
version: "3"
services:
  web:
    build: .
    command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p '3001' -b '0.0.0.0'"
    tty: true
    stdin_open: true
    # environment:
    #   - DATABASE=myapp_development
    #   - DATABASE_USER=root
    #   - DATABASE_PASSWORD=password
    #   - DATABASE_HOST=db
    volumes:
      - .:/katagami-ant
    ports:
      - 3001:3001
    depends_on:
      - db
      - redis

  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      - MYSQL_DATABASE=myapp_development
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - mysql_vol:/var/lib/mysql
    ports:
      - 3306:3306

  redis:
    image: redis
    ports:
      - 6379:6379
    volumes:
      - "./app/redis:/data"

volumes:
  mysql_vol:


config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  # username: <%= ENV.fetch("DATABASE_USER") { root } %>
  # password: <%= ENV.fetch("DATABASE_PASSWORD") { password } %>
  # host: <%= ENV.fetch("DATABASE_HOST") { db } %>
  # database: <%= ENV.fetch("DATABASE") { katagami-ant_development } %>

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>

実現したいこと

heroku run db:createを実行したい.

開発環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.1
BuildVersion:   19B88
$ docker -v
Docker version 19.03.1, build 74b1e89
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b

解決

config/database.ymlにおいて,
username: <%= ENV.fetch("DATABASE_USER") { root } のrootを
ちゃんと文字列にしてなかったのが原因でした.

以下のように他の部分もクォーテーションで囲って実行すると上手くいきました.
コメントアウトが効いてないのかな...ちょっと謎いです...

development:
  <<: *default
  # username: <%= ENV.fetch("DATABASE_USER") { 'root' } %>
  # password: <%= ENV.fetch("DATABASE_PASSWORD") { 'password' } %>
  # host: <%= ENV.fetch("DATABASE_HOST") { 'db' } %>
  # database: <%= ENV.fetch("DATABASE") { 'katagami-ant_development' } %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

system_specテストにおいて特定のリンクをクリックする方法

テストにおいて特定のリンクをクリックする

スクリーンショット 2020-01-16 16.14.02.jpeg

前提条件

taskアプリを作成してある。(scaffoldでもOK)
gem 'capybara', '>= 2.15'
gem 'rspec-rails'
インストール済

上記画像の黒丸に囲まれた(詳細を確認する)をクリックする

task_spec.rb
#省略
visit tasks_path
tds = page.all('td')
tds[24].click
#省略

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsでUTF-16のファイルを作成する

経緯

Ruby on RailsでUTF-16のファイルを作成する必要があったので、
その時の処理を備忘録として書き留めて置きたいと思います。

ソース

create_file.rb
/**
 * ファイル作成(ローカルにファイルを作成する)
 * @param xml バイナリデータ
 * @param file_name ファイル名
 * @param upload_time 作成日時
 */
def put_string_file(xml, file_name, upload_time)
    # ディレクトリとファイルの定義
    dir = "#{Rails.root}/storage/#{upload_time}/"
    file = "#{dir}#{file_name}"
    # フォルダがなければ作成
    FileUtils.mkdir_p(dir) unless File.directory?(dir)

    # バイナリデータをファイルに出力
    File.binwrite(file, StringIO.new(xml).read)
    # 作成されたファイルを読み込みUTF-16に変換する
    File.open(file, 'r'){ |f|
      buffer = f.read();
      buffer = buffer.encode("UTF-16", "UTF-8", :invalid => :replace, :undef => :replace, :replace => '*')
      f = File.open(file, 'w:UTF-16:UTF-8')
      f.write(buffer)
    }
  end

まとめ

一発でUTF-16のファイルを作成できないかなと調べてみましたが、見つからず。
一旦UTF-8でファイルを作成し、UTF-16に変換してと手間をかける方法しか浮かばなかったです。
改善点などあれば情報求む。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サーバーが起動しない時の対処法

A server is already running.が出てrails s が起動しない時

#lsof -i

COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby2.5 2722 vagrant   15u  IPv4  23988      0t0  TCP ubuntu-bionic:3000->_gateway:52166 (CLOSE_WAIT)
ruby2.5 2722 vagrant   16u  IPv4  23985      0t0  TCP *:3000 (LISTEN)

この2722が邪魔。なので

#kill -9 2722

killed

これで動かせる。
アプリ/tmp/pids/server.pidのファイルを削除してもいけるらしい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

master以外のブランチからherokuにpushする方法

railsアプリを作って、herokuをデプロイする(masterブランチ以外からデプロイする方法も同時に載せています。)

1 コミット

$ git add .
$ git commit -m "heroku"
$ git push origin ブランチ名

2 herokuにアプリケーションを新規作成する

$ heroku create

3-1 herokuにデプロイする(masterブランチにいる時)

$ git push heroku master

3-2 herokuにデプロイする(master以外のブランチにいる時)

$ git push heroku <現在いるブランチ名>:master

※3-1 or 3-2 どちらかを実行してください

4 herokuにデータベースを作成する

$ heroku run rails db:migrate

5 アプリケーションを開く

$ heroku open

以上で、完成です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Redmine test でmocha/setupがないエラー(cannot load such file -- mocha/setup (LoadError))

環境

Redmineのローカル開発環境
MacOS 10.15.2
Rails 5.2.3

エラー内容

testを実行しようとすると下記のエラーが出る。

cannot load such file -- mocha/setup (LoadError)

原因

.bundle/configを確認してください。

.bundle/config
BUNDLE_WITHOUT: "development:test"

となっている場合、GemfileのtestグループのGemがインストールされません。

解決

.bundle/configを下記のように変更してください。

.bundle/config
BUNDLE_WITHOUT: "development"

再度bundle installを実行してください。

bundle install

エラーが出なければGemfile内のtestグループに記載されている"mocha"がインストールされます。

Gemfile
gem "mocha"

これで、testを実行した時mocha/setupがないというエラーは出ないと思います。

参考

https://qiita.com/mana-bin/items/4e24247dc074ccee3a4f

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

migrate

rails db:migrate

・model
1 rails generate controller StaticPages home help

2 rails generate model User name:string email:string

3 rails generate model Article content:text user:references

4 rails generate model Relationship follower_id:integer followed_id:integer

5 rails g model Like user_id:integer article_id:integer

・add
2 rails generate controller Users new

2 rails generate migration add_index_to_users_email
rails generate migration add_password_digest_to_users password_digest:string
rails g migration add_image_column_to_users
rails g migration add_image_name_to_users
rails generate controller Sessions new

3 rails generate controller Articles

rails generate uploader Picture
rails generate uploader Image
rails generate migration add_picture_to_articles picture:string

5 rails g migration add_likes_count_to_articles likes_count:integer
rails g migration add_article_tag_to_articles

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails g migrate で外部キーを追加する

ポートフォリオ作成中に後から外部キーを追加しよとしたら、コマンドに詰まったので忘れないために記事にしておく。

articleテーブルにuser_idを追加する

rails g migration AddUserRefToArticles user:references

成功したら

rake db:migrate

を実行する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuにデプロイしたら見た目が変になっちゃった問題

以前、Asset Pipeline に関する記事を書きました。Asset Pipeline をご存じない方はそちらを先に読んでいただけると、とっても理解しやすいのではないかと。

Asset Pipeline を理解してみる

ともかく、超初心者の僕は初めて作ったtwitterクローンアプリを公開したくてサーバーにアップしたくなったのです。そしてどうやらHerokuというものが、初心者に優しい無料サーバーということで利用してみました!すると

僕「アプリの見た目変わっとるやないかーい

調べた結果、その理由はAsset Pipeline にある様でした。問題の原因と解決法を書き残しておきます。

前提

僕のスペック

  • プログラミング学習を始めて1ヶ月
  • HTML/CSS/Javascript/Ruby/Railsをprogateで一応学習済
  • Ruby on rails でポートフォリオを作成中

開発環境

  • 端末 : LENOVO ideapad 530S-14ARR
  • OS : Windows 10 Home ver.1809
  • シェル : PowerShell 5.1.17763.771
  • git : 2.24.1.windows.2
  • Ruby : 2.6.4
  • rails : 5.2.4.1

なんで急に変わっちゃったの?

僕「開発中は良きな見た目だったのに、なんで公開した途端変貌してしまったの?」

その理由はAsset Pipelineの設定ミスでした。Asset Pipline はapp/assetにあるディレクトリ内のファイルをまとめてくれる頼れる兄さん。でもこの兄さん、普段は開発中にしか仕事しないのです。だから、公開しても仕事をしてくれるようにお願いする必要があります。

僕「兄さん頼むよ。Herokuにアップした時もその勇姿を見せてくれよ」
兄さん「いいだろう。」
兄さん「では、config/environments/production.rbの設定を以下に変更してね」
兄さん「config/environments/production.rbの31行目くらいにある設定だよ。」

config/environments/production.rb
config.assets.compile = true

そうすると、無事に見た目が整いました。
Asset Pipline はデフォルトでは開発環境でしか動かない設定となっているので、これを本番環境でも動く設定にする必要があるのです。

まとめ

僕「ありがとう!兄さん」

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Asset Pipeline を理解してみる

Railsアプリの開発を行っていく中で、「Asset Pipeline」という言葉を目にするようになった。プログラミング学習歴1ヶ月の僕が「Asset Pipeline」を理解するまでの流れを記録することにした。

前提

僕のスペック

  • プログラミング学習を始めて1ヶ月
  • HTML/CSS/Javascript/Ruby/Railsをprogateで一応学習済
  • Ruby on rails でポートフォリオを作成中

開発環境

  • 端末 : LENOVO ideapad 530S-14ARR
  • OS : Windows 10 Home ver.1809
  • シェル : PowerShell 5.1.17763.771
  • Ruby : 2.6.4
  • rails : 5.2.4.1

Asset Pipelineとは

以下引用です。(引用元:Rails初学者がつまずきやすい「アセットパイプライン」

アセットパイプラインは、Ruby on Railsのアプリケーション内で使用したいJavaScriptやCSS、画像ファイルを「開発作業がしやすいようにファイルを分割してコーディングができるようにしつつ、最終的に一つのファイルに連結・圧縮する」仕組みです。

僕「へー仕組みの事か」
僕「でも、なんで最終的に1つのファイルにする必要があるのかしら?」

1つのファイルに連結・圧縮する理由

そもそもなんで分けているのだっけ?

プログラマーがアプリを開発する際、あるwebページを表示するのに必要なcss、javascript、画像等をが1つのディレクトリにまとめられいると、開発を行う際に、

「どのファイルがどのファイルに対応してたっけ」や
「1つのディレクトリに画像もcssもjavascriptも混ざってるなんて気持ち悪いわ!」

なんて問題が起きるでしょう。だからrails newで作成されたアプリには初めから、app/assetの中にimagesstylesheetjavascriptというディレクトリがあらかじめ用意されとるという訳です。

なんで1つにまとめる必要があるのだっけ?

でもこんなことをすると困る人がいます。それは機械側です。
機械「こんなにディレクトリ分けられても読み込めないんですけど。」
機械「1つにまとめてよ・・・。」

Rails におけるcss,javascript,画像のまとめ役登場

こんな機械側のお悩みを解決するのがAsset Pipelineな訳です。
具体的には以下の流れでassets内のディレクトリに含まれるファイルを1つにまとめるそうで。
(引用元(再掲):Rails初学者がつまずきやすい「アセットパイプライン」
image.png

まとめ

そんなわけで、アプリに反映させたいcss等はassetsにぶち込んでおけば、あとはAsset Pipelineが何とかしてくれるみたい。Asset Pipeline 素敵!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

webpackerを高速化した話

webpackerの高速化をしようと色々試したら、灯台下暗しだったひとのお話。

環境

rails5.2.3
rails/webpacker v4.2.2
capistrano v3.x

あらまし

デプロイがクッッッッッッソ遅い
デプロイ1回につきアセットのビルドに早くても200秒程度かかる。キレそう。
まあ待てないこともないけど結構辛い
とくにjs関係ないfixのデプロイに数分待たされるのはかなりしんどい

1) sourcemapをオフ

webpackのsourcemapを作ってる時間って割と長い。
自分の場合、200秒のデプロイ時間のうち、100秒くらいはsourcemapの作成に取られてた
高速化の手段としては有効だと思うけど、sourcemap消したくなかったので今回はパス
あとwebpackerでこの設定いじるのはなかなかめんどくさいので、webpackerマンは覚悟した方がいい

https://webpack.js.org/plugins/terser-webpack-plugin/

2) SplitChunksPluginでよしなに

webpackの便利機能にSplitChunksPluginっていうのがある。詳しくは知らんけど。
アプリケーションとライブラリでチャンクを分けるとかするといいらしいって先輩が言ってた
しかしwebpackerでこの設定いじるのなかなかめんどくさいんだよなぁ(2回目)、ということでパス
誰か脱webpackerしやすいライブラリをつくってくれ〜〜〜

https://webpack.js.org/plugins/split-chunks-plugin/

3) public_output_pathをsharedにする

最終的に行き着いたのがこれ

deploy.rb
...

# Default value for linked_dirs is []
# public_output_pathに指定しているディレクトリを追加(今回は"public/packs"になってる)
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system", "public/packs"

...

capistranoだと、linked_dirsを設定するとそのディレクトリがsharedになる(=バージョンに関わらず共通のディレクトリになる)のだが、そこにpublic_output_pathを追加していなかった。要はwebpackの結果を毎回0から作り直していてた。(・ω<) てへぺろ☆
この設定をすると正しくキャッシュが効くようになったようで、3分はかかってたビルドが最短30秒くらいで済むようになった

ここからは余談。
いま扱っているプロジェクト、実は脱Sprocketsもできてないのだが、デプロイ時にSprocketsはキャッシュっぽい挙動をしてるのに、webpackerはしていない、もしかしてwebpackerキャッシュしてないのでは?と気づいたことからこの策が浮上した。
ちなみにSprocketsのキャッシュ先はデフォルトのpublic/assets以下なのだが、これをlinked_dirsに入れた覚えはない。じゃあどこで?と調べて見ると、capistrano/railsrequire 'capistrano/rails/assets' するときによしなにしてくれていた。いや、webpackerもよしなにしろよ!!!

あと、今の所副作用はないけど、webpackの挙動全然知らないマンなので、このやり方まずいですよ!って感じだったら教えてください

結論

誰か脱webpackerしやすいライブラリをくれ!!!(懇願

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む