20200110のRubyに関する記事は21件です。

Dockerで環境構築する際、ソースコードの変更が即時反映されない場合の対処法

記事の目的

docker-composeで環境構築する際に起こったRailsのソースコードを修正しても即時反映されない問題に対しての対処法を共有すること。

対処法

1.development.rbを編集

開発環境用の設定ファイルである config/environments/development.rb を編集。
「 ~ 」は元々の記述を省略しているものとする。
この中にconfig.reload_classes_only_on_change = falseという記述を追加する。

development.rb
Rails.application.configure do

~
config.reload_classes_only_on_change = false

end

2.railsコンテナを再起動

設定を記載しただけでは反映されないので、最後にRailsを再起動する。

ターミナル上で、

$ docker-compose restart 

と入力する。

以上でソースコードの変更が即時反映される。

終わりに

Dockerで環境構築をした際に、もう設定しておくと良い。

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

はじめてAWSでデプロイする方法③(AWSセキュリティグループの設定)

これまでの記事

はじめてAWSでデプロイする方法①(インスタンスの作成)
はじめてAWSでデプロイする方法②(Elastic IPの作成と紐付け)

前回までの流れ

作成したEC2インスタンスとElastic IPを紐付けして、パブリックIPを固定にした。

今回の流れ

現状

現時点において、HTTP(www.サイトURL)で接続することはできない。
スクリーンショット 2020-01-10 16.13.43.png
(ターミナルでEC2とSSH接続は可能。)

つまり、一般ユーザーは閲覧することはできない状態である。
なので、今回はHTTP接続(www.)を解放して、URLでサイトを閲覧できるようにしていく。

ポート(入り口)の解放

このHTTP接続(www.)の入り口となるのが、「ポート」(扉)と呼ばれます。IPアドレスが住所「家」であれば、ポートは外に出る・外から入る「扉(ドア)」に該当します。

ポートの設定をするためには、「セキュリティグループ」という設定を変更していきましょう

本題、セキュリティグループの設定

セキュリティグループとは、AWSのファイアウォール機能の一つ。
プロトコル、ポート範囲、送信元/送信先IPアドレスによるパケットフィルターが可能。
インスタンス単位に適用することができる。

手順

  1. AWSのEC2ダッシュボードを開く Image from Gyazo
  2. 『実行中のインスタンス』をクリック Image from Gyazo
  3. インスタンスを選択
    スクリーンショット 2020-01-10 16.34.14.png

  4. セキュリティグループの『launch-wizard-3』をクリック

スクリーンショット 2020-01-10 16.37.48.png

補足: インバウンドルール(この後追加します)
そのセキュリティグループに関連付けられたインスタンスにアクセスできるトラフィックを規制する。『インバウンドルールの表示』をクリックすると下記が表示される。
スクリーンショット 2020-01-10 16.36.31.png

補足: アウトバウンドルール(この後追加します)
そのセキュリティグループに関連付けられたインスタンスからどの送信先にトラフィックを送信できるか(トラフィックの送信先と送信先ポート)を制御するルール
『アウトバウンドルールの表示』をクリックすると下記が表示される。
スクリーンショット 2020-01-10 16.36.49.png

(ここから、セキュリティグループの『launch-wizard-3』をクリック後に続く)
5. 下記の画面が表示される
68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3435353430332f37323334663664362d323935342d626334662d643634662d3466633236353061303066312e706e67 (1).png

6.『 インバウンド 』を選択
スクリーンショット 2020-01-10 20.49.20.png
7. 『 編集 』をクリック
スクリーンショット 2020-01-10 20.57.06.png
8. 左下の『ルールの追加』をクリック
Image from Gyazo
9. タイプ:『 HTTP 』を選択
スクリーンショット 2020-01-10 21.03.27.png
10. 画面左下の『 保存 』をクリック
スクリーンショット 2020-01-10 21.08.22.png

スクリーンショット 2020-01-10 21.07.29.png
11. 完了
これでIPアドレス、WWW.やドメインでのWEB閲覧が可能となります。

次はEC2にSSHログインしていきましょう!

ここまで、お疲れ様でした。
なかなか慣れない作業で疲れたのではないでしょうか?

セキュリティグループについては、下記記載のAWSのセキュリティグループリファレンスを参照してみるといいかもしれません。

次回は自身で作成したWEBアプリとEC2サーバーを紐づけていくために、SSHログインしましょう

次回の記事はこちら!
はじめてAWSでデプロイする方法④(EC2にSSHログイン)

参考

【AWS】セキュリティグループを設定してみた
AWS公式-セキュリティグループのルールのリファレンス

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

bundle installするときに "can't find gem bundler (>= 0.a) with executable bundler (Gem::GemNotFoundException)" とErrorが出る

問題が起きたらググれって偉い人が言ってた

対象のディレクトリ下でbundle installするときに起った現象のメモ
※初学者なので細かめに記載

git cloneしたアプリのgemを入れようとしたら以下のエラーが出た。

console
Traceback (most recent call last):
    2: from /Users/mac/.rbenv/versions/2.5.3/bin/bundler:23:in `<main>'
    1: from /Users/mac/.rbenv/versions/2.5.3/lib/ruby/2.5.0/rubygems.rb:308:in `activate_bin_path'
/Users/mac/.rbenv/versions/2.5.3/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundler (Gem::GemNotFoundException)

結局原因ってなんなの?

どうやらbundlerとGemfile.lockのversionが異なっていたので、
『bundlerのgemが見つからないよ!!!!!』って怒られていたらしい。
version違うだけで見つからないのは、当たり前とはいえ
ぶち当たるとちょっとテンション落ちる。
ドジっ子と思えばそうでもないかもしれない。

どうやって解決したの?

方法は2つ
・bundlerのダウングレードをする
・Gemfile.lockにある 'BUNDLED WITH' をbunderのversionに対応させる

bunderのダウングレードはいっぱい記事があるので、
検索してみてください。

そもそものbundlerのversionチェック

ルートディレクトリで以下のコマンドを叩く

bundlercheck
$ bundle -v
Gemfile.lockにある 'BUNDLED WITH' をbunderのversionに対応させるの方法
bundler
$ cd ~/[対象のディレクトリ]
bundler
$ vim Gemfile.lock

ファイルの中身が見れるようになるので、
G(Shift+g)で最終行へ
x.x.xを対応のversionに書き換えます。

Gemfile.lock
BUNDLED WITH
   x.x.x

書き換え方
i → インサートモードへ(書き換えができるようになる)
esc → インサートモードの終了
:wq!を入力 → 保存して強制終了

これでbundle -v したり bundle install して、
問題なければヨシッ!

まとめ

いろんな記事を読んで模索した結果なので、これが最善の解説策かはわかりません。
なのでこれだけでなくいろんな記事を読んで、
ここは一つの参考にしていただければと思います。

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

Railsでカンマ区切り+小数点以下表示で数値を出力する方法

目的

整数部をカンマ区切りで表示し、小数点以下を表示したい

コード

number_with_precision(123456789, precision: 2, delimiter: ',')
#=> "123,456,789.00"

参考リンク

ruby-on-rails — 大きな数字にカンマを追加するためのRailsトリックはありますか?
ActionView::Helpers::NumberHelper

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

はじめてAWSでデプロイする方法②(Elastic IPの作成と紐付け)

前回の記事

はじめてAWSでデプロイする方法①(インスタンスの作成)の続きになります。
インスタンスの作成などを知りたい場合は、この記事を参照してください。

今回実施していくこと

作成したEC2インスタンスには、作成時にIPアドレスが""自動""で割り振られています。
これをパブリックIP(一般公開用のID)と言います。
しかし、""サーバーを再起動させるたびにこのパブリックIPが変わってしまうという欠点""を持っています。

そのため、パブリックIDを固定して、いちいち更新しないようにします。
この固定化したパブリックIDを『 Elastic IP 』と呼びます。

今回はその欠点を改善するために、『 EC2インスンタンスとElastic IP紐付け 』をしていきましょう。

Elastic IPの作成

EC2インスタンスのパブリックIPアドレスをElastic IPに固定する。
Elastic IPとは、AWSから割り振られた固定したパブリックIPアドレス。
このパブリックIPアドレスをEC2インスタンスに紐付けることで、インスタンスの起動、停止に関わらず常に同じIPアドレスで通信をすることが可能になります

手順

  1. AWSのサイドナビにある、『Elastic IP』をクリック。こちらからでも進めます
    Image from Gyazo

  2. 『 Elastic IP アドレスの割り当て 』をクリック
    スクリーンショット 2020-01-10 15.14.40.png

  3. 画面右下の『 割り当て 』をクリック
    スクリーンショット 2020-01-10 15.13.53.png

  4. Elastic IPの作成完了(緑の帯に作成されたElastic IPアドレスが記載されています。)
    スクリーンショット 2020-01-10 15.18.09.png

Elastic IPアドレスは、パブリック IPv4 アドレスの項目にも記載されています(公開するわけにはいかないので伏せています)
スクリーンショット 2020-01-10 15.22.59.png

Elastic IPアドレスとEC2インスタンスと紐付け

ここからEC2インスタンスとElastic IPアドレスを紐付けします。
紐付けが完了すれば、EC2インスタンスのパブリックIPは、Elastic IPアドレスで固定されます

手順

  1. Elastic IPアドレスを選択✅
  2. アクション 『Elastic IPアドレスの関連付け』をクリック
    スクリーンショット 2020-01-10 15.29.25.png

  3. 作成したEC2インスタンスを選択
    スクリーンショット 2020-01-10 15.33.22.png
    補足:上の画像のようにインスタンスを選択すると、その下にあるプライベートIPアドレスが自動で選択されます。なのでプライベートIPアドレスは空白で大丈夫です

4.画面右下の『関連付ける』をクリック
スクリーンショット 2020-01-10 15.35.50.png

5.紐付け完了
スクリーンショット 2020-01-10 15.38.46.png

無事に関連づけられたインスタンスに『i- (EC2インスタンスID)』が表示されています

次は AWS セキュリティグループの設定

みなさん、ここまでお疲れ様です。
慣れていないとここまででも大変かと思います。

立ち上げたばかりのEC2インスタンスはSSHでアクセスすることはできますが、HTTPなどの他の接続は一切つながらないようになっています。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります

次回はポート解放の操作をお伝えしていきたいと思います。

長くなってきたので、次の記事で案内したいと思います。
はじめてAWSでデプロイする方法③(AWSセキュリティグループの設定)

いいね!とフォローをして、有料級記事を見逃すな

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

【Rails】has_secure_passwordメソッド

has_secure_passwordメソッドについてのメモです。

準備

usersテーブルにpassword_digestカラムを追加しておく。

bcryptをインストールする。

Gemfile
gem 'bcrypt'
ターミナル
$ bundle install

モデルにhas_secure_passwordを記載する。

app/models/user.rb
class User < ApplicationRecord
  has_secure_password
end

機能

  • 暗号化されたパスワードがpassword_digestカラムに保存される。
  • 仮想属性password_confirmationを使用して、入力ミスを減らすためにパスワードの確認入力をさせることができる。
  • authenticateメソッドを使用して、メールアドレスとパスワードに基いてユーザー認証を行うことができる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsアプリケーションのメモリが膨れ上がる問題

次のグラフは、Herokuで運用している、とあるRailsアプリケーションのMemory Usageです。1日1回再起動がかかったあと、スワップが発生するまでメモリ使用量が増え続けます。特に大きなデータをメモリ上に置き続けているわけではありません。

memory-2.png

Passengerの作者Hongli Lai氏が、Rubyのメモリが膨れ上がる問題について研究して記事を書いています(2019年3月)。

日本語での概略は、次の記事の真ん中あたりで読めます。

Hongli Lai氏が見つけたのは、Rubyはメモリを正しく解放しているが、Cのライブラリ(glibc)のmalloc周りがなかなかメモリを回収してくれない、ということです。メモリ使用量よりパフォーマンスを優先しているせい、との見立てです。

メモリ使用量が膨れ上がるのを防ぐ方法は、3つあります。1と2は以前から知られた方法で、3はHongli Lai氏が発見した方法です。Hongli Lai氏の説が正しければ、3が本質的な解決方法ということになります。

  1. mallocの代わりにjemallocを使ってRubyをコンパイルする。
  2. 環境変数 MALLOC_ARENA_MAX=2 を指定する。
  3. ガベージコレクションの後でmalloc_trimを呼ぶ。

Hongli Lai氏は、この件について一緒に研究してくれるよう呼びかけています。

RubyのBug trackerでも報告されていますが、話は進んでいないもよう。

Rubyに上記の3のパッチを当てるプロジェクトが公開されています。残念ながらHeroku用は開発が進んでいないようです。

Herokuでは、上記の2の環境変数MALLOC_ARENA_MAX=2はデフォルトになりました。ただし、2019年9月24日より前に作られたアプリケーションでは自分で設定する必要があります。

MALLOC_ARENA_MAXを指定すると、レスポンスタイムが若干増えるという実験結果があります。

以上です。私自身は上記1-3のどれも実際には試していません、すいません。?‍♂️

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

はじめてAWSでデプロイする方法①(インスタンスの作成)

AWSアカウントのリージョン設定をしよう

リージョンとは、AWSの物理的なサーバの場所を指定するものです。リージョンは世界各地に10箇所以上存在し、そのうちの一つは東京にあります。
リージョンを東京に設定していきましょう

手順

  1.  コンソールにアクセス 

  2. 画面右上にある『 国 』を『アジアパシフィック(東京)を選択』
    スクリーンショット 2020-01-10 13.48.30.png

EC2インスタンスを作成

「サーバーを生成する」といっても、AWSが全てのサーバを物理的に用意しているわけではなく、実際には「仮想マシン」と呼ばれるソフトウェアを利用しています。
この「仮想マシン」のことをAWSでは「EC2インスタンス」と呼んでいます。

手順

  1. AWSにアクセス

  2. EC2を選択する
    Image from Gyazo

  3. 画面右上にある、『New EC2 Experience』をオン
    ※アンケートは『 キャンセル 』 しましょう。
    Image from Gyazo

  4. 『実行中のインスタンス』をクリック
    スクリーンショット 2020-01-10 14.14.20.png

  5. インスタンスの画面が開かれたら、画面右上の 『インスタンスの作成』 をクリック
    スクリーンショット 2020-01-10 14.17.36.png

  6. 「 Amazon Linux2 AMI 」ではなく、「 Amazon Linux AMI 」を選択してください。
    (上から2番目にあります)
    Image from Gyazo

  7. 無料枠で利用できる「t2.micro」を選択し、画面右下の 『確認と作成』 をクリック
    スクリーンショット 2020-01-10 14.25.06.png
    ( EC2インスタンスのタイプを選択します。EC2ではさまざまなインスタンスタイプが用意されており、CPUやメモリなどのスペックを柔軟に指定することができます。)

  8. 画面右下の『起動』をクリック
    スクリーンショット 2020-01-10 14.28.11.png

  9. 『新しいキーペアの作成』を選択
    Image from Gyazo

  10. キーペア名を入力(空白NG)

  11. キーペアのダウンロード(ファイル名.pem)

スクリーンショット 2020-01-10 14.36.47.png
?注意:こちらはインスタンスにSSHでログインする際に必要となる「秘密鍵」です。これがないとEC2インスタンスにログインできないので、必ずダウンロードしてパソコンに保存しておきましょう。また、間違って他人に渡さないよう気をつけてください。
ダウンロードしたpemキー(ファイル名.pem)のsshフォルダに移行する

$ cd ~ 
#ターミナルをスタート地点に戻す

$ mkdir ~/.ssh  
#.sshというディレクトリを作成
# エラー『 mkdir: /Users/owner/.ssh: File exists 』と表示の場合、すでに存在します


$ mv Downloads/ファイル名.pem .ssh/
# mvコマンドで、移動させたい対象(ファイル名.pem) → .sshディレクトリに移動します。

$ cd .ssh/

$ ls
# pemファイルが存在するか確認します

12.画面右下の『インスタンスの作成』をクリック
13. 作成完了(反映に時間がかかる場合があります)
スクリーンショット 2020-01-10 14.39.41.png
14.次のインスタンスの作成がされました: 『 i- 』のインスタンスIDをクリック

スクリーンショット 2020-01-10 14.44.47.png
15. 作成したインスタンスがrunningと表示されて、稼働している
スクリーンショット 2020-01-10 14.47.05.png

完了

次は『 Elastic IPの作成と紐付け 』をしよう

ここまで、お疲れ様です。
初めてだとかなり、疲れたと思います。

先ほど作成したEC2インスタンスには、作成時にIPアドレスが自動で割り振られています。これをパブリックIPと言います。しかし、サーバーを再起動させるたびにこのパブリックIPが変わってしまうという欠点を持っています。

次回はその欠点を改善するために、『 Elastic IPの作成と紐付け 』をしていきましょう。

長くなったので、次の記事で続きを記載します
はじめてAWSでデプロイする方法②(Elastic IPの作成と紐付け)

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

rails usersテーブルの値をpasswordなしで更新する

はじめに

Userテーブルのカラムをpasswordなしで更新しようと思ったときに、更新ができずに手間取ってしまったのでその備忘録として記載する。

概要

usersテーブルにprofileというカラムを持たせていたのだが、ユーザー登録後にユーザーページからユーザー情報を更新したい。

ぶつかった課題

controllerで以下のように定義して実行した際にRollbackが起こり、値が更新されなかった。

mypage_controller.rb
   class MypageController < ApplicationController
    # 途中略
    def update

      user=User.find(current_user.id)

      #パスワードなしでのプロフィールの変更    
      user.update_without_password(nickname:params[:mypage][:nickname],profile: params[:mypage][:profile])

      redirect_to root_path,notice: 'プロフィールが変更されました'
    end
    # 途中略
   end

  • エラー内容
[2] pry(#<MypageController>)> user.update_without_password(nickname:params[:mypage][:nickname],profile: params[:mypage][:profile])
   (0.3ms)  BEGIN
   (pry):2
  User Exists (3.4ms)  SELECT  1 AS one FROM `users` WHERE `users`.`email` = BINARY 'ytest@gmail.com' AND `users`.`id` != 21 LIMIT 1
  ↳ (pry):2
   (0.2ms)  ROLLBACK
  ↳ (pry):2
=> false
[3] pry(#<MypageController>)> user.errors
=> #<ActiveModel::Errors:0x00007f8b3304a270
 @base=
  #<User id: 21, email: "ytest@gmail.com", last_name: "test", first_name: "test", last_name_kana: "test", first_name_kana: "test", nickname: "test", profile_image: nil, birthday: "1990-12-04", telephone: "12345678", created_at: "2020-01-10 04:36:29", updated_at: "2020-01-10 04:36:29", provider: nil, uid: nil, profile: "test">,
 @details={:password=>[{:error=>:too_short, :count=>6}, {:error=>:blank}], :password_confirmation=>[{:error=>:blank}]},
 @messages={:password=>["は6文字以上で入力してください", "を入力してください"], :password_confirmation=>["を入力してください"]}>

解決策

modelファイルのバリデーションいじった。

詳細は以下

  • 変更前
user.rb
   class User < ApplicationRecord
    # 途中略
     validates :password, length: { minimum: 6 }
     validates :password_confirmation, presence: true
     validates :password, presence: true, unless: :uid?
   end
  • 変更後

passwordのバリデーションに対して、on create を追加することで、 userの新規登録するときにのみバリデーションによる入力チェックがかかるように変更した。コード内容は以下

user.rb
   class User < ApplicationRecord
    # 途中略
     # create のみバリーデーションをかける
     validates :password, length: { minimum: 6 }, on: :create
     validates :password_confirmation, presence: true, on: :create
     validates :password, presence: true, unless: :uid?, on: :create
   end

とりあえずバリデーションを状況によって、かけたい場合には、オプションとしてon< xxx >を指定すればよいらしい。
ちなみに参考資料はこちら

もっと勉強しないとなぁ〜

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

Railsで開発した個人アプリにDockerを導入する手順と最低限の知識

Railsで開発した個人アプリに、後からDockerを導入しました。
その時知識不足なせいでハマってしまった場面があったので、自分の中で整理してアウトプットすることを目的にこの記事を書き残します。

ちなみに、以下の記事を主に参考にさせていただきました。
DockerをMacにインストールする
Docker + Rails + Puma + Nginx + MySQL

RailsアプリにDockerを導入する手順+事前知識

まずは事前知識として、これは知っておいたほうがいいというものを簡単に書いていきます。

事前知識 - Docker関係

Docker(ドッカー)

※1.軽量な仮想化環境を実現するためのツール。

OS やアプリケーションを設定したものを丸ごと実行イメージとして保存できるので、Docker が導入されている別のマシンにそのまま持って行くことができる。

実行環境をテキストファイルとして共有できるのでとても便利。

※1.仮想化環境とは、コンピュータ上にソフトウェアによって仮想的に構築されたコンピュータ(仮想マシン)が備える仕様や機能の総体のこと。

Dockerイメージ

Dockerイメージは、コンテナを起動させるためのベースとなるもの(オブジェクト指向でいうと「クラス」にあたる)

テキストファイル(Dockerfile)からビルドされる。(後に記述)

DockerHub(Docker向けのコンテナ共有サービス)では、既に多くのイメージが公開されている。

Dockerコンテナ

Dockerのコンテナは、 Dockerイメージを元に作成される仮想環境の実行部分(オブジェクト指向でいうと「インスタンス」にあたる)

原則1コンテナ1アプリ。

Dockerfile(ドッカーファイル)

指定したベースのDockerイメージに加える変更を記述するファイル。

Dockerfileを使うことでオリジナルのDockerイメージを作成することができる。

docker-compose(ドッカーコンポーズ)

複数のコンテナから構成されるアプリケーションで、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツール。

docker-composeを使用する際は「docker-compose.yml」が必要になる。

事前知識 - サーバ関係

ミドルウェア

OSとアプリケーションの間に入り、中間的な処理を行うソフトウェアのこと。

ー 例 ー

  • Webサーバ
    • Apache、NginXなど
  • APサーバ
    • Puma
    • Unicornなど
  • DBサーバ
    • MySQL
    • PostgreSQLなど

Nginx(エンジンエックス)

webサーバの一つ。

Apacheよりも処理能力が高い。

puma(プーマ)

※1.Rackという機能を提供するためのアプリケーションサーバ。

webサーバの1つでもある。

※1.RackとはWeb サーバと Rubyやフレームワークをつなぐ最小のインタフェースを提供するもの。

Docker導入手順

① Docker for Macを公式サイトからインストール、そして起動

公式サイトで会員登録を済ませた後、Docker for Macをダウンロードしインストール。

インストールが終わったら、Dockerを起動しておく。
(MACの画面上部にDockerのマークが出れば起動できてる証拠)

②作成済みのアプリケーションフォルダの直下に「Dockerfile」、「docker-compose.yml」ファイルを新しく作成する。

フォルダ構成

  • 既存のRailsアプリフォルダ
    • app
    • bin
    • config
    • db
    • ・・・
    • Dockerfile
    • docker-compose.yml

③Dockerfileに記述する(アプリケーションフォルダ直下)

Dockerfile
FROM ruby:2.5.1

RUN apt-get update && \
    apt-get install -y mysql-client nodejs vim --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir /myproject

WORKDIR /myproject

ADD Gemfile /myproject/Gemfile
ADD Gemfile.lock /myproject/Gemfile.lock

RUN gem install bundler
RUN bundle install

ADD . /myproject

RUN mkdir -p tmp/sockets

④docker-compose.ymlに記述する(アプリケーションフォルダ直下)

docker-compose.yml
version: '2'
services:
  db:
    image: mysql:5.6
    environment:
      - ./environments/db.env
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "4306:3306"

  app:
    build: .
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/myproject
      - public-data:/myproject/public
      - tmp-data:/myproject/tmp
      - log-data:/myproject/log

  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/myproject/public
      - tmp-data:/myproject/tmp
    ports:
      - 80:80
volumes:
  mysql-data:
  public-data:
  tmp-data:
  log-data:

⑤アプリケーションフォルダ直下に「environments」フォルダを作成、さらにenvironmentsフォルダ直下に「db.env」ファイルを作成する。

  • 既存のRailsアプリフォルダ
    • app
    • bin
    • config
    • db
    • environments
      • db.env
    • ・・・
    • Dockerfile
    • docker-compose.yml

⑥db.envを編集

environments/db.env
MYSQL_ROOT_PASSWORD=password
MYSQL_USER=user
MYSQL_PASSWORD=password

⑦database.ymlを編集

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'root' } %>
  host: db

⑧アプリケーションフォルダ直下に「containers」フォルダを作成、さらにcontainersフォルダ直下に「nginx」フォルダを作成する。

フォルダ構成

  • 既存のRailsアプリフォルダ
    • app
    • bin
    • config
    • containers
      • nginx
    • db
    • environments
      • db.env
    • ・・・
    • Dockerfile
    • docker-compose.yml

⑨作成したnginxフォルダ直下に「Dockerfile」、「nginx.conf」ファイルを作成する。

  • 既存のRailsアプリフォルダ
    • app
    • bin
    • config
    • containers
      • nginx
        • Dockerfile
        • nginx.conf
    • db
    • environments
      • db.env
    • ・・・
    • Dockerfile
    • docker-compose.yml

⑩Dockerfileに記述する(containers/nginxフォルダ直下)

containers/nginx/Dockerfile
FROM nginx:1.15.8

RUN rm -f /etc/nginx/conf.d/*

ADD nginx.conf /etc/nginx/conf.d/myproject.conf

CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

⑪nginx.confに記述する(containers/nginxフォルダ直下)

containers/nginx/nginx.conf
upstream myproject {
  server unix:///myproject/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name 13.112.60.229;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  root /myproject/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @myproject;
  keepalive_timeout 5;

  location @myproject {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://myproject;
  }
}

⑫puma.rbを編集

puma.rb
app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

⑬ターミナルでコマンドを実行

ファイルの準備が整ったら、最後にターミナル上でコマンドを実行。
(railsアプリケーションフォルダ内で実行する)

イメージを構築する

ターミナル
$ docker-compose build

railsのコンテナを作成し、データベースの作成処理を行う

ターミナル
$ docker-compose run --rm app rake db:create db:migrate

全てのコンテナを構築・起動する

ターミナル
$ docker-compose up

上記の流れが終わったあとlocalhostにアクセスすると、しっかり確認することができました。

ちなみに今回書きまとめたものは、DBもDockerで管理することになりますが、DBはローカルのものを参照したいという場合、以下の記事が参考になるかと思います。
既存のRailsアプリをDocker化し、ローカルのDBに接続する方法

(おまけ)

Dockerfileに記述できるコマンド一覧

コマンド 意味
FROM ベースとなるイメージ
RUN docker build 時に実行するコマンド
CMD docker run 時に実行するコマンド
ENTRYPOINT docker run 時に実行するコマンド
MAINTAINER 作者情報
LABEL ラベル情報(メタデータ)
EXPOSE 公開ポート番号
ENV 環境変数
ARG 一時変数
COPY ホストからコンテナへのファイルコピー
ADD ファイル/ディレクトリの追加
VOLUME ボリュームのマウント
USER 実行ユーザ
SHELL シェル指定
WORKDIR ワークディレクトリ
ONBUILD ビルド時に実行するコマンド
STOPSIGNAL コンテナ終了時に送信されるシグナル
HEALTHCHECK ヘルスチェック

ターミナル上で実行できるdocker-composeコマンド一覧

コマンド 意味
build サービスの構築または再構築
config compose ファイルの確認と表示
create サービスの作成
down コンテナ・ネットワーク・イメージ・ボリュームの停止と削除
events コンテナからリアルタイムにイベントを受信
help コマンド上でヘルプを表示
kill コンテナを kill (強制停止)
logs コンテナの出力を表示
pause サービスを一時停止
port ポートに割り当てる公開用ポートを表示
ps コンテナ一覧
pull サービス用イメージの取得
restart サービスの再起動
rm 停止中のコンテナを削除
run 1度だけコマンドを実行
scale サービス用コンテナの数を指定ド
start サービスの開始
stop サービスの停止
up コンテナの作成と開始
version Docker Compose のバージョン情報を表示
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bundle install時に"[DEPRECATED] The `--path` flag is deprecated"という警告が発生した場合の対応手順

はじめに

Bundler 2.1ではBundler 3で使えなくなる機能に対して警告が表示されるようになりました。

参考:【翻訳】Bundler 3アップグレードガイド - Qiita

この関係でBundler 2.1ではbundle install--pathオプションを付けると以下のような警告が発生します。

$ bundle 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

この記事ではこの警告に対する対応手順を説明します。

なお、「今日初めてBundlerを使った」というRuby初心者さんは、必ずこの記事を最後まで読んでください!(大事な話が書いてあります)

対応手順

すでにbundle installを実行した場合

警告は出るものの、bundle install実行後も--path vendor/bundleのオプションは記憶されます。
ですので、それ以上の操作は必要ありません。

bundle installをまだ実行していない場合

bundle installをまだ実行していない場合は、bundle installを実行する前にbundle configコマンドで明示的にpathを設定してください。
それから--pathオプションなしでbundle installを実行すると警告は発生しません。

なお、pathの設定方法はglobalとlocalの2種類があります。
従来のbundle install --path vendor/bundleと同じ動きになるのはlocalの方です。

# マシン全体でbundle install実行時のインストール先を
# vendor/bundleに設定する場合(global)
bundle config set path 'vendor/bundle'

# そのプロジェクト内でのみ、bundle install実行時の
# インストール先をvendor/bundleに設定する場合(local)
bundle config set --local path 'vendor/bundle'

# --pathオプションなしでインストールを実行する
bundle install

最後に:でもちょっと待って!!本当にpathの指定は必要?

もしあなたが今までBundlerを使ったことがなく、「ネットで見つけたBundlerの紹介記事を見ながらbundle installをしようとしたら警告が出たので、警告メッセージでググってこのページにやってきた」という人であれば、きっと--path vendor/bundleを付ける必要はありません。

--path vendor/bundleのオプションを付けることを推奨している多くのWeb記事は、その必要性を十分に理解していないものが多いです。

pathオプションは特殊な条件下でしか必要になりません。
ですので、「今日初めてBundlerを使います」というような初心者さんは、 pathを指定せずにシンプルにbundle installを実行してください。

(すでにbundle install --path vendor/bundleを実行した人は、次回からpathオプションなしでbundle installしてください)

この件に関する詳しい話は以下の記事にまとめているので、こちらも読んでもらえると幸いです。

bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう - Qiita

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

既存のRailsアプリをDocker上で環境構築する方法+sequel proによるDBコンテナ可視化

はじめに

新規アプリをDocker環境で開発するやり方はたくさんあるけど、既存アプリをDocker環境で構築するやり方は全然見当たらず、わりと苦労しました。
振り返ってみると新規アプリでの構築の仕方とあまり変わらないはずなのですが、色々エラー出て苦労したのでまとめておきます。

個々のコマンドの意味もできるだけ記載しました。
単なる環境構築だけでなく、DBコンテナのsequel proによる可視化やAPPコンテナでのbinding.pryの仕方、bundle install後にbuildし直さなくてもよい設定にする方法などもまとめました。

同じく既存のRailsアプリをDocker上で構築したい人の参考になれば幸いです。

内容について間違っていたら教えていただけると嬉しいです。

開発環境

  • Ruby: 2.5.1
  • Rails: 5.2.4
  • MySQL: 5.6
  • MacOS

前提

  • Docker for Macはインストール済み
  • Dockerについての基礎知識
  • 今回は開発環境のみ

対象読者

作成した既存のアプリをDocker上で構築したい人

目次

  • コンテナ起動までの大まかな流れ
  • 実際の作業
  • 番外編:sequel proによるDBコンテナの可視化
  • 開発する上でのDockerコマンド
  • おまけ
    • railsコンテナ上でbinding.pryをする方法
    • railsコンテナ上でbundle installした時に、変更内容をコンテナ上に反映させる方法

コンテナ起動までの大まかな流れ

DockerfileにてRubyのベースイメージをもとにイメージを作成する

作成したイメージをもとにdocker-compose.ymlでappコンテナを作成すると同時に、DBのコンテナのイメージを作成し、これらのコンテナを連携させる

database.ymlを修正してappコンテナからdbコンテナへ接続できるように設定する

実際の作業

  1. Dockerfileとdocker-compose.ymlの作成
  2. Dockerfileの記載
  3. docker-compose.ymlの記載
  4. database.ymlの変更

1. Dockerfileとdocker-compose.ymlの作成

まず、開発しているアプリで、Dockerfileとdocker-compose.ymlを以下のように作成します。

アプリ名
  |- app
  |- bin
  |- config
      #略
  |- vendor
  - .gitignore
  - config.rb
  - Dockerfile           #追加
  - docker-compose.yml  #追加
  - Gemfile
  - Gemfile.lock
      #略

2. Dockerfileの記載

続いてDockerfileの中身を書いていきます。
myprojectのところはコンテナ起動の際に作成するディレクトリ名なので、何でも大丈夫です
ただし、それ以降の記述でも随時書き換えてください

Dockerfile
FROM ruby:2.5.1

RUN apt-get update && \
    apt-get install -y mysql-client nodejs vim --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir /myproject

WORKDIR /myproject

ADD Gemfile /myproject/Gemfile
ADD Gemfile.lock /myproject/Gemfile.lock

RUN gem install bundler
RUN bundle install

ADD . /myproject

詳細な説明は省きますが、ざっと説明すると

  • ruby2.5.1をベースイメージとする
  • コンテナ内で必要なコマンドをインストール
  • myprojectというディレクトリを作成して基点にする
  • Gemfileをコンテナ上にコピーした後、bundle install
  • ローカルのディレクトリ、ファイルをコンテナ上にコピー

という感じかと思います。

3. docker-compose.ymlの記載

Rubyのコンテナは作成できるようになりました。
続いてこれをもとにアプリケーションのコンテナとデータベースのコンテナを作成し、それらのコンテナをリンクさせるための作業をしていきます。
docker-compose.ymlを以下のように記載します。
*mysqlは8.0以上だと認証方法が異なるようなので注意
https://qiita.com/yensaki/items/9e453b7320ca2d0461c7

docker-compose.yml
version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - mysql-data:/var/lib/mysql  #データの永続化のために必要
    ports:
      - "4306:3306" #両方3306でもok。詳細は下の「番外編:DBをsequel proで可視化したい」へ

  app:
    tty: true       #コンテナ上でbinding.pryするために必要
    stdin_open: true  #コンテナ上でbinding.pryするために必要
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myproject  #ローカルのディレクトリをコンテナ上にマウント
      - bundle:/usr/local/bundle  #bundle installした後buildし直さなくてよくなる
    links:
      - db

volumes:
  mysql-data:
  bundle:   #bundle installした後buildし直さなくてよくなる

要点は以下

  • versionは2でも3でもいいと思いますが、使えるコマンドが違ってくるみたいです。
  • servicesのところにdbとappがありますが、これらがそれぞれコンテナになります。
  • appのコンテナのlinksにdbがあり、これによってappコンテナとdbコンテナが連携できるようになります
  • 一番下のvolumesには永続化させたいデータを記載
  • appコンテナ上でvolumes: - .:/myprojectとすることで、ローカルのディレクトリをマウントしている。
  • dbコンテナ上でvolumes: -mysql-data:/var/lib/mysqlとすることでデータベースで変更されたデータを永続化。この記述がないと、コンテナを壊した時に変更したデータが消えてしまいます。
  • bundle installとbinding.pryのための記述は本記事、最後のおまけを参照

4. database.ymlの変更

これまでの作業でappコンテナとdbコンテナを連携させる設定をしました。
最後にappコンテナからdbコンテナに接続するために、接続設定をします。
database.ymlの中身はおそらく初期設定のままだとこんな感じの記述になってるかと思います。

config/database.yml変更前
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

このままだとsocket通信でDB接続をするので、せっかく作成したdbコンテナが意味なくなってしまいます。
作成したdbコンテナに接続するために以下のように変更します。

config/database.yml変更後
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:password
  host: db   #変更(docker-compose.ymlのservice名を記載)

usernameやpasswordは環境変数で設定している記事もいくつか見ますが、開発環境なら気にしなくてもいいかなと思いました。
本番環境ではちゃんと環境変数を設定します。

以上で準備ができました。
あとはターミナルで該当アプリのディレクトリまで移動して、docker-compose upと入力するだけです
(Gemfile.lockの中身を削除して空にしないとエラーになるかもしれません)
localhost:3000で接続確認して終了です!

今回はMySQLを使いましたが、他のDBでも可能なはずです(未検証)
*ポート番号は変わるはずなのでご注意ください

番外編:DBをsequel proで可視化したい

今まで開発していた時、DBをsequel proで可視化していて便利だったのですが、docker上のDBも可視化したい!
という方に向けて以下に方法を記載します

docker-compose.ymlで以下のように記載していました
Ruby:docker-compose.yml
db:
ports:
- "4306:3306"

これはホストが4306で接続した時にコンテナ上では3306に置き換えますという意味です。
準備はこれでokなのでsequel proで接続します。
sequel proを開いて、標準タブに切り替えます。
そこで以下の内容を入力します

名前: 任意、変えなくてもok
ホスト: 127.0.0.1
ユーザー名: root (database.ymlに記載のユーザー名)
パスワード: password (database.ymlにパスワード)
データベース: 空でok
ポート: 4306docker-compose.ymlportsに記載した左側)

ホストの127.0.0.1は自分自身を表すIPアドレス

これで見れるようになるはず!

その他開発する上で必要なコマンド

docker上でrails g controllerやrails db:migrateなどを行う時は以下のようにコンテナを通して入力します
appの部分はdocker-compose.ymlで作成したコンテナ名のappのことです

docker-compose run --rm app 入力したいコマンド(例: rails db:migrate)

その他必要なコマンドは以下の記事参照
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1



全てのコンテナやイメージを削除する場合はこちら

#全てのコンテナ停止
docker stop $(docker ps -q)

#全てのコンテナ削除
docker rm $(docker ps -q -a)

#全てのイメージ削除
docker rmi $(docker images -q)

おまけ

bundle installしたい時

開発していく中で、gemを追加してbundle installしたい場面が出てくると思います
そのままやってもできるんですが、追加したgem内容がコンテナ内に反映されないため、イメージをbuildし直さなくてはなりません。
いくつか解決方法はあるみたいですが、今回はvolumeでマウントするという方法で解決しました。

docker-compose.yml
app:
  volumes:
    - bundle:/usr/local/bundle
  
 #中略

volumes:
  bundle:

参考記事
https://qiita.com/neko-neko/items/abe912eba9c113fd527e

bindin.pryしたい時

binding.pryをするためには以下の記述を追加します

docker-compose.yml
app:
  tty: true
  stdin_open: true

おわりに

dockerについて全くわからないところから環境構築するのはかなり大変でした
自分なりにまとめられて良かった
同じような状況の人の参考になれば幸いです

間違ってる場所があれば指摘していただけると幸いです

本番環境でDockerを使うのも苦労したので、そのうち開発環境との違いなどもまとめようかなと思います

参考記事

Dockerについての概要と色々なTIPSを知りたい場合は下記リンクがおすすめ
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1

実際の作業で参考にした記事
https://qiita.com/azul915/items/5b7063cbc80192343fc0
https://qiita.com/Nishi53454367/items/aee4cf0c346bc115be99

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

既存のRailsアプリをDockerコンテナで動かす方法+sequel proによるDBコンテナ可視化

はじめに

新規アプリをDocker環境で開発するやり方はたくさんあるけど、既存アプリをDocker環境で構築するやり方は全然見当たらず、わりと苦労しました。
振り返ってみると新規アプリでの構築の仕方とあまり変わらないはずなのですが、色々エラー出て苦労したのでまとめておきます。

個々のコマンドの意味もできるだけ記載しました。
単なる環境構築だけでなく、DBコンテナのsequel proによる可視化やAPPコンテナでのbinding.pryの仕方、bundle install後にbuildし直さなくてもよい設定にする方法などもまとめました。

同じく既存のRailsアプリをDocker上で構築したい人の参考になれば幸いです。

内容について間違っていたら教えていただけると嬉しいです。

開発環境

  • Ruby: 2.5.1
  • Rails: 5.2.4
  • MySQL: 5.6
  • MacOS

前提

  • Docker for Macはインストール済み
  • Dockerについての基礎知識
  • 今回は開発環境のみ

対象読者

作成した既存のアプリをDocker上で構築したい人

目次

  • コンテナ起動までの大まかな流れ
  • 実際の作業
  • 番外編:sequel proによるDBコンテナの可視化
  • 開発する上でのDockerコマンド
  • おまけ
    • railsコンテナ上でbinding.pryをする方法
    • railsコンテナ上でbundle installした時に、変更内容をコンテナ上に反映させる方法

コンテナ起動までの大まかな流れ

DockerfileにてRubyのベースイメージをもとにイメージを作成する

作成したイメージをもとにdocker-compose.ymlでappコンテナを作成すると同時に、DBのコンテナのイメージを作成し、これらのコンテナを連携させる

database.ymlを修正してappコンテナからdbコンテナへ接続できるように設定する

実際の作業

  1. Dockerfileとdocker-compose.ymlの作成
  2. Dockerfileの記載
  3. docker-compose.ymlの記載
  4. database.ymlの変更

1. Dockerfileとdocker-compose.ymlの作成

まず、開発しているアプリで、Dockerfileとdocker-compose.ymlを以下のように作成します。

アプリ名
  |- app
  |- bin
  |- config
      #略
  |- vendor
  - .gitignore
  - config.rb
  - Dockerfile           #追加
  - docker-compose.yml  #追加
  - Gemfile
  - Gemfile.lock
      #略

2. Dockerfileの記載

続いてDockerfileの中身を書いていきます。
myprojectのところはコンテナ起動の際に作成するディレクトリ名なので、何でも大丈夫です
ただし、それ以降の記述でも随時書き換えてください

Dockerfile
FROM ruby:2.5.1

RUN apt-get update && \
    apt-get install -y mysql-client nodejs vim --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir /myproject

WORKDIR /myproject

ADD Gemfile /myproject/Gemfile
ADD Gemfile.lock /myproject/Gemfile.lock

RUN gem install bundler
RUN bundle install

ADD . /myproject

詳細な説明は省きますが、ざっと説明すると

  • ruby2.5.1をベースイメージとする
  • コンテナ内で必要なコマンドをインストール
  • myprojectというディレクトリを作成して基点にする
  • Gemfileをコンテナ上にコピーした後、bundle install
  • ローカルのディレクトリ、ファイルをコンテナ上にコピー

という感じかと思います。

3. docker-compose.ymlの記載

Rubyのコンテナは作成できるようになりました。
続いてこれをもとにアプリケーションのコンテナとデータベースのコンテナを作成し、それらのコンテナをリンクさせるための作業をしていきます。
docker-compose.ymlを以下のように記載します。
*mysqlは8.0以上だと認証方法が異なるようなので注意
https://qiita.com/yensaki/items/9e453b7320ca2d0461c7

docker-compose.yml
version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - mysql-data:/var/lib/mysql    #データの永続化のために必要
    ports:
      - "4306:3306"  #両方3306でもok。詳細は下の「番外編:DBをsequel proで可視化したい」へ

  app:
    tty: true          #コンテナ上でbinding.pryするために必要
    stdin_open: true   #コンテナ上でbinding.pryするために必要
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myproject    #ローカルのディレクトリをコンテナ上にマウント
      - bundle:/usr/local/bundle    #bundle installした後buildし直さなくてよくなる
    links:
      - db

volumes:
  mysql-data:
  bundle:      #bundle installした後buildし直さなくてよくなる

要点は以下

  • versionは2でも3でもいいと思いますが、使えるコマンドが違ってくるみたいです。
  • servicesのところにdbとappがありますが、これらがそれぞれコンテナになります。
  • appのコンテナのlinksにdbがあり、これによってappコンテナとdbコンテナが連携できるようになります
  • 一番下のvolumesには永続化させたいデータを記載
  • appコンテナ上でvolumes: - .:/myprojectとすることで、ローカルのディレクトリをマウントしている。
  • dbコンテナ上でvolumes: -mysql-data:/var/lib/mysqlとすることでデータベースで変更されたデータを永続化。この記述がないと、コンテナを壊した時に変更したデータが消えてしまいます。
  • bundle installとbinding.pryのための記述は本記事、最後のおまけを参照

4. database.ymlの変更

これまでの作業でappコンテナとdbコンテナを連携させる設定をしました。
最後にappコンテナからdbコンテナに接続するために、接続設定をします。
database.ymlの中身はおそらく初期設定のままだとこんな感じの記述になってるかと思います。

config/database.yml変更前
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

このままだとsocket通信でDB接続をするので、せっかく作成したdbコンテナが意味なくなってしまいます。
作成したdbコンテナに接続するために以下のように変更します。

config/database.yml変更後
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:password
  host: db   #変更(docker-compose.ymlのservice名を記載)

usernameやpasswordは環境変数で設定している記事もいくつか見ますが、開発環境なら気にしなくてもいいかなと思いました。
本番環境ではちゃんと環境変数を設定します。

以上で準備ができました。
あとはターミナルで該当アプリのディレクトリまで移動して、docker-compose upと入力するだけです
(Gemfile.lockの中身を削除して空にしないとエラーになるかもしれません)
localhost:3000で接続確認して終了です!

今回はMySQLを使いましたが、他のDBでも可能なはずです(未検証)
*ポート番号は変わるはずなのでご注意ください

番外編:DBをsequel proで可視化したい

今まで開発していた時、DBをsequel proで可視化していて便利だったのですが、docker上のDBも可視化したい!
という方に向けて以下に方法を記載します

docker-compose.ymlで以下のように記載していました
Ruby:docker-compose.yml
db:
ports:
- "4306:3306"

これはホストが4306で接続した時にコンテナ上では3306に置き換えますという意味です。
準備はこれでokなのでsequel proで接続します。
sequel proを開いて、標準タブに切り替えます。
そこで以下の内容を入力します

名前: 任意、変えなくてもok
ホスト: 127.0.0.1
ユーザー名: root (database.ymlに記載のユーザー名)
パスワード: password (database.ymlにパスワード)
データベース: 空でok
ポート: 4306(docker-compose.ymlのportsに記載した左側)

ホストの127.0.0.1は自分自身を表すIPアドレス

これで見れるようになるはず!

その他開発する上で必要なコマンド

docker上でrails g controllerやrails db:migrateなどを行う時は以下のようにコンテナを通して入力します
appの部分はdocker-compose.ymlで作成したコンテナ名のappのことです

docker-compose run --rm app 入力したいコマンド(例: rails db:migrate)

その他必要なコマンドは以下の記事参照
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1



全てのコンテナやイメージを削除する場合はこちら

#全てのコンテナ停止
docker stop $(docker ps -q)

#全てのコンテナ削除
docker rm $(docker ps -q -a)

#全てのイメージ削除
docker rmi $(docker images -q)

おまけ

bundle installしたい時

開発していく中で、gemを追加してbundle installしたい場面が出てくると思います
そのままやってもできるんですが、追加したgem内容がコンテナ内に反映されないため、イメージをbuildし直さなくてはなりません。
いくつか解決方法はあるみたいですが、今回はvolumeでマウントするという方法で解決しました。

docker-compose.yml
app:
  volumes:
    - bundle:/usr/local/bundle

   #中略

volumes:
  bundle:

参考記事
https://qiita.com/neko-neko/items/abe912eba9c113fd527e

bindin.pryしたい時

binding.pryをするためには以下の記述を追加します

docker-compose.yml
app:
  tty: true
  stdin_open: true

おわりに

dockerについて全くわからないところから環境構築するのはかなり大変でした
自分なりにまとめられて良かった
同じような状況の人の参考になれば幸いです

間違ってる場所があれば指摘していただけると幸いです

本番環境でDockerを使うのも苦労したので、そのうち開発環境との違いなどもまとめようかなと思います

参考記事

Dockerについての概要と色々なTIPSを知りたい場合は下記リンクがおすすめ
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1

実際の作業で参考にした記事
https://qiita.com/azul915/items/5b7063cbc80192343fc0
https://qiita.com/Nishi53454367/items/aee4cf0c346bc115be99

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

Rails Datetime型のカラムの値を日付(mm/dd/yyyy)単位で集計する方法

はじめに

gem chatkickを使用して、値を日付(mm/dd/yyyy)ごとにカウントしようとした際に、ハマってしまったのでその備忘録になります。

概要

やりたかったことは簡単グラフ表示 gem 'charkick'を使用して、テーブルの値を日付単位でカウントして表示したかった。
ちなみに、charkick の一次情報はこちら。
また、charkickを使っての日付単位での集計にはgem 'groupdate'を使うことがベストプラクティスらしい

導入

以下の記事を参考にcharkickを導入しました
Railsメモ(29) : Chartkickで簡単にグラフを描画する

ここから本題

ぶつかった問題

エラー発生
ActiveRecord::Base.default_timezone must be :utc to use Groupdate
スクリーンショット 2020-01-10 11 57 39

どうやらtimezoneがUTCでないといけないらしい。アプリのtimezoneをtokyoにしていたが、あくまでtokyoのままカウントしたい。

application.rb
  class Application < Rails::Application
   ## 途中略
   config.time_zone = 'Tokyo'
  end

対応策

groupdateのメソッドgroup_by_day を使うとエラーの回避ができず、しょうがなくあきらめることに。
ちなみにエラーが出ていたコードは以下。

  • 対応前
user_controller.rb
  class UsersController < ApplicationController
   ## 途中略
    def show

      @data2 = Message.where(user_id: current_user.id).group_by_day(:created_at).count
      ## 途中略
     end
  end
  • 対応後
user_controller.rb
  class UsersController < ApplicationController
   ## 途中略
    def show
     # messageテーブル値の取得
     data2 = Message.where(user_id: current_user.id)

     # 配列の宣言
     c = []

     # data2の値を日付(mm/dd/yyyy)形式で取得し配列に格納
     data2.each do |d|
       c << d.created_at.strftime('%Y%m%d').to_s
     end

     # 配列に含まれている重複している値を数える
     @data2 = c.each_with_object(Hash.new(0)){|v,o| o[v]+=1}

     @today = Date.today
     @lastmonth_today = @today.prev_day(14)
    end
  end

もっといい書き方ができるかもしれませんが、とりあえずこれで日付単位でのカウントができた。

ちなみに表示側のHTML以下

show.html.haml.rb
.learning-curve
  # 途中略
  .learning-curve_graph
  = line_chart @data2, width: "100%", height: "300px",min: 0, max: 20, xmin: @lastmonth_today, xmax: @today,label: "Value",xtitle: "日付",ytitle: "登録件数"

結果

無事に日付単位でのカウントに成功し、グラフの表示ができた。

スクリーンショット 2020-01-10 12 53 15

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

2回目以降のAWSを無料で利用する方法(請求かからないようにする)

Amazon EC2の無料条件

  • 750時間/月 (t2.microインスタンスの使用もこれに含む)まで
  • Amazon S3: 5GBの標準ストレージ、20,000件のGETリクエスト、2,000件のPUTリクエスト
  • Elastic IPアドレス 実行中のインスタンスに関連づけられたElastic IPアドレスを1つだけ インスタンスに紐付いていないElastic IPアドレスは全て課金対象
  • IAM: IAMユーザーの一時的なセキュリティ認証情報を使用して他のAWSサービスにアクセスするときのみ料金が発生

2回目以降で実施する場合

  • Elastic IPアドレスを解放する (すでに作成済みで、これ以上必要の無い場合)
  • 紐付いているS3バケットを削除する
  • インスタンスを削除する

Elastic IPアドレスを解放する

Elastic IPアドレスは、停止しているインスタンスに関連づけられている場合に時間ごとに料金が発生します。そのため、インスタンスを停止するときにElastic IPアドレスを解放する必要があります。

手順

  1. (https://console.aws.amazon.com/ec2/) にある Amazon EC2 コンソールを開きます。

    スクリーンショット 2020-01-10 12.13.49.png

  2. [Elastic IP] を選択します。

    スクリーンショット 2020-01-10 12.17.28.png

  3. Elastic IP アドレスを選択✅し、[アクション]>[Elastic IPアドレスの解放]>[解放] の順に選択します。
    スクリーンショット 2020-01-10 12.11.21.png

参考URL: Elastic IPアドレスを解放する方法
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html#using-instance-addressing-eips-releasing

S3バケットを削除しよう

不要なバケットである場合、以下の手順で削除することができます。(ただし、同じバケット名を別のサービス等で使いたい場合は、バケットの中身を空にするようにしてください。)

手順

  1. AWS マネジメントコンソール にサインインし、Amazon S3 コンソール (https://console.aws.amazon.com/s3/) を開きます。
    スクリーンショット 2020-01-10 12.22.44.png

  2. [バケット名] リストで、削除するバケットの名前の横にあるバケットアイコンを選択✅
    スクリーンショット 2020-01-10 12.24.11.png

  3. [バケットを削除する] を選択します。(または空にする)
    スクリーンショット 2020-01-10 12.26.09.png

  4. [バケットを削除する] ダイアログボックスで、削除するバケットの名前を確認のために入力し、[確認] を選択します。
    スクリーンショット 2020-01-10 12.27.40.png

EC2インスタンスの停止させましょう

インスタンスを停止するとEIastic IPアドレスは関連づけられなくなるので、あらかじめEIastic IPアドレスを解放し課金されないように気をつけましょう。

手順

  1. (https://console.aws.amazon.com/ec2/) にある Amazon EC2 コンソールを開きます。
    スクリーンショット 2020-01-10 12.32.12.png

  2. 
EC2コンソールで [実行中インスタンス] を選択し、インスタンスを選択します
    スクリーンショット 2020-01-10 12.34.28.png

  3. 停止したいインスタンスを選択✅

  4. [アクション] を選択
    スクリーンショット 2020-01-10 12.37.39.png

  5. [インスタンスの状態] >[停止] を選択します。
    スクリーンショット 2020-01-10 12.38.01.png
    [停止] が無効になっている場合は、インスタンスが既に停止しているか、またはルートボリュームがインスタンスストアボリュームです。(インスタンスを停止すると、インスタンスストアボリューム上のデータは消去されます。インスタンスストアボリュームのデータを保持するには、このデータを永続的ストレージに必ずバックアップしてください。)


参考URL: インスタンスの停止と起動
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Stop_Start.html

費用はこまめに確認する

発生している料金については、AWSの請求ダッシュボードからいつでも確認することができます。気になる場合は、こまめに確認するようにしましょう。

手順

  1. 画面右上にある 『アカウント名』 を選択し、 『注文と請求書』 を選択
    スクリーンショット 2020-01-10 12.46.29.png

  2. 画面右にあるサイドナビの『請求書』を選択。請求金額の確認が可能
    スクリーンショット 2020-01-10 12.50.23.png

不明な課金がされている場合

その他にも数十円の料金が発生していたり、不明な料金が発生していることがあったら以下のような対応を取りましょう。

高度な設定

費用発生を最小限に留めるために、EC2を自動でシャットダウンされるように設定したり、無料利用枠を超えないようにS3でオブジェクトの有効期限を設定できたりします。以下のリンクを参考にしてください。

無駄なコストを省こう!AWSで消し忘れを防止するためにチェックすべき7つのポイント
(https://dev.classmethod.jp/cloud/aws/cost-check-point/)

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

2回目以降のAWSを無料で利用する方法(請求かからないようにインスタントの削除)

Amazon EC2の無料条件

  • 750時間/月 (t2.microインスタンスの使用もこれに含む)まで
  • Amazon S3: 5GBの標準ストレージ、20,000件のGETリクエスト、2,000件のPUTリクエスト
  • Elastic IPアドレス 実行中のインスタンスに関連づけられたElastic IPアドレスを1つだけ インスタンスに紐付いていないElastic IPアドレスは全て課金対象
  • IAM: IAMユーザーの一時的なセキュリティ認証情報を使用して他のAWSサービスにアクセスするときのみ料金が発生

2回目以降で実施する場合

  • Elastic IPアドレスを解放する (すでに作成済みで、これ以上必要の無い場合)
  • 紐付いているS3バケットを削除する
  • インスタンスを削除する

Elastic IPアドレスを解放する

Elastic IPアドレスは、停止しているインスタンスに関連づけられている場合に時間ごとに料金が発生します。そのため、インスタンスを停止するときにElastic IPアドレスを解放する必要があります。

手順

  1. (https://console.aws.amazon.com/ec2/) にある Amazon EC2 コンソールを開きます。

    スクリーンショット 2020-01-10 12.13.49.png

  2. [Elastic IP] を選択します。

    スクリーンショット 2020-01-10 12.17.28.png

  3. Elastic IP アドレスを選択✅し、[アクション]>[Elastic IPアドレスの解放]>[解放] の順に選択します。
    スクリーンショット 2020-01-10 12.11.21.png

参考URL: Elastic IPアドレスを解放する方法
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html#using-instance-addressing-eips-releasing

S3バケットを削除しよう

不要なバケットである場合、以下の手順で削除することができます。(ただし、同じバケット名を別のサービス等で使いたい場合は、バケットの中身を空にするようにしてください。)

手順

  1. AWS マネジメントコンソール にサインインし、Amazon S3 コンソール (https://console.aws.amazon.com/s3/) を開きます。
    スクリーンショット 2020-01-10 12.22.44.png

  2. [バケット名] リストで、削除するバケットの名前の横にあるバケットアイコンを選択✅
    スクリーンショット 2020-01-10 12.24.11.png

  3. [バケットを削除する] を選択します。(または空にする)
    スクリーンショット 2020-01-10 12.26.09.png

  4. [バケットを削除する] ダイアログボックスで、削除するバケットの名前を確認のために入力し、[確認] を選択します。
    スクリーンショット 2020-01-10 12.27.40.png

EC2インスタンスの停止させましょう

インスタンスを停止するとEIastic IPアドレスは関連づけられなくなるので、あらかじめEIastic IPアドレスを解放し課金されないように気をつけましょう。

手順

  1. (https://console.aws.amazon.com/ec2/) にある Amazon EC2 コンソールを開きます。
    スクリーンショット 2020-01-10 12.32.12.png

  2. 
EC2コンソールで [実行中インスタンス] を選択し、インスタンスを選択します
    スクリーンショット 2020-01-10 12.34.28.png

  3. 停止したいインスタンスを選択✅

  4. [アクション] を選択
    スクリーンショット 2020-01-10 12.37.39.png

  5. [インスタンスの状態] >[停止] を選択します。
    スクリーンショット 2020-01-10 12.38.01.png
    [停止] が無効になっている場合は、インスタンスが既に停止しているか、またはルートボリュームがインスタンスストアボリュームです。(インスタンスを停止すると、インスタンスストアボリューム上のデータは消去されます。インスタンスストアボリュームのデータを保持するには、このデータを永続的ストレージに必ずバックアップしてください。)


参考URL: インスタンスの停止と起動
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Stop_Start.html

費用はこまめに確認する

発生している料金については、AWSの請求ダッシュボードからいつでも確認することができます。気になる場合は、こまめに確認するようにしましょう。

手順

  1. 画面右上にある 『アカウント名』 を選択し、 『注文と請求書』 を選択
    スクリーンショット 2020-01-10 12.46.29.png

  2. 画面右にあるサイドナビの『請求書』を選択。請求金額の確認が可能
    スクリーンショット 2020-01-10 12.50.23.png

不明な課金がされている場合

その他にも数十円の料金が発生していたり、不明な料金が発生していることがあったら以下のような対応を取りましょう。

高度な設定

費用発生を最小限に留めるために、EC2を自動でシャットダウンされるように設定したり、無料利用枠を超えないようにS3でオブジェクトの有効期限を設定できたりします。以下のリンクを参考にしてください。

無駄なコストを省こう!AWSで消し忘れを防止するためにチェックすべき7つのポイント
(https://dev.classmethod.jp/cloud/aws/cost-check-point/)

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

【翻訳】Bundler 3アップグレードガイド

はじめに

Rubyのパッケージ管理ツールであるBundlerはバージョン 3で後方互換性が失われる様々な変更点が導入される予定になっています。
そして、バージョン 3への移行を容易にするため、バージョン 2.1ではバージョン 3で使えなくなる機能を使うと警告が出ます。

これらの内容については公式リポジトリのアップグレードガイドで詳細が説明されています。

https://github.com/rubygems/bundler/blob/master/UPGRADING.md

この記事は上記のアップグレードガイドの日本語訳です。

翻訳したアップグレードガイドの版について

この記事で翻訳したのは2019年10月3日に更新された以下の版です。
(翻訳時点のBundlerの最新バージョンは2.1.4)

https://github.com/rubygems/bundler/blob/e8f261882397f7e8a6c74760f8fe1a4955c9e980/UPGRADING.md

今後更新される可能性もあるため、必要に応じて最新の版を参照するようにしてください。

https://github.com/rubygems/bundler/blob/master/UPGRADING.md

おことわり

普段あまり使わない機能については、正しく翻訳できているかどうかあまり自信がありません。
もし明らかにおかしな内容を見つけたら、コメント欄や編集リクエスト等で報告してください?

ラインセンスについて

この記事はBundlerと同様にMITライセンスで公開します。

This document is under the MIT License.

それでは以下がアップグレードガイドの翻訳になります。

【翻訳】アップグレードについて

Bundler 3について

以下で説明するのはBundler 3で導入される変更点のまとめです。なぜその変更を入れるのか、そして非推奨化のプロセスがどのようになるのかについても説明しています。非推奨になる変更点はBundler 2.1のリリース時にすべてデフォルトで表示されます。

もし非推奨警告の対応は後回しにして警告を非表示にしたい場合は、設定によってそのように変更できます。その場合はBUNDLE_SILENCE_DEPRECATIONSという環境変数を"true"に設定するか、bundle configコマンドを使って設定してください。グローバルに設定を変更したい場合はbundle config set silence_deprecations trueコマンドを使い、ローカルの設定だけ変更したい場合はbundle config set --local silence_deprecations trueコマンドを使います。これ以降、本ドキュメントではこの3つの設定方法がすべて有効である前提で執筆していきますが、記述するのはbundle config set <option> <value>の方法だけにします。

全般的な話として、これらの変更点は「新規Bundlerユーザー」のユーザー体験を改善するために行われます。ここでいう新規Bundlerユーザーとは、毎回特に決まった使い方をしておらず、これまでの使用体験から「Bundlerにはこう動いてほしい」という明確な意思も持っていないユーザーのことを指します。今回の変更点は長年Bundlerを使ってきたユーザーをイライラさせるものだと思います。その点は私たちも十分理解しています。ですので、私たちはこのプロセスをできる限りスムーズなものにしたつもりです。

非推奨化警告は、「CLIの非推奨警告」と「DSLの非推奨警告」と「その他の非推奨警告」という3つのグループに分けられます。それぞれについて今から見ていきましょう。

CLIの非推奨警告

CLIではBundlerを動かすためのコマンドとオプションの集合を定義しています。このコマンドとオプションの集合に対して、私たちはさまざまな変更を導入する予定です。

  • 一度設定するとそれ以後の呼び出しでその設定が記憶されるbundle install用のフラグが非推奨となりました。

具体的には、bundle installに渡す --clean, --deployment, --frozen, --no-cache, --no-prune, --path, --shebang, --system, --without, --with オプションのことになります。

記憶されるCLIオプションはこれまで混乱とバグレポートの温床になってきました。これは初心者に限った話ではなく、経験豊富なユーザーにとっても同様です。CLIツールは全く同じ呼び出し方なのに異なる振る舞いをするべきではありません。そうなってもよいのは、そのように明示的に設定されている場合「だけ」です。それが設定の存在理由であり、ユーザーが気づかないところでこっそりと設定が変更されるべきではありません。

この仕様変更によって影響を受けるのは、この機能に依存する「よくあるワークフロー」です。たとえば、本番環境でbundle install --without development:testというコマンドを実行すると、このフラグがアプリケーションの設定ファイルに保存され、それ以降はbundleコマンドを実行してもdevelopmentとtestのgemをありがたく無視してくれます。Bundler 3以降はこの魔法が使えなくなります。同じ挙動を維持するためには明示的な設定が必要です。設定を入れる方法は、環境変数、アプリケーションの設定、マシン全体の設定のいずれかです。たとえば、bundle config set without development testというコマンドを使います。

こうしたフラグの削除は類似のコマンドにも適用されます。たとえば、bundle check --pathがそうです。

  • bundle installbundle updateに渡す--forceフラグは、--redownloadにリネームされます。

これは単なるフラグのリネームです。リネームするのは実際の挙動をよりわかりやすくするためです。このフラグは強制的にすべてのgemを再ダウンロード(redownload)するだけで、それ以外の何かを強制(force)するわけではありません。

  • bundle vizコマンドが削除され、プラグインとして切り出されます。

これはBundlerで唯一外部依存が発生するコマンドです。依存先はOS(graphvizパッケージ)とgem(ruby-graphviz gem)です。この依存性を排除することで開発がより容易になります。また、この機能はBundlerチームによって公式に保守されるBundlerプラグインになります。ユーザーもこのプラグインを参照すれば、独自のプラグインを作るのに役立ちます。このプラグインは従来のコアコマンドと同じコードになっていますが、唯一異なる点としてコマンド名がbundle graphに変わっています(でも、この方がずっとわかりやすいはずです)。この新しいプラグインのインストール方法や使い方についてはプラグインのリポジトリを参照してください。

  • bundle consoleコマンドが削除され、bin/consoleに置きかわります。

時間の経過とともにbundle consoleコマンドは保守するのが難しくなってきました。これは各ユーザーが自分独自の変更点を追加しようとしてくるためです。保守を容易にし、細々した議論を減らすため、bundle consoleコマンドをbin/consoleスクリプトに置き換えます。このスクリプトはgem開発時にbundle gemコマンドで作成され、ユーザーは自分が好きなようにこのコマンドを修正することができます。

  • bundle updateコマンドを実行しても、すべてのgemがアップデートされなくなります(--allオプションが必要になります)。

Bundlerチームはこのコマンドを使ってすべてのgemを一気にアップデートするのは、このコマンドの主要なユースケースになるべきではないと判断しました。それよりも1回につき1つのgemをアップグレードする(または関連するgemのグループをアップグレードする)方がよいと考えます。すべてのgemを一気にアップグレードすることもできますが、その場合は--allフラグが必要になります。

  • bundle installコマンドに--binstubsフラグを渡せなくなります。

--binstubsオプションはbundle installコマンドから削除され、bundle binstubsコマンドに置きかえられました。--binstubsオプションはプロジェクト内のgemに存在するすべての実行可能ファイル(executables)に対してbinスタブを作成します。しかし、これはほとんど役に立ちませんでした。なぜなら大半のユーザーが使うのはbinスタブの一部だけだからです。加えて、これを使うと、使われることのない大量のファイルがソース管理システムに追加されます。こうした理由により、binスタブは個別に作成され、個別にバージョン管理されるようになります。

  • bundle configコマンドに新しいサブコマンドが追加されました。

従来のインターフェースは混乱の原因になっていたと思います。なぜなら様々なフラグと引数の組み合わせによって実行されるオペレーションを推測しなければならなかったからです。これに代わり、私たちはlist, get, set, unsetというサブコマンドを導入しました。このサブコマンドの導入により、configコマンドが以前よりもきっと扱いやすくなったはずです。従来のインターフェースは非推奨になりましたが、警告メッセージと一緒に新しいコマンドの提案を行います。

  • bundle injectコマンドが非推奨になり、bundle addコマンドに置きかえられました。

新しいコマンド名の方がきっとユーザーのメンタルモデルにフィットし、より広いユースケースをサポートすると思います。bundle injectコマンドでサポートされていたインターフェースはbundle addコマンドでもまったく同じように動作します。ですので、新しいコマンドに移行するのは簡単なはずです。

ヘルパーの非推奨警告

  • 右のメソッドは非推奨になりました。Bundler.clean_env, Bundler.with_clean_env, Bundler.clean_system, Bundler.clean_exec

これらのヘルパーメソッドはすべて、背後でBundler.clean_envメソッドを使っています。これにより実行されるブロック内ではBundlerに関連する環境は削除されます。

ユーザーからたくさんのレポートを受け取った結果、ユーザーは通常この挙動を望まず、代わりにカレントプロセスが開始する前と同じBundler環境を使いたがっていることに私たちは気づきました。こうして生まれたのが、Bundler.with_original_env, Bundler.original_system, Bundler.original_execという3つのメソッドです。これらのメソッドはすべて新しいBundler.original_envメソッドを背後で使います。

とはいえ、特定の状況下では従来のBundler.clean_envの挙動が望ましいこともあるでしょう。たとえば、Railsジェネレータのテストをする場合は、bundlerのいない環境が欲しくなると思います。このため、私たちは従来の挙動を新しく、よりわかりやすい名前で維持できるようにしました。"clean"という単語はあまりにもあいまいだからです。というわけで、私たちは Bundler.unbundled_env, Bundler.with_unbundled_env, Bundler.unbundled_system, Bundler.unbundled_exec という4つのメソッドを新たに追加しています。

  • Bundler.environmentが非推奨になり、Bundler.loadに置き換えられました。

どれくらいの人がこれを直接使っているのかはわかりませんが、私たちはBundler::Environmentクラスを削除しました。このクラスはBundler.environmentによってインスタンス化されるクラスです。削除した理由はBundler::Runtimeが同じ役割のクラスだと気づいたからです。移行期間中、Bundler.environmentBundler.loadに委譲されます。このメソッドはBundler::Environmentへの参照を保持しています。

DSLの非推奨警告

Bundler DSLで発生する下記の非推奨警告は、Bundler 3で予定されている厳格なソース固定(strict source pinning)への準備を意味します。Bundler 3ではすべての依存ライブラリのsourceは厳格に定義されます。

  • 複数定義されたグローバルなGemfileのsourceはサポートされなくなります。

こんなふうに書く代わりに・・・

  source "https://main_source"
  source "https://another_source"

  gem "dependency1"
  gem "dependency2"

このように書いてください。

  source "https://main_source"

  gem "dependency1"

  source "https://another_source" do
    gem "dependency2"
  end
  • グローバルなpathgitのソース(source)はサポートされなくなります。

こんなふうに書く代わりに・・・

  path "/my/path/with/gems"
  git "https://my_git_repo_with_gems"

  gem "dependency1"
  gem "dependency2"

このように書いてください。

  gem "dependency1", path: "/my/path/with/gems"
  gem "dependency2", git: "https://my_git_repo_with_gems"

もしくは各ソースに対して複数のgemがあり、もっとDRYに書きたい場合はブロック記法を使ってください。

  path "/my/path/with/gems" do
    # gem "dependency1"
    # ...
    # gem "dependencyn"
  end

  git "https://my_git_repo_with_gems" do
    # gem "dependency1"
    # ...
    # gem "dependencyn"
  end

その他の非推奨警告

  • vladcapistrano用のデプロイヘルパー(Deployment helper)は削除されました。

vladツールは何年も活動が止まっているので自然に非推奨となりました。一方でcapistrano 3はcapistrano-bundler gemによってBundlerに統合されています。Capistrano 3のユーザーはきっとこれを使っているはずです。なんらかの理由でCapistrano 2を使い続けている場合は、遠慮無くBundler 2のbundler/deployment.rbファイルからCapistrano用のタスクをコピーして、ご自身のアプリケーションに追加してください。

基本的に私たちはあらゆるデプロイメントシステムの統合機能を保守したくありません。この機能を削除したのはこうした理由からです。

(翻訳は以上)

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

【Rails】config/localesに新規追加したファイルが読み込まれない【I18n】

はじめに

タイトルの通りです。
Railsで多言語化対応をする際にconfig/localesにymlファイルを追加していくと思いますが、それが読み込まれない場合の対応策です。

結論

早速結論なのですが、超シンプルで、Railsサーバを再起動するです。。。
既存ファイルに訳文を追加する場合はRailsサーバの再起動は不要ですが、新規ファイルを追加した場合はRailsサーバの再起動が必要です。

ちなみに少しこの記事の内容と外れるかもしれませんが、RailsガイドにRailsの初期化プロセスについて記載があったので参考としてリンクを貼っておきます。
Railsの初期化プロセス

おわりに

単純なミスで恥ずかしいのですが、めっちゃハマって辛かったので記事にしてみました。(typoやインデント、ディレクトリ構成等見直しまくりました。。。)
案外検索しても出てこず、他ごとしてたら急に「これ、サーバ再起動案件じゃね。。。?」と気が付いた次第です。はい。

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

I understand #Ruby Lonely operator &. is a operator allows nil receiver method chains

If receiver is nil you can do method chains many times

nil&.to_wow
# => nil
nil&.to_wow&.to_ya
# => nil
nil&.to_wow&.to_ya&.to_yes!
# => nil

If not nil is reciever then you can not chain undefined method by lonely operator

100&.to_wow
NoMethodError: undefined method `to_wow' for 100:Integer

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2924

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

index.html+mobile.haml なviewをrspecする

before_action do
  request.variant = :mobile if ua.match(/Android/)
end

とかするとviewを切り替えられる ActionPack Variants という機能1
view specを書く方法

# spec/views/users/index.html+mobile.haml_spec.rb

RSpec.describe 'users/index.html+mobile.haml', type: :view do
  it do
    render
  end
end

とやると 「html+mobile 何ていうフォーマットねーよ」 と怒られる
なので render の呼び出しで正しい情報を与える

# spec/views/users/index.html+mobile.haml_spec.rb

RSpec.describe 'users/index.html+mobile.haml', type: :view do
  it do
    render template: 'users/index.html.haml', variants: 'mobile'
  end
end

これで正しくmobileのテンプレートをレンダーできる
(確認は適当に = 1 / 0 とか追記すれば死んでくれる)

しかし当然めんどくさい
render の中身を見ると _default_render_options というのを describe の文字列から作っているようだ
なのでこいつをいじってしまう

# spec/support/variants_support.rb

module VariantsSupport
  def _default_render_options
     render_options = super

     if render_options[:formats].first
       formats, variants = render_options[:formats].first.to_s.split('+')
       render_options[:formats] = [formats.to_sym] if formats
       render_options[:variants] = [variants.to_sym] if variants
     end

     render_options
   end
end

RSpec::Rails::ViewExampleGroup::ExampleMethods.prepend(VariantsSupport)

これで render するだけでよくなった

なおこの現象は rspec 3.9 までの挙動で現在ベータの 4.0 では修正されている
本家の修正も _default_render_options なので大正解っぽい
早くリリースしてくれ


  1. 名前初めて知った 

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

テーブルの結合ができない。。Mysql2::Error: Column 'updated_at' in order clause is ambiguous

はじめに

Railsでeager_loadしようとしたときに、下記のようなエラーが出て解消に時間がかかったのでまとめました。

Mysql2::Error: Column 'updated_at' in order clause is ambiguous

やりたいこと

user の updated_at を指定した期間のものだけ抽出するために、テーブルの結合をしたい。

なぜeager_loadできないのか

これを実行すると、

user.rb
User.where("updated_at >= '2020/01/01' and updated_at <= '2020/01/31'").eager_load(:post)

MySQLのエラーが出る。

Mysql2::Error: Column 'updated_at' in order clause is ambiguous

なぜか。

updated_at は User にも Post にも存在しているため、どちらの updated_at なのか判別がつかない。

そこで、incidents.updated_at とすることで、User の updated_at なのか Post の updated_at なのかを明確化する。

下のように書き換えることで、エラーを解消することができました。

user.rb
# incidents.updated_at とすることで、user
User.where("incidents.updated_at >= '2020/01/01' and incidents.updated_at <= '2020/01/31'").eager_load(:post)

まとめ

updated_at は、どのテーブルでも持っている値となるので、こういう値でjoinするときは気をつけるようにします。

裏話としては、railsでデバックをしていていたのですが、eager_loadを実行したらSQL文しか表示されずエラーが表示されていませんでした。
.to_sで文字列化することで、上記のMysql2::Errorが出てなんとかデバックすることができました。
エラーが隠れてる??自分の確認方法が悪かっただけかもしれませんが、、
時間はかかりましたが、解決できてよかったです。

参考

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