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を押す。
こうすることで、コンテナから出ることができます。もし、exit
やcontorol + c
をした場合は、サーバーも停止されます。
3.binding.pry`を削除します。
最後に
自分は、logger.debug
やログで動作状況を確認していたので、このデバッグ方法は非常に便利に感じました。是非、やった事がない方はやってみる事をお勧めします。もし、もっと良いデバッグ方法がある場合は、コメントで教えていただけると嬉しいです。読んで頂きありがとうございました。
webサーバーとアプリケーションサーバーの違いについて
なぜ記事を書こうと思ったか
アプリケーションサーバーとWebサーバーについての明確な違いと例えば、どのような種類があるか調べた為、備忘録としてまとめる。
webサーバーとアプリケションサーバーの説明
ユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムです。そして、場合によってはあなたのRailsアプリケーションにリクエストを投げます。SSLリクエストや静的なファイルやアセット、圧縮されたリクエスト等を処理したり、その他大半のwebサイトが必要としそうな数多くの処理をこなしたりすることができます。もし、Railsアプリケーションがリクエストを処理しなければならない場合は、webサーバーはリクエストをアプリケーションサーバーにパスします。
複数のアプリケーションを一度に処理したり、アセットを素早くレンダリングしたり、リクエストごとに発生する多くの処理をさばいたりしてくれます。
- アプリケーションサーバー(例:Unicorn、Thin、Rainbows、Mongrel)
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アプリケーションの直接のレスポンス以外の構成要素のことを指します。Javascript、CSS、画像などがこれにあたります。
- 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から実装されました。利用することで、たとえばリアルタイムで更新されるチャット機能を実装することができます。
- config.action_cable.url = 'wss://example.com/cable'
Cableサーバを決めたら、ServerのURLをclientサイドに提供する必要がある。Action CableサーバーがホストされているURLを文字列で指定します。Action Cableサーバーがメインのアプリケーションと別になっている場合に使う可能性があります。View側に action_cable_meta_tag を書く。
- config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
指定されていない送信元からのリクエストを受け付けません。送信元リストは、配列の形でサーバー設定に渡します。送信元リストには文字列のインスタンスや正規表現を利用でき、これに対して一致するかどうかがチェックされます。
- 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のインスタンスが指定されます。
- ActiveSupport::Logger.new(STDOUT)
標準出力用の Logger オブジェクトを作成する。
- config.active_record.dump_schema_after_migration = false
マイグレーション実行時にスキーマダンプ(db/schema.rbまたはdb/structure.sql)を行なうかどうかを指定
スキーマダンプとは、スキーマを抽出する。db/schema.rb の作成
最後に
間違っている箇所やわからない箇所があれば、ぜひコメントしていただけると嬉しいです。
読んで頂きありがとうございました。
参考資料
- Rails 5でconfig.cache_classes = falseにしているとメモリリークする
- Railsの config.eager_load はModelやControllerを読み込むタイミングを制御できる
- エラー情報をブラウザに表示をするかの設定
- コントローラのキャッシュ設定するかの設定
- Railsガイド:Rails アプリケーションを設定する
- Rails Assetの管理についてまとめる
- X-Accel
- Active Storage の概要
- Action Cableでできることと実装方法
- Action Cable の概要
- Railsのログを理解する-ログの基礎知識-
- 調査しやすくするためログにリクエストIDを入れましょう
- Rails のキャッシュ機構
- resque/resque
- プレフィックス 【prefix】 プリフィックス / 接頭辞
- Railsのキャッシュ(cache)について
- Action Mailer の基礎
- ActionMailerのSMTP設定を動的に変更する
- HEADS UP! i18n 1.1 changed fallbacks to exclude default locale. But that may break your application.
- module ActiveSupport::Deprecation::Behavior
- Logger のログファイルへの出力を標準出力にも出力したい
- pg_dump
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を生成する。
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に値が入っている事を確認後、:q
でvimを閉じる。
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に変更する。
上記の手順で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をクリックし、インストールを押して下さい。
- 使い方
1.拡張機能のマークの下に新しい雷のマークがあるので、クリックして下さい。
2.「New Request」を押して下さい。
3.検索バーの下にあるHeaderタブをクリックして下さい。
4.「Raw」のチェックマークにチェックマークを入れて下さい。
5.HttpHeadersにいらない情報がある為、全て削除して下さい。
6.HttpHeaderにcookieの値やX-CSRFtokenなど必要情報を入力して下さい。
もしわからない場合は、API通信できているか確認したいURLに関連するURLをグーグルで表示し、デベロッパーツールを開いて下さい。
「Network」タブを開き、⌘+Rを押し、RequestHeaderの中身を全てコピーして下さい。
7.コピーした内容をThunderClientのHttpHeaderに貼り付け、検索バーにURLを入力後、Sendをクリックして下さい。
その後、ステータスコードなどが表示されます。
最後に
間違っている箇所があれば、ぜひ教えていただけると嬉しいです。
読んで頂きありがとうございました。
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のプルリクエストで確認)
- コンフリクト対処順序
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できる様になっている事が確認できます。
コンフリクトを少なくするために
基盤となるブランチ(ほぼ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、png、ico、svg、css、jsのファイルをキャッシュする
access_log off` `log_not_found off
アクセスログ、エラーログを捨てる
error_page 404 /404.html
エラーページを作成する。
最後に
何か間違っている所や気になった事があれば、コメントいただけると嬉しいです。
参考記事