購入機能が本番環境で正しく動作しない時は?
カード情報を入力しても"Token can't be blank"と表示されてしまう
本番環境で公開鍵、秘密鍵ともに設定されていないことが濃厚でしょう。
ということで、早速ターミナルを見てみましょう。
まずはローカルで設定されているかどうかを改めて確認してみましょう。
# ターミナル上のコマンド MacOSがCatalina以降の場合 vim ~/.zshrc export PAYJP_SECRET_KEY='sk_test_************************' export PAYJP_PUBLIC_KEY='pk_test_************************'
環境変数は問題なく、設定されてます。
そうなると原因は本番環境に渡されていないことなので、渡します。
# 秘密鍵を設定 heroku config:set PAYJP_SECRET_KEY='sk_test_************************' # 公開鍵を設定 heroku config:set PAYJP_PUBLIC_KEY='pk_test_************************'
これで設定が終わりました。念の為、確認します。
# 環境変数を一覧で表示する heroku config # 表示結果 BASIC_AUTH_PASSWORD: ************************ BASIC_AUTH_USER: ************************ CLEARDB_DATABASE_URL: ************************ DATABASE_URL: ************************ LANG: ************************ PAYJP_PUBLIC_KEY: pk_test_************************ PAYJP_SECRET_KEY: sk_test_************************ RACK_ENV: ************************ RAILS_ENV: ************************ RAILS_LOG_TO_STDOUT: ************************ RAILS_MASTER_KEY: ************************ RAILS_SERVE_STATIC_FILES: ************************ SECRET_KEY_BASE: ************************
本番環境上でもちゃんと渡せてます。
ブラウザをリロードして、本番環境で動作確認!
"Token can't be blank"
git push heroku masterも入力したのに何で?!と思い、引き続き検索
答えは空のコミットでも良いのでGithubに上げないと反映されないとのこと。
だから、ターミナルで"Everything is up to date"と出てたのかーと納得です。
参考にしたURL
本番環境できちんと購入処理が上手くいくか調べたところ、Token can't be blankと出てしまった。空のコミットでも良いから変更を加えないとgit push heroku masterをしてもEverything is up to dateとなり上手く環境変数が本番環境で定義されない!
— Tomo (@BlackTomo26) 2020年9月26日
user_signed_in?におけるアウトプット
ログイン時とログアウト時でページの表示を変えたい
ログイン時「ユーザー名」「ログアウト」が表示
ログアウト時 「サインイン」「新規登録」が表示
deviseのgemを元々インストールしてるので.
使用できるのがuser_signed_in?となる。
上記のように入れてみた。サーバーを更新して確認してみると 必要ない点が増えてしまってる.
激しく要らないので色々試行錯誤してみたが.
結果はuser_signed_in?の位置とendの位置だった。
<ul class="lists-right"> <% if user_signed_in? %> # 記述省略 <% end %> </ul>
上記のように書き換えてみた。 求めていたデザインになりました。
「li」の中にある要素を変えたいだけだから.
「li」より外で「ul」よりも内側で使わないと正しく反映されないみたいです
deviseに関してのアウトプット
deviseとは?
ユーザー管理機能を簡単に実装するためのGem.
ログイン機能を1から構築するのが大変なため、deviseを使用して簡単に実装しよーよ!ということは私を含めてご存知な方は多いと思います。
たくさん使ってきましたが、色々と実装を進めていく中であまり理解をしていないことに気づきました。
自分でも分かりやすいように今回はまとめたいと思います。
どのような機能が実装できるか
- サインアップ機能
- サインイン機能
- アカウント編集機能
- パスワード変更機能
- メール認証機能
- アカウント凍結機能
凍結までできるのですね、これは知りませんでした。
導入手順
- gem 'devise' (Gemfileに記述)
- bundle install (ターミナルでディレクトリがdeviseを導入したいアプリで)
- rails s (インストールしたGemを反映させるため)
- rails g devise:install (deviseの設定ファイルを作成)
- rails g devise user (Userモデルを作成)
- rails db:migrate (必要なテーブルを記述してから実行)
- rails s (テーブル・カラムに変更があった場合)
- rails g devise:views
ここで意外だったのが、コントローラーは特別いらないこと。
今回実装しているアプリはコントローラーがいらなかったのです。
調べてもよく出てこなかったのですが、deviseに元々備わっている機能だけでアクションのようなものも付随しているってことなのかな。
元々備わっているもの
今回はマイグレーションファイルに関してだけの説明です。
t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: ""
マイグレーションファイルを確認すると. 既に記述がある項目の一つです。
アプリを開発する上でemailに一意性制約を用いたいと思い. Userモデルのバリデーションに記述しました。
validates :email, uniqueness true #混同しやすいですが、uniqueはマイグレーションファイルに使用
本当は他にも色々記述してますが.
このように記述をしました。
が、結論 要りませんでした。
deviseのemailには一意性制約がデフォルトであるため. 要りません。
deviseにより自動的に含まれているバリデーション
email
- 存在すること
- 一意であること
- @を含むこと
password
- 存在すること
- 6文字以上128文字以下であること
今回はモデルに記述した箇所を削除して. エラー文の重複に悩んでましたが、解決しました。
参考にしたサイト
Rubyにおけるinclude?メソッドのアウトプット
特定の値だけ検知するプログラム
配列内にChelsea, Man.C, Liverpoolが全て入ってる場合は「True」と出力.
配列内にChelsea, Man.C, Liverpoolが全て入ってない場合は「False」と出力.
雛形
def premier(tops) # 処理を記述 end
呼び出し例
premier(["Chelsea", "Man.C," "Liverpool"]) → True premier(["Arsenal", "Man.C", "Liverpool"]) → False premier(["Chelsea", "Man.U", "Man.C", "Arsenal", "Liverpool"]) → True
include?メソッド
指定した値が含まれているかを判断するメソッド.
指定した値が含まれたらtrue、含まれてなかったらfalse.
array = [1,2 ] puts array.include?(1) #=> true puts array.include?(5) #=> false
定義方法
def premier(tops) if tops.include?("Chelsea") && tops.include?("Man.C") && tops.include?("Liverpool") puts "True" else puts "False" end end premier(["Chelsea", "Man.C", "Tottenham", "Leicester", "Liverpool"])
解説
1行目のpremierメソッドの仮引数(tops)には、対象の配列["Chelsea", "Man.C", "Tottenham", "Leicester", "Liverpool"]が格納される。
2行目のif文の中には配列にChelsea, Man.C、Liverpoolが全て含まれてる場合は「Trueを出力する」という条件分岐を。
また仮引数として受け取った配列topsにChelsea, Man.C, Liverpoolが全て含まれてるかを確認するためにinclude?メソッドを使用してる。
最後に&&演算子を複数使用することで条件式の中に複数の条件を設定できる。
Herokuにおけるアウトプット1
Herokuのアウトプットであったアレやコレや
Heroku上とローカルでの差異がある
実際にHerokuに作成したWebAppを上げようとなった時にターミナル上では
git push heroku masterは無事に遂行されており、
heroku run rails db:migrateもエラーなく、完了した!さぁ、サイトのURLをクリック!
We're sorry, but something went wrong
まぁここまでは想定の範囲内です。では、ログを見てましょう。
どれどれと見てみるとindexのビューファイルがオカシイよ!と記述がありました。
考えられる方法を直してみて、再度push諸々やってアクセス!…直らない…
原因はコメントアウトか?
と思ったので、全てのファイルのコメントアウトを削除。そしてアクセス!
と思ったら、また別のエラーがあるみたいで入れない…
残りの原因は結論から言うと二つありました。
Addonsが二つある
CLEARDB_BLUE_URLが不要 DATABASE_URLが違っていた
複数あるAddonsの削除方法
HerokuのWebサイトにログインし、マイページのアプリからMetrixをクリック
どちらかを削除すればOKですが、場合によっては二つとも削除し、もう一度Addonsを追加した方が早いかも
CLEARDB_BLUE_URLとDATABASE_URLの削除
heroku config
上記のコマンドも一応念のため、入力したら出てきた新たなエラー原因
このままアンセットして削除したいと思います。
heroku config unset: CLEARDB_BLUE_URL
削除したい項目を上記のように入力すれば消えます。
そして新たにDATABASEとURLを設定したら無事にアクセス出来ました。
GitHubDesktopにおけるアウトプット 1
マスターブランチにあってトピックブランチにはないファイルがあった場合の対処法
GitHubDesktopやGitHubに慣れるためにもおもちゃ感覚で触ってます。
ここで今後よくぶち当たるであろう、事例を備忘録も兼ねて書いてみます。
例えばブランチ1で作成したモデルやコントローラーがあります。
色々コミットして、PR作成>マージ>masterに切り替えてfetch>pull
別の機能を実装する時に次のブランチ2を作ります。ここで上記で書いたpullがpushになってた場合にブランチ2を作成するとブランチ1で作成したモデルやコントローラーがテキストエディタで書けません。実在しないことになってるので。
頭を悩ましてて、色々調べてても分からなかったので聞いてみました。
解決方法は二つあります。
- ブランチ2を丸々削除する
- マスターブランチの情報をブランチ2に結合する
ある程度ブランチ2は色々と実装してたので、消したくはありません。
では、どうするのかを下記の画像を参照に。
GitHubDesktopを開きます。ブランチ1のファイルがないブランチ2を選択の状態です。
三角形の印をクリックして一番下に英語で表示されている箇所をクリック
「ブランチ2と何を結合しますか?」と聞かれるので、マスターを選択
私の場合はコンフリクトが発生してたので解決して、結合
テキストエディタを見るとブランチ1で作成してたファイルが見事にありました!
これは今後かなり役立ちそうなのと。イマイチGitHubに慣れていない自分への戒めも込めてアウトプットとして残します。
Ruby on Railsにおける記述のアウトプット2
【議題】フォームで入力したデータを送信したが、ページに反映されない。
エラー画面が出ないので、パラメーターやバリデーションの問題と考えられる
①保存する時にターミナルに出力されるログは以下
Processing by CalendarsController#create as JS Parameters: {"authenticity_token"=>"aqNYAP4QTakFCz7lLT+lSaKANNhh5Nxes+Yl/9dYGlTfa0wBc8EYEvh2voO/AOx0j2L4Bv5gvs2FOg4t0iaoQQ==", "plan"=>{"date"=>"2020-04-29", "plan"=>"aaaaa"}, "commit"=>"保存"} Completed 400 Bad Request in 7ms (ActiveRecord: 0.0ms | Allocations: 774) ActionController::ParameterMissing (param is missing or the value is empty: calendars):
- param is missing or the value is empty: calendarsというエラー文が気になる。
- callerndarsというキーのバリューが空だ、と書いてある
- またHTTPステータスコードは400が表示されてるので、リクエストが失敗している可能性もある。
calendarsというキーはどこのコードのどの部分なのか?が今回の怪しいポイントです。
②binding.pryを使って原因を追求しよう
今回の問題箇所は、Railsの基本機能の「フォームからの値を保存」処理です。
処理の流れは以下の通りです。
- form_withを利用して整理した情報をフォームからリクエストする
- リクエストを受け取ったRailsアプリは、今回はcalendars_controllerのcreateアクションを動かす
- createアクション内 Plan.create(plan_params)が動く
- 終了
binding.pryを使えば、上記の流れのどの場面でも途中で止め、その後の処理を1つ1つ確かめることが出来る。今回はcreateアクション内部にbinding.pryを記入する。
def create binding.pry Plan.create(plan_params) redirect_to action: :index end
この状態でサーバーを動かし、実際に保存を試すとbinding.pryを記入した所で止まる。
次に行われる処理がplan_paramsメソッドなので、動作が止まったコンソール上に「plan_params」を打ち込み、Enterを押す。
「paramの中は空だよー」というエラーが出てくる。
今回のエラーを解決する上で、コントローラー、モデル、ビューファイルを見てみた。
検索も兼ねて見比べてみると、コントローラーのplan_paramsが引数となっているprivateの所が怪しい…
そもそもcalendersのキーはどこにもないので、params.require.(:calenders)は誤りであること。までは分かった。
が、ここからが非常に長かった。requireの後に続くのが、plansもしくはplanの二つだろうと思ってたので入力するも値が返ってこない…
requireの記述を丸々消して、params.permit(:data, :plan)にしたら、新たなエラーが出たけど何かtrueとは返ってくる…どうしたらいいて思ってたら単なる記述ミスでした。
params.require(:plan).permit(:data, :plan)
そう、この「:」をずっと忘れてました。
そして一番初めのターミナルのエラーで何だったら答えは出てたという。
"plan"=>{"date"=>"2020-04-29", "plan"=>"aaaaa"}, "commit"=>"保存"}
エラー文を直前のではなく、もう少し上のも見るよう意識します…
ストロングパラメーターのおさらい
データを指定したものしか保存できないようにしましょーよ!というストロングパラメーター。マトリョーシカのように入れ子になってます。
params.require(:plan).permit(:data, :plan)
今回だとこんな感じ。「.」は「の」みたいな感じで解釈すると分かりやすいかも。
paramsのplanのdataとplanしか保存しないよー!てことになります。