アウトプット12/6

<今日のカリキュラム>

・最終課題の購入機能(テーブル保存)

・1つのフォームからの複数のテーブル保存のアプリ実践

 

<問題解決など>

・1つのビューから複数のテーブルに保存する。

 色々問題が生じて超苦戦した。。

①Formオブジェクトパターンへのparamsを飛ばす。

 →この飛ばし方が引っかかった。注文テーブルは商品とユーザーにルーティングされているだけのカラムなので、配送住所テーブルのカラムと紐付けがわからなかった。

結論としては、商品カラムはネストされているので自動で紐付けが行われており、ユーザーはmergeメソッドでの紐付けを行えば良かった。(pictweetのコメント実装で同じことをしていたのに全くわからなかった!!)

 

②Formオブジェクトパターンにて、飛ばされてきたparamsをモデルとして規定する。

「ActiveModel::Model」←ここ飛ばれされてきた情報を規定することが大切。

 

③バリデーションもFormオブジェクトパターンにて記述。

 

④ここで、2つのテーブルに保存する内容を記述をする。

 →今回は、Formオブジェクトパターンで最初に保存した注文テーブルからルーティングされている配送住所テーブルにidを飛ばさなければならなかったので、注文テーブルの保存を定義付けし、その上で配送先テーブルの保存する際に「consumer_id: consumer.id」と記述する必要があった。当然記述の順番も注文→配送住所とする必要があった。

・attr_accessor

モデルに対応するテーブルのカラム名以外の属性を使用したいときは、attr_accessorメソッドを使って追加することができる。

他テーブルに情報を追加するときにも使える。

・numericalityとformatの違い

numericalityは数値に関するバリデーションで、オプションによって色々な成約をつけることができる。

整数のみ:「only_integer: true

特定の数値以外:「other_than: 0」

範囲指定:「greater_than_or_equal_to: 1, less_than_or_equal_to: 1000000」

 

 

<分かっていなかったこと> 

・ルーティングのネスト(3回目!!)

商品購入は、その商品に対するconsumerなのかをパスから判断する必要がある。

モデルと結びついている別のモデルのid情報を送る必要がある。

パスの親子関係を表現できる。

Rails.application.routes.draw do
  resources :親となるコントローラー do
    resources :子となるコントローラー
  end
end

 

<理解していないこと>

・have_selector,have_contentの違い

 指定したセレクタがあるかないかを判断するマッチャがhave_selector。have_contentは指定した文字列があるかどうかを判断するマッチャ。

・sliceメソッドとslice!メソッド

 array.slice(1) →配列の中から1番目の数値を取り出す。但し配列に影響はない。

 array.slice!(1) →配列の中から1番目の数値を取り出す。取り出した数値は配列から削除される。

・afterメソッド 

 任意の処理の後に指定の処理を実行するメソッド。テストコードでFactoryBot後に画像を保存するコードを作るときなどに使用する。

・DOM

 ドキュメントオブジェクトモデルのこと。 HTMLを解析し、データを作成する仕組み。JavaScriptではHTMLを階層として捉えて変換したデータと捉え、そのHTMLの階層を取得し、操作することでプログラムを動かす言語。

XMLHttpRequest

 javascriptからAjaxによるリクエストを送るためのオブジェクトのこと。

・renderメソッド

 JSON形式でデータをサーバーから返却する際には、

 render json:{ post: post}

 とcreate定義に記載する。

・onload

 XMLHttpRequestで定義されているプロパティで、レスポンスの受信が成功した場合に呼び出されるイベントハンドラーのこと。

 ・セッションとクッキー

  webサービスにおいて情報を一時的に保存しておく仕組み。セッションがハッシュの形式でクッキーという保存場所に保存される。

・case文

 ifを使わない条件分岐

case 対象のオブジェクトや式
when 値1
 # 値1に一致する場合に実行する処理
when 値2
 # 値2に一致する場合に実行する処理
else
 # どれにも一致しない場合に実行する処理
end

・whereメソッドとLIKE句

「c」が含まれるタイトルの検索方法は、

 where('title LIKE(?)', "%c%")

 検索機能の実装で使うメソッドでモデルに記述する。

 

・heroku addons:add cleardb

 herokuのデフォルトデータベースはPostgreSQLというデータベースなのでMySQLに変更するため

・テーブルの型

 生年月日はdate型で保存。

 長い文章はtext型。

 金額などの数値はinteger型。

・Active Storage

 ファイルアップデートを簡単に実装できるGem。画像を保存するテーブルは自動で形成されるので自分でテーブルを作る必要はなし。

・utf8

 database.ymlにはデフォルトで「utf8mb4」でデータサイズに制限がかかっているので「utf8」に変更する。

・devise

 パスワードの6文字制限はデフォルトで実装されているのでバリデーションでlengthを定義する必要はなし。

・文字列変換

 .to_i→数値変換、.to_s→文字列変換

参考)chompメソッドは、文字列が使用できるメソッド。
chompメソッドを使用すると、文字列の末尾に存在する改行を取り除いた文字列を返してくれます。

・正常系・異常系テストコードは分けて記載する。 

 

**2重ハッシュの取り出し方**

user_data = [
{user: {profile: {name: 'George'}}},
{user: {profile: {name: 'Alice'}}},
{user: {profile: {name: 'Taro'}}},
]
この配列からnameキーだけを取り出したいときの方法。

[:user][:profile][:name]
この二重ハッシュだけではエラーが出る。なぜなら配列の中に複数のハッシュが格納されているので、これだけだとどのハッシュから取り出すのかが指示されていないのでエラーとなる。

配列の中に複数のハッシュがある場合には、each文を使って上述の二重ハッシュを各ハッシュで適用する以下の指示を行う必要がある。

user_data.each do |u|
puts u[:user][:profile][:name]
end

**herokuエラー**

ローカル環境では投稿ができていたのに、デプロイを行ったらエラーがでてしまう状況になってしまった。

色々苦戦したけれど、内容としては

*マイグレーションファイルの順番が違った*

ということ。itemテーブルにuserが紐ついているのに、ファイルの順番が、item user active_storage だったのでエラーが発生。順番は、~~item~~ user item  active_storage が正しかった模様。なぜかローカル環境ではうまく行ってので気が付かなかった。

マイグレーションファイルの順番を正しくした上で、

```

rails db:migrate:reset

```

を行うことで修正できた。

ちなみにメンターさんに教えてもらったheroku上でマイグレーションをリセットするコマンドは以下。

heroku run rails db:migrate:reset REILS_ENV=prodction DISABLE_DATABASE_ENVIRONMENT_CHECK=1

・ クラスメソッドとインスタンスメソッド

 クラスメソッド;個別の情報によらず共通の結果を返す動作を定義するメソッド

class クラス名
  def self.メソッド名
    # 処理
  end
end

 呼び出し方は次の通り。

クラス名.メソッド名(引数) 

 インスタンス変数

定義は以下の通り。

class クラス名
  def メソッド名
    @変数名 =   # インスタンス変数
  end
end

@をつけるインスタンス変数の特徴は、おなじクラス間であれば利用できること。@をつけないローカル変数は定義してあるインスタンスメソッド内(def~end)でしか利用できない。

つまり、クラスメソッドを使って引数を渡したいときにはインスタンス変数を使って利用できる範囲を広くしておかないといけないということ。

なお、インスタンス変数はクラスが呼ばれるたびに実行するため、initializeメソッドを定義するのが一般的。

イメージはこんな感じ。

class クラス名
  def initialize
    # インスタンス生成したときに実行される処理(以下は例)
    puts "クラス名のインスタンスが生成されました"
  end
end

インスタンス = クラス名.new  # initializeメソッドが呼ばれ文字が表示される

・.orderメソッド

 コントローラーのindex定義に記載することが多い。定義したモデルのテーブルのカラムをどの順で表示するかを決めることができる。

通常のアプリは新しい投稿が上に来るようにするので、その場合にはDESC(降順)、逆にしたいときはASC(昇順)。

インスタンス = モデル名.order("並び替えの基準となるカラム名 並び順")

Javascript:e.preventDefault();

 通常のRuby on Railsにおける処理をキャンセルする記述。JSに置き換えるときに使う方法。このままだとキャンセルされたままなので、JSファイルで最後の記述は記載する。

Javascript:FormData

 フォームに入力された値を取得できるオブジェクトのこと。
new FormData(フォームの要素);のように、オブジェクトを生成し、引数にフォームの要素を渡すことで、そのフォームに入力された値を取得する。

ブラウザ上の投稿などのフォームに入力された情報を非同期通信で送信する必要には、投稿情報をJS上に持ってくるために使用する。

 

<気付き>

実装につまづく→学習が億劫になるの悪循環。

だけどなんとか複数テーブルへの保存までできたので良しとしよう!

明日からはpayjpの実装でまずは全体的を掴むことを優先しよう。テストコードとかは最後にやろう。