Rails及びDocker環境でのpry-railsのデバッグ方法

なぜ記事を書こうと思ったか

Rails及びDocker環境でpry-railsでのデバッグをおこなったので、そのやり方を記載致します。

これまで、行っていたデバッグよりもより細かくコードを確認できるので、すごく便利に感じたので、多くの新人の方が使ってくれると嬉しいです。

Rails及びDocker環境でpry-railsでのデバッグ手順

※Dockerは構築して、起動してある事を前提として記載致します。

デバッグ手順

1.Railsのコードで動作を止めて、確認したいコードの直後にbinding.pryを追加します。

今回は例として、createメソッドのコードに付け足したいと思います。

def create
  permit_parameters = params.permit(:name, :age, :sex).to_h
  binding.pry

  user = User.create!(
           name: permit_parameters[:name].to_i,
           age: permit_parameters[:age],
           sex: permit_parameters[:sex]
         )

  return_json = { "#{ user.name }さんの登録を受け付けました。" }
  render json: return_json
end

上記のようにするだけで、permit_parameters変数の行までしか実行されないようになります。

2.docker ps -aでDockerで起動しているコンテナの一覧を表示し、Railsサーバーを立ち上げているコンテナのIDを確認します。

3.docker attach コンテナIDを入力し、Railsサーバーを立ち上げているコンテナに入ります。

4.今回の場合はcreateメソッドにデータをPOSTします。

ログと共に、以下のようなログも表示されます。

  1:      def create
  2:        permit_parameters = params.permit(:name, :age, :sex).to_h
  3:        binding.pry
  4:
=>5:        user = User.create!(
  6:                 name: permit_parameters[:name],
  7:                 age: permit_parameters[:age],
  8:                 sex: permit_parameters[:sex]
  9:               )
  10:
  11:       return_json = { "#{ user.name }さんの登録を受け付けました。" }
  12:       render json: return_json
  13:     end

上記のログでは、=>が書いてある行以前まで、コードが動いている事を表します。

また、[1] pry(#)>railsコンソールの時と同様の操作ができます。

[1] pry(#)> params[:name]
=> "田中太郎"

5.次の行のコードまで動作させたい場合は、nextと入力する。

[2] pry(#)> next

  1:      def create
  2:        permit_parameters = params.permit(:name, :age, :sex).to_h
  3:        binding.pry
  4:
  5:        user = User.create!(
  6:                 name: permit_parameters[:name],
  7:                 age: permit_parameters[:age],
  8:                 sex: permit_parameters[:sex]
  9:               )
  10:
=>11:       return_json = { "#{ user.name }さんの登録を受け付けました。" }
  12:       render json: return_json
  13:     end

[3] pry(#)>

先ほどまでは4行まで動作していましたが、今回は10行まで動作した状態になります。

このような作業をするだけで各コードが適切に動作しているか確認することができます。

デバッグ終了方法

1.continueを入力して、止まっていたコードを全て動作させる。

[3] pry(#)> continue

~~~ログが流れる~~~

2.controlボタンを押しながら、pの後にqを押す。

こうすることで、コンテナから出ることができます。もし、exitcontorol + cをした場合は、サーバーも停止されます。

3.binding.pry`を削除します。

最後に

自分は、logger.debugやログで動作状況を確認していたので、このデバッグ方法は非常に便利に感じました。是非、やった事がない方はやってみる事をお勧めします。もし、もっと良いデバッグ方法がある場合は、コメントで教えていただけると嬉しいです。読んで頂きありがとうございました。

webサーバーとアプリケーションサーバーの違いについて

なぜ記事を書こうと思ったか

アプリケーションサーバーとWebサーバーについての明確な違いと例えば、どのような種類があるか調べた為、備忘録としてまとめる。

webサーバーとアプリケションサーバーの説明

ユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムです。そして、場合によってはあなたのRailsアプリケーションにリクエストを投げます。SSLリクエストや静的なファイルやアセット、圧縮されたリクエスト等を処理したり、その他大半のwebサイトが必要としそうな数多くの処理をこなしたりすることができます。もし、Railsアプリケーションがリクエストを処理しなければならない場合は、webサーバーはリクエストをアプリケーションサーバーにパスします。

複数のアプリケーションを一度に処理したり、アセットを素早くレンダリングしたり、リクエストごとに発生する多くの処理をさばいたりしてくれます。

Railsアプリケーションを動かしているもの。コードを読み込み、アプリケーションをメモリに保持します。webサーバーからリクエストを受け取ると、Railsアプリケーションにそのことを知らせます。アプリケーションがリクエストを処理すると、アプリケーションサーバーはそのレスポンスをwebサーバーに返します。webサーバーを使わずに単体で実行できます。

 

まとめると、ユーザーからのリクエストをwebサーバーが処理し、Railsにアクセスする必要がある場合は、アプリケーションサーバーにリクエストを送る。その後、アプリケションからレスポンスされた情報をアプリケションサーバーがwebサーバーに送り、ユーザーに届けます。

しかし、必ずしもアプリケーションサーバーが必須なわけではなく、Pumaなどは、webサーバーでありながら、アプリケーションサーバーの仕事もこなすことができる為、Puma一つだけでもアプリケーションを動作させる事は可能である。

最後に

正直、インフラ関連の内容について理解が薄い為、今後も触れて行き深く理解して行きたいと思います。

間違っている箇所やわからない箇所があれば、ぜひコメントしていただけると嬉しいです。

読んで頂きありがとうございました。

参考資料

Railsのproduction.rbはどういう事が設定できるの?全ての設定を調べてみた!

なぜ記事を書こうと思ったか

Railsのproduction.rbでどのような設定をしているか及びどのような設定ができるかを確認する為に調べたので備忘録として残します。

default.confのコマンド説明

  • config.cache_classes = true

ソースコードをリロードしない。キャッシュが適用される。

  • config.eager_load

Railsのapp以下にあるクラス(ModelやController)を起動時に全て読み込むかどうか設定

  • config.consider_all_requests_local

すべてのエラーをブラウザに表示をするかの設定

例:Routing Errorなど詳細なエラー情報が表示される。

  • config.action_controller.perform_caching

アプリケーションのキャッシュの有無

  • config.require_master_key = true

ENV["RAILS_MASTER_KEY"]環境変数またはconfig/master.keyファイルでマスターキーを取得できない場合はアプリを起動しないようにする。

  • config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

public/ディレクトリ内の静的アセットを配信するかどうかを指定するかの設定。

production環境ではアプリケーションを実行するNginxやApacheなどのサーバーが静的アセットを扱う必要があるので、falseに設定されます。

  • config.asset_host

アセットを置くホストを設定

アセットとは、Webアプリケーションの直接のレスポンス以外の構成要素のことを指します。JavascriptCSS、画像などがこれにあたります。

  • config.action_dispatch.x_sendfile_header = 'X-Sendfile'

バックエンドで認証やログ記録などを処理し、Apacheにリダイレクトされた場所からエンドユーザーへのコンテンツの提供を処理させることができるため、バックエンドを解放して他のリクエストを処理できる。

  • config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

バックエンドで認証やログ記録などを処理し、NGINXにリダイレクトされた場所からエンドユーザーへのコンテンツの提供を処理させることができるため、バックエンドを解放して他のリクエストを処理できる。

  • config.active_storage.service = :local

config/storage.ymlで名前を宣言し、このオプションでファイルを保存する場所を指定

  • config.action_cable.mount_path = nil

Action Cableをメインサーバープロセスの一部としてマウントする場所を文字列で指定します。デフォルト値は/cableです。nilを設定すると、Action Cableは通常のRailsサーバーの一部としてマウントされなくなります。

ActionCableとは、Railsのアプリケーションと同様の記述で、WebSocket通信という双方向の通信によるリアルタイム更新機能を実装できるフレームワークで、Rails5から実装されました。利用することで、たとえばリアルタイムで更新されるチャット機能を実装することができます。

Cableサーバを決めたら、ServerのURLをclientサイドに提供する必要がある。Action CableサーバーがホストされているURLを文字列で指定します。Action Cableサーバーがメインのアプリケーションと別になっている場合に使う可能性があります。View側に action_cable_meta_tag を書く。

指定されていない送信元からのリクエストを受け付けません。送信元リストは、配列の形でサーバー設定に渡します。送信元リストには文字列のインスタンス正規表現を利用でき、これに対して一致するかどうかがチェックされます。

  • config.force_ssl = true

すべてのリクエストをHTTPSプロトコル下で実行するよう強制し、URL生成でも"https://"をデフォルトのプロトコルに設定します。

  • config.log_level = :info

Railsのログ出力をどのぐらい詳細にするかを指定します。

ログレベル(順に必要度が低くなる):①unknown ⇨ ②fetal → ③error → ④warn → ⑤info → ⑥debug)

④を指定した場合、④⑤⑥のログが出力される。

  • config.log_tags = [ :request_id ]

ログにタグ付けをする。

今回の場合、ログの前に一意の値が出力される。

  • config.cache_store = :mem_cache_store

Railsでのキャッシュ処理に使われるキャッシュストアを設定します。

キャッシュの種類

①:memory_store → プロセス内のメモリ

②:file_store → ファイルシステム

③:mem_cache_store → Dangaのmemcachedサーバーに一元化

④:null_store → キャッシュをしない

  • config.active_job.queue_adapter = :resque

キューのバックエンドに用いるアダプタを設定

Resqueは、バックグラウンドジョブを作成し、それらのジョブを複数のキューに配置し、後で処理するためのRedisがサポートするライブラリ

  • config.active_job.queue_name_prefix = "app_production"

キューの前にプレフィックスを付ける。

プレフィックスとは、単語の先頭に付加して特定の意味を付け加える要素(接辞)のこと。

  • config.action_mailer.perform_caching = false

メイラーのテンプレートでフラグメントキャッシュを有効にするかどうかを指定します。指定のない場合のデフォルト値はtrueです。

フラグメントキャッシュとは、ページの一部分をキャッシュする機能。キャッシュされたデータはキャッシュストアに保存され、2回目以降はキャッシュストアからデータを取り出される。

  • config.action_mailer.raise_delivery_errors = true

メール配信が完了しなかった場合にエラーを発生させるかどうかを指定

  • config.action_mailer.default_url_options

Action MailerのビューでURLを生成する

  • ActionMailer::Base.smtp_settings

ActionMailer経由の全てのメールがこのSMTP設定を用いて配信される

  • ActionMailer::Base.delivery_method

配信方法の設定

  • config.i18n.fallbacks = true

訳文がない場合のフォールバック動作を設定

フォールバック動作とは、システムに障害が発生したときに性能を落としたり機能を制限したりして限定的ながら稼動を続行すること。あるいは、利用したい機能が条件が悪く使えない場合に、代替となる機能に切り替えること。また、そのような機能や構成。

  • config.active_support.deprecation = :notify

非推奨警告メッセージの振る舞いを設定。どこにメッセージを出力するかを指定。

  • config.active_support.disallowed_deprecation = :log

利用が許されない非推奨警告メッセージの振る舞いを設定します。すべてのログ行の前に次のタグを付けます。

  • config.active_support.disallowed_deprecation_warnings = []

どの非推奨メッセージを禁止するかをアクティブサポートに伝えます。

  • config.log_formatter = ::Logger::Formatter.new

Railsロガーのフォーマットを定義

  • config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')

Rails.loggerで使われるロガーやRails関連のあらゆるロガー(ActiveRecord::Base.loggerなど)を指定します。デフォルトでは、ActiveSupport::LoggerのインスタンスをラップするActiveSupport::TaggedLoggingのインスタンスが指定されます。

標準出力用の Logger オブジェクトを作成する。

  • config.active_record.dump_schema_after_migration = false

マイグレーション実行時にスキーマダンプ(db/schema.rbまたはdb/structure.sql)を行なうかどうかを指定

スキーマダンプとは、スキーマを抽出する。db/schema.rb の作成

最後に

間違っている箇所やわからない箇所があれば、ぜひコメントしていただけると嬉しいです。

読んで頂きありがとうございました。

参考資料

Dockerで構築したRailsサービスのproductionモード起動方法

なぜ記事を書こうと思ったか

サービス開発中に本番環境のテストをする状況が発生し、Railsのproductionモードを起動する必要があったのですが、少し苦戦してしまった為、備忘録として残します。

関連ファイル

  • config/credentials.yml.enc
  • config/master.key rails newを実行した事がない場合、作成されていません。今回作成する手順も記載します。
  • docker-compose.yml
  • Dockerfile
  • config/database.yml
  • config/environments/production.rb

実行手順

※元々のconfig/credentials.yml.encに対応するmaster.keyを所持している場合、2~5の手順は飛ばして下さい。

1.ターミナルにてdocker-compose up -dでサーバーを起動し、docker-compose exec app bashでコンテナに入る。

2.コンテナにてEDITOR=vi rails credentials:editを実行し、config/master.keyを生成する。

スクリーンショット 2022-05-06 16 46 01

3.config/credentials.yml.encをukabu_01ディレクトリ以外のディレクトリに移動する。

4.コンテナにてEDITOR=vi rails credentials:editを実行し、config/credentials.yml.encを再作成。

(今回作成したmaster.keyでは、元々のconfig/credentials.yml.encを複合することができない為、再生成)

5.再生成されたconfig/credentials.yml.encファイルがvimで開かれている為、secret_key_baseに値が入っている事を確認後、:qvimを閉じる。

6.docker-compose.ymlのRailsサービスのコンテナにrails sコマンドを使用してる箇所がある為、-e productionを追記する。

7.Dockerfileにrails sコマンドを使用してる箇所に"-e", "production"を追記する。

8.config/database.ymlのproductionの記載をdevelopmentと同様の値にする。

※今回の記事では、テストの為の記事なので簡易にproductionモードのdatabaseの設定をしています。

9.ターミナルのコンテナをexitし、docker-compose downでサーバーを終了させる。

10.ターミナルでdocker-compose up -dを行い、docker-compose exec app bashでコンテナに再度入る。

11.config/environments/production.rbにあるconfig.cache_classesの値をfalseに変更する。

スクリーンショット 2022-05-06 17 28 36

上記の手順でproductionモードで操作する事ができるようになります。

動作確認後手順(developmentモードに戻す方法)

1. 今回作成したconfig/credentials.yml.encとconfig/master.keyを削除する。

2. 実行手順の3で別ディレクトリに移動したcredentials.yml.encをukabu_01/configディレクトリ配下に戻す。

3. docker-compose.yml、Dockerfile、config/database.yml、config/environments/production.rbで変更した箇所を元の状態に戻す。

4. .DS_Storeファイルが生成されている場合は、削除する。

最後に

間違っている箇所やわからない箇所があれば、ぜひコメントしていただけると嬉しいです。

読んで頂きありがとうございました。

API通信確認方法はThunderClientが便利

なぜ記事を書こうと思ったか

サービスの開発中にAPI通信が動作してるか確認する必要があった為、API通信確認方法の備忘録として残す為。

おすすめのAPI通信確認方法

おすすめのAPI通信確認方法としては、コードエディタにVScodeを利用している場合、VSCode拡張機能である「Thunder Client」をおすすめします。

昔は「Postman」というサービスがAPI通信確認方法として利用されており、VScodeを使っていない場合は、利用するのもありだと思いますが、「Thunder Client」はVScodeで完結できる為、非常に便利です。

「Thunder Client」の導入方法と使い方

  • 導入方法(インストールするだけですが笑)

VScode拡張機能を開き、以下のThunder Clientをクリックし、インストールを押して下さい。

スクリーンショット 2022-06-26 18 13 01
  • 使い方

1.拡張機能のマークの下に新しい雷のマークがあるので、クリックして下さい。

スクリーンショット 2022-06-26 18 23 45

2.「New Request」を押して下さい。

スクリーンショット 2022-06-26 18 26 05

3.検索バーの下にあるHeaderタブをクリックして下さい。

スクリーンショット 2022-06-26 18 26 44

4.「Raw」のチェックマークにチェックマークを入れて下さい。

スクリーンショット 2022-06-26 18 31 08

5.HttpHeadersにいらない情報がある為、全て削除して下さい。

6.HttpHeaderにcookieの値やX-CSRFtokenなど必要情報を入力して下さい。

もしわからない場合は、API通信できているか確認したいURLに関連するURLをグーグルで表示し、デベロッパーツールを開いて下さい。

「Network」タブを開き、⌘+Rを押し、RequestHeaderの中身を全てコピーして下さい。

スクリーンショット 2022-06-26 19 00 12

7.コピーした内容をThunderClientのHttpHeaderに貼り付け、検索バーにURLを入力後、Sendをクリックして下さい。

その後、ステータスコードなどが表示されます。

スクリーンショット 2022-06-26 19 03 45

最後に

間違っている箇所があれば、ぜひ教えていただけると嬉しいです。

読んで頂きありがとうございました。

gitのコンフリクト解消方法となぜ起こってしまうのか

なぜ記事を書こうと思ったか

サービスの開発中にブランチでのコンフリクトが発生した為、修正方法の備忘録として残す為。

そもそもコンフリクトはどの状況で起こる現象?

簡潔に言うと、同じブランチから派生した複数のブランチで同じファイルを編集した際に、コンフリクトが起きる。

hogeファイルを所持しているmainブランチとmainブランチからチェックアウトしたAブランチ、Bブランチがあるとします。Aブランチでhogeファイルを編集し、mainブランチにmergeした際に、Bブランチでもhogeファイルを編集し、mainブランチにmergeしようとした場合に、コンフリクトが生じます。

対処方法(備忘録の為、簡単に書きます笑)

  • 前提条件(コンフリクトを発生させる条件)

1. hogeファイルを所持するmainブランチの作成

hogeファイルの中身

あいさつの種類
①おはようございます。

2. mainブランチから派生したAブランチの作成

hogeファイルの中身

あいさつの種類
①おはようございます。
②こんにちは。

3. mainブランチから派生したBブランチの作成

hogeファイルの中身

あいさつの種類
①おはようございます。
②こんばんは。

4. Aブランチをmainブランチにmergeし、mainブランチでgit pullを行う。

5. Bブランチをmergeしようとしてもコンフリクトを起こしている。(githubのプルリクエストで確認)

スクリーンショット 2022-06-19 18 06 00
  • コンフリクト対処順序

1. ターミナルでBブランチにてgit merge mainを行い、Aブランチの修正内容をBブランチに更新する。

gitのターミナルでは以下の様に表示される。

Auto-merging hogeファイル
CONFLICT (content): Merge conflict in hogeファイル
Automatic merge failed; fix conflicts and then commit the result.

表示された内容は、「更新したけど、hogeファイルでコンフリクトが発生してるから修正してね。」と言う内容です。

2. Bブランチのhogeファイルの内容を確認すると、コンフリクト発生箇所が以下のように表示される。

hogeファイル

あいさつの種類
①おはようございます。
<<<<<<< HEAD
②こんばんは。
=======
②こんにちは。
>>>>>>> main

HEAD側のコードはBブランチの変更内容、main側のコードは取り込まれたmainブランチの内容を表しています。

3. Bブランチのhogeファイルを正しい内容に変更する。

hogeファイル

あいさつの種類
①おはようございます。
②こんにちは。
③こんばんは。

4. ターミナルにてBブランチでgit add [hogeファイルのパス]git commit -m "コメント"を行い、Bブランチにpushする。

`[hogeファイルのパス]`が分からない場合、git merge mainを行った際の表示された内容にhogeファイルのパスがあります。

5. これでコンフリクトは解消されて、Bブランチをmergeできるようになります。

プルリクエストなどを確認した場合、mergeできる様になっている事が確認できます。

スクリーンショット 2022-06-19 18 59 36

コンフリクトを少なくするために

基盤となるブランチ(ほぼmainブランチ)が他のブランチの変更をmergeした後に、新しいブランチを作成する事を心掛けるだけで極力コンフリクトを無くすことは可能だと思います。しかし、派生したブランチの変更をmergeせずに他のブランチを作成しないといけない状況もある為、その際はコンフリクトを解消しましょう。

最後に

もっと良い対処方法や対策方法、間違っている箇所があれば、ぜひ教えていただけると嬉しいです。

読んで頂きありがとうございました。

参考記事

Ruby on Railsの環境を構築する際のNginx設定ファイルのコマンド及びコード理解

なぜ記事を書こうと思ったか

Nginx 用の設定ファイルを作成する際にコマンド及びコードの理解を備忘録として残すため。

default.confのコマンド説明

default.conf

upstream puma {
    server app:3000;
  }

server {
    listen 80;
    server_name localhost;

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

    root /app/public;

    location @puma {
      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://puma;
    }

    location / {
      try_files $uri @puma;
    }

    location ~ ^/(assets|packs)/ {
      gzip_static on;
      expires max;
      add_header Cache-Control public;
    }

    location = /favicon.ico {
      access_log off;
      log_not_found off;
    }
    
    location = /robots.txt  {
      access_log off;
      log_not_found off;
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /500.html {
    }
}

以下にコマンド及びコードの解説を致します。

  • server app:3000

upstreameでpumaグループを定義、個々のサーバーに app:3000を設定

  • listen 80

デフォルトでは、 Nginx HTTP サーバーは受信接続を待機し、標準のWebポートを表すポート 80 にバインドする。

  • server_name localhost

ホスト名を指定

  • access_log /var/log/nginx/access.log` `error_log /var/log/nginx/error.log

access_logとerror_logのパス指定

  • root /app/public

ドキュメントルートを指定

  • location

locationはURI毎に異なる設定をできるようにする

  • proxy_set_header

ロキシーサーバに送られるリクエストヘッダの フィールドを再定義、あるいは追加する。

  • proxy_pass http://puma

リクエストをHTTP プロキシされたサーバに送る

  • try_files $uri @puma

左から順に実体ファイルが存在しているかどうかを探し、あればそのままそのファイルを参照してくれる

  • gzip_static on

圧縮していない物を圧縮し、既に圧縮済みのファイル(e.g. xxx.js.gz)があればそれをそのまま配信する

  • expires max

クライアントキャッシュの有効期限設定

  • add_header Cache-Control public

下位のレベル(location)にadd_headerを設定した場合、上位のレベル(server)のadd_headerは破棄される。

拡張子 gif、jpeg、jpg、pngicosvgcss、jsのファイルをキャッシュする

  • access_log off` `log_not_found off

アクセスログ、エラーログを捨てる

  • error_page 404 /404.html

エラーページを作成する。

最後に

何か間違っている所や気になった事があれば、コメントいただけると嬉しいです。

参考記事