アウトプット12/18

<今日のカリキュラム>

・最終課題の購入機能実装

 ようやくLGTMがでてデプロイ完了!達成要件も満たしているようなので、課題提出。

長かった。。

 

<問題解決など>

・form_withについて

 記述におけるモデル設定は、indexアクションでも定義をしないと駄目!
 ↑今週の最大の気付き。まじでメンターさんに感謝。

・jsでトークンが生成されない

 検証ツールのelementsを見れば一発。FormDataの理解が薄かった。

・ログインして以内ユーザーの制限

 わざわざ自分で定義してbefore_actionしなくでも

before_action :authenticate_user!

 で一発。

・URL直打ち禁止

qiita.com

まずdevise_parameter_sanitizerメソッドは完全に忘れてた。

→deviseのUserモデルに関わる「ログイン」「新規登録」などのリクエストからパラメーターを取得すること。application_controller.rbに記載。

 

購入者=出品者のときはトップページにリダイレクトしてほしいので、

def correct_consumer
item = Item.find(params[:item_id])
unless current_user.id == item.user_id
redirect_to root_path
end
end

と記述。

ログインしていないユーザーはbefore_action :authenticate_user!で弾かれているのでオッケー。

最後に売り切れている商品購入ページにも現状ではURL直打ちでアクセスできてしまうので、商品に紐ついている注文テーブルidが存在している場合にもトップページにリダイレクトするようにした。

def move_to_index
if current_user.id == @item.user_id
redirect_to root_path
elsif @item.consumer != nil
redirect_to root_path
end
end

 

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

モデル名.find(params[:レコード名])について

指定したモデル名から、任意のカラム名を引き出すメソッド。レコード名が:idであればそのidのレコード情報を返すことになる。取り出したレコード情報を編集したり、削除したりするのでupdateやdestroyで定義することが多い。

何度も定義するのは無駄なので、

def set_item
@item = Item.find(params[:id])
end

のようにまとめて、before_actionに設定する。

 

<理解していないこと>

・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上に持ってくるために使用する。