テックキャンプ 最終課題まとめます

最終課題が終わったので、ミスした点を振り返りながら再発を防ぎます。

細かいコードの記述などは致しません。あくまで自身用の復習の為に羅列していく形式ですので、実際にどういうコードを記述するかはこの内容をヒントに別の方の記事で確認をお願い致します。

 

テックキャンプ の最終課題ではメルカリクローンのようなアプリケーションを実装しました。以下復習点羅列。

 

ER図、README

・DBに保存できないクレジット情報、deviseに標準設定されているパスワードはカラム作成不要。

・画像登録にActiveStrageを使用する場合はimageカラムも不要。

・1対1のアソシエーション(投稿商品と購入データ、等)は親にhas_one、子にbelongs_to

・重要なのは、ここで作成した設計図は完全では無いということ。実装に関してはこのER図に固執するのではなく、都度修正しながら作っていくのが重要。しかし、全体像はここで考えておく。

 

ユーザー登録

・deviseを導入するとモデルやコントローラの作成が若干変わる。rails g devise 名前、等。

・registrationは新規登録、sessionはログイン、サインアップは新規登録、サインインはログイン、意外とこんがらがる。

・バリデーション等がdeviseでどこまで標準装備されているか確認しておく。

・deviseでコントローラは基本的にいじらない。application_controllerにストロングパラメーターの設定をする。

・ルーティング時にスコープを設定する。

devise_scope :users do
get '/users', to: redirect("/users/sign_up")
end

・テストコード時、Eメールの重複をチェック

it "emailが重複する場合登録できないこと" do
@user.save
another_user = FactoryBot.build(:user, email: @user.email)
another_user.valid?
expect(another_user.errors.full_messages).to include("Email has already been taken")
end

 

商品出品機能

・form_withの使い方として、モデルを指定した場合は、データの受け手のストロングパラメータの設定時、requireでモデルを紐づける。個人的に変数をviewに反映させる、部分テンプレートでデータの数だけ表示させるみたいな処理はこの形式の方がやりやすいので基本はこの形で設定することにしている。また、モデルを指定する場合はURLの指定がいらない。

・form_withでデータを入力する時点で、変数にデータが入っていればedit、入っていない空のインスタンスであればcreateアクションを呼び出す。

・userと紐づけるので、アソシエーションと、ストロングパラーメータのmergeを忘れない。

・エラーメッセージの出力は部分テンプレートをform_withのオブジェクトと結び付けて発動できるよう設定する。

都道府県等の変更が発生しないデータ、はカラム名のモデルを作成し、ActiveHashを設定する。

class Postage < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
{ id: 2, name: '着払い(購入者負担)' },
{ id: 3, name: '送料込み(出品者負担)' }
]
end

基本はHTMLでcollection_selectと合わせてプルダウンの選択式にする。

<%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"select-box"

そもそものカラム名はこれらのIDを取得できるように設定しておく。

・同じバリデーションを複数のカラムに設定する場合、with_optionsで纏める。

with_options presence: true do
validates :category_id, numericality: { other_than: 1,
message: "must be other than --"}
validates :condition_id, numericality: { other_than: 1,
message: "must be other than --"}

・テストコード、ActiveStorageを使っている場合は、Fakerを使用できない。after

buildで指定の画像を指定する。

after(:build) do |item|
item.image.attach(io: File.open('app/assets/images/item-sample.png'),
filename: 'item-sample.png')

 

商品一覧表示機能

・個人的には部分テンプレート、collectionオプションで変数を利用するやり方がわかりやすい。eachで繰り返し処理をすることもできるが、記述が長くなる。

 

商品編集・削除機能

・どのユーザーならそのページに行けるかという条件分岐を設定する。また、そのような条件分岐は基本的にbefore_actionでまとめておく。

・移動先のパスとmethodに注意する。railsroutesで確認。パスの記述方法は全体で統一する。prefixがないやつはただ省略されているだけ。

<%= link_to '商品の編集', edit_item_path(@item.id), method: :get, class: "item-red-btn" %>
<p class='or-text'>or</p>
<%= link_to '削除',item_path(@item.id), method: :delete, class:'item-destroy' %>

・編集がうまく行った場合といかなかった場合の処理を指定する。redirect_to、renderの違いを意識する。redirect_toではインスタンスが空になってしまう為、ページを再編集に指定しても入力データが反映されないのでエラーメッセージが出せない。

 

商品購入機能

・一つのフォームで複数のテーブルにデータを保存したい場合はフォームオブジェクトを利用する。これをしないと入力ミスがあった際に個別のエラーメッセージの出力等ができない。具体的には、自身でActiveModelを作成してそこにクラスを定義、

①attr_accessorでカラムに保存する要素を全て使用できるように設定、

②バリデーションを定義

③saveメソッドを定義して各テーブルにデータを保存する処理を定義。

複数のテーブルにアソシエーションがある場合は、saveメソッドの処理の順番を注意する。親テーブルのデータをcreate,それを変数定義し親テーブルのIDを取得するような記述の仕方が必要。

④コントローラでストロングパラメータのフォームオブジェクトモデルをrequireする。

⑤createアクションに入ってsaveメソッドが実行される時、フォームオブジェクトの設定が反映される。

フォームオブジェクト内の記述はエラーにならない。データが保存されない等の時は、saveメソッド内のcreateアクションにcreate!と入れるとなぜcreateできないかエラーメッセージが表示される。

def save
@purchase = Purchase.create(user_id: user_id, item_id: item_id)
Address.create(purchase_id: @purchase.id, post_number: post_number,
prefecture_id: prefecture_id, city: city, house_number: house_number,
building_name: building_name, phone_number: phone_number)
end

 

 

クレジット機能

railsの入力フォームの送信処理をキャンセルする記述をjsに記述

②jsにフォーム送信がされた時にカード情報をHTMLより取得、それを暗号化(トークンの作成)、公開鍵に取得と設定、をする記述

トークンの情報を取得できるようHTMLにInsertHtmlでHTMLにinput要素を嵌め込む。その際、実際に表示しないようhidden属性を適用する。

④カード情報を残さないように、removeする処理を記述。

railsのコントローラーにPAY.JPに秘密鍵の作成、トークンと価格の情報をストロングパラメータに入れ込む記述。

⑥PAY.JPに購入データがうまく反映されてれば、環境変数を設定。

herokumasterを行う。

・公開鍵、秘密鍵は機密情報。js、rails上の記述も暗号化しておく。

Payjp.api_key = ENV["PAYJP_SECRET_KEY"]

・カード情報も機密情報、直接カード番号等をテーブルに保存する、ストロングパタメータに入れ込むような設定は違法。

・Jsはrails上ではエラーが確認できないので、検証ツール、debuggerを使用する。

 

本番環境における設定エラー

・画像のエラー解消の為にはDBのリセットが必要な場合が。

`% heroku run DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop db:create db:migrate`

 

・herokuエラーが発生する場合は、ログを確認する。

2020-10-24T02:16:56.252945+00:00 app[web.1]: [fb36fcf1-76b4-4c7e-9179-eeacaedebd95]

2020-10-24T02:16:56.252946+00:00 app[web.1]: [fb36fcf1-76b4-4c7e-9179-eeacaedebd95] ActionView::Template::Error (Mysql2::Error: Table 'heroku_f5d134c0865131d.purchases' doesn't exist):

自身の場合は、マイグレーションファイルを右クリック削除してしまったことで、エラーが発生。

bundle exec rake db:migrate:status

マイグレーションファイルの状態を確認、

Status   Migration ID    Migration Name

--------------------------------------------------

   up     20201015102415  Devise create users

   up     20201016071057  ********** NO FILE **********

NO FILEとなっているのは、ターミナル上はデータが残っているのに、rails上は削除されている状態。これがエラーの原因。

 

これの修正としては、このファイルをdownにして、コマンドで削除する。それで削除できない場合は、

rails db:migrate:reset

で一旦データベースを全て白紙にして、再度rails上に残っているマイグレーションファイルでマイグレートする。何回も誤って消してしまった場合はこちらでもいいかもしれません。この辺は他の方の記事の確認をお願い致します。ちなみに、herokuマスターでrubyを最新版にするとか、procfileがないよとか、webpackが最新じゃないよ、とか出てましたがこれは無視してもこのアプリの動作には問題ありませんでした。基本的には、まずログを確認する事が重要です。