Railsの学習(7日目)
7日目
いいね機能を搭載する
ユーザーがいいねした投稿ページを作る。
「どのユーザー」が「どの投稿」をいいねしたかを記録するために、「user_id」と「post_id」の二つのカラムを持つ「likesテーブル」を作成する。

rails g model を用いてマイグレーションファイルを作成し、準備ができたらrails db :migrateでデータベースに変更を反映させる。

いいねのデータはuser_idとpost_idの両方がないといけないので、バリデーションをかけておく。処理はpresence: trueで良い。

ログインしているユーザーがその投稿にいいねをしたか表示する。逆にいいねをしていなかったら、いいねをしていないと表示するようにする。
そのためにはログインしているユーザーがその投稿にいいねした投稿が存在するかどうか、ログインしているuser_idとpost_idが合致しているデータを、likesテーブルからfind_byを用いて探す必要がある。これをif文で書くことで、いいねしているかしていないかの条件分岐をさせる。

いいねボタンの準備
ここからいいねしたり、いいねを取り消したりできるようにする。まずはlikesコントローラを作成してLikeデータを作成するためのアクションを作成する。
今までコントローラは「rails g controller」コマンドで自動生成してきた。コマンドを用いるとビューファイルも自動生成されるが今回はビューファイルは必要ないので、今回はコントローラファイルを手動で作成する。
作り方としてはcontrollerフォルダに「likes_controller.rb」を作成することで作成される。

作成したコントローラに新たにLikeデータを作成するためにcreateアクションを作成する。createはデータベースにデータを作成するアクションなので、postで定義する。
今回はURLの部分は「どの投稿をいいねしたか」という情報を送信するために、「likes/:post_id/create」する。

これで作ったcreateアクションの中身を完成させ、そのアクションへのリンクを「いいね!」ボタンとして投稿詳細ページに表示させる。
createアクション内では新たにデータを作成後、投稿詳細ページへリダイレクトするようにする。user_idは現在ログイン中のユーザー、post_idは開いた投稿記事に応じたidにする。

作成したcreateアクションへのリンク(/likes/#{@post.id}/create)をlink_toを用いて投稿詳細ページに追加する。今までは「いいね!していません」と表示していた部分を、「いいね!」するためのリンクに書き換える。つまり「いいねしていなければ、いいね!というリンクと機能を表示するようにする」ということ。

いいね取り消しボタンを作る
いいね取り消し機能を作るにはlikesコントローラにdestroyアクションを用意する。
destroyアクションでは受け取ったログイン中のidと投稿内容のidをもとに削除すべきlikeデータを受け取り、削除する。

destroyアクションへのリンクを投稿詳細ページに追加し、今までは「いいね!済み」と表示していた部分を、「いいね!」を取り消すためのリンクに書き換えます。

Font awesomeを使っていいねボタンをアイコンにかえる
font awesomeを利用するには<head>タグがひつようになる。あとはapplication.html.erbに<link>を作って埋め込んでいく。詳しいやり方は(HTML & CSS 学習コース 中級編)

これはあくまで読み込みなので、ここから実際にアイコンに変えていく
左の図のようにHTMLを書き、show.htmlにリンクを埋め込んだが、link_toメソッド内にHTML要素を記述するとうまく反映されてくれない

この場合は<%= link_to("URL") do %>HTML要素<% end %>とすることで実行できる。

つまり2個上のハートマークを表示するコードを参考にしつつ、上の画像のやり方を応用すれば、下の画像の通りになる。要は実行したいHTML要素をlink_toメソッドで囲うということだ。

いいねの数を取得する。
いいねの数を数えるにはSQLでも用いたCOUNTメソッドを使う。これは配列の要素数を取得するメソッドだがデーブルのデータ数を取得するのにも役立つ。

いいねした投稿を表示する。
今回はユーザーに関するページを作成するのでlikeコントローラではなくusersコントローラにお気に入り投稿一覧ページを表示するためのlikesアクションを作っていく。

ルーティングのURL部分はshowアクションと同様に、どのユーザーに関する情報を表示するかを判断するために「users/:id/likes」これでこのURLでアクセスできるrootingを作成できた。そのユーザーがいいねしたページというニュアンスが伝わりやすいURLだねぇ。実際には[params:id]になると思われる。

いいね一覧のページを表示する。
viewページ用いるための変数をlikesアクション内で定義する。whereメソッドを用いてそのユーザーに関するデータをlikesテーブルから取得し、変数@likesに代入する。これでビューページで変数を使うことができる。

likesアクション内で定義した変数@userと@likesを用いて、ビューも完成させたい。各投稿を1つずつ表示するためには、@likesに対してeach文を用いて、likeに紐付いているpostを繰り返し表示させる。

Railsの学習(6日目)
ユーザーがいない場合の処理
登録されていない値でログインした場合、再度ログイン画面に戻したり、エラ〜メッセージを出したり、フォームに打ち込んだ内容を初期値として表示できるようにする。
エラーメッセージを表示するためには「find_byで検索したが見つからなかった」という結果を伝えるためのコードを書く。

続きを読む
Railsの学習(4日目)
rails4日目
削除機能を作る
ootingはpostから始める。URLから削除したい投稿を指定できるように、「posts/:id/destroy」とする。このURLにidを含める考え方は合理的で大事だね。

postとgetの違いとは?
違いは画像の通り。destroyは投稿データを削除し、更新するのでデータベースを変更していることになり、post rootingになる

destroyアクションのリンクを作る際、今まで通りに作るとpostアクションを探してしまう。

そのため、link_toの第3引数に「{method: "post"}」を追加することで、「post」として定義されているルーティングにマッチするようになる。

destroyアクション内で行う処理は以下のとおり

投稿の制限をする
空白の投稿を制限する。

不正な投稿内容が投稿されないようにチェックする仕組みをValidation(検証、実証、認可、妥当性)という。これに引っかかるとデータベースに保存がされなくなる。

Validationは図のようにモデルとして設定する。「validates」を用いてカラム名と内容を指定します。図のように{presence: true}を用いることで、「そのカラムの値が存在するかどうか」をチェックすることができます。右の画像はvalidates(検証) :content(検証するカラム名), {presence(存在感):true}で空の投稿がないかどうか検証する、となっている。

validationの詳細な指定
validationでは値が存在しているか否かだけでなく、文字数も設定できる。
図のように「length」を用い、{maximum: 数値}を指定することで、最大文字数を設定することができます。下の画像では文字の長さ、という意味になる。

validationで検証する内容はハッシュとなっているため、図のようにコンマで区切ることで複数の内容を検証することができる。

validationに引っ掛かったらもう一度入力フォームに戻る処理を行う。これにはsaveメソッドに真偽値を用いることで、validationに引っ掛かったパターンと引っかからなかったパターンを想定することができる。
例えば保存に成功したパターンをtrue, 失敗したパターンをfalseとそれぞれ返すようにするとして、rails consoleで試すと以下のようになる。

バリデーションの結果で表示するページを変える。
例えば投稿成功なら投稿一覧のページへ、失敗なら再度投稿フォームへ、というふうに設定してみる。

投稿できなかったときは投稿編集ページに飛ぶ(リダイレクトする)ようにする。保存できたときは投稿一覧ページへ飛ぶようにする。これをif文で条件分岐することで成立させる。

直前の内容を表示したまま編集ページに戻る
そもそもなぜ投稿した内容が消えてしまうのか?それは
①updateアクションでは失敗したときにeditアクションに転送しており、編集画面にリダイレクトするようになっている。
②さらにeditアクションはデータベースから編集前のデータを取得している。
③フォームの初期値は②で取得したデータにになるよう指定されている。

そしてupdateアクションの中の「params[:content]」にはpost.contentに代入するための、直前の投稿内容が入っているため、これを編集画面で呼び出すようにすれば良い。

そこで、render(差し出す)メソッドを用いることでeditアクションを経由せず、直接編集画面に表示できるようになる。
差出先は、render("フォルダ名/ファイル名")のように表示したいビューを指定する。
renderメソッドを使うと、redirect_toメソッドを使った場合と違い、そのアクション内で定義した@変数をビューでそのまま使うことがでる。プログラムの命令がどのようなルートで実行されているか、柔軟で有機的に捉えないといけないね。

このままだとユーザーに分かりづらいので、エラ〜メッセージが出るようにする。
rails consoleで流れを見てみると、保存失敗前には@post.errors.full_messagesの中に空の配列が入っており、失敗後にのなかにエラ〜メッセージが入っているのがわかる。

それをedit.html.erbのフォームの上で、each文を用いてエラー文を1つずつ表示するようにする。

サクセスメッセージの表示
ページに一度だけ表示されるメッセージをフラッシュという。
Railsではフラッシュを表示するために、特殊な変数flashが用意されている。アクションで変数flash[:notice]に文字列を代入すると、flash[:notice]をビューで使うことができます。変数flashは1度表示された後に自動で削除されるようになっています。flashはいろいろな箇所で共通で使っていくのでapplication.html.erbで表示しましょう。
下の画像で言えば、if文があるので、もしセーブしたら、表示したい文字列をフラッシュとして表示する、という意味である。

Railsの学習(2日目)
今日も頑張ろう
自動生成されるidカラム
idカラムはデータベースにデータが保存されるときに自動で入れられる。

created_atカラムとupdated_atカラムも、データベースに保存された時刻が自動で入るようになっている。
updated_atは名前のとおりデータ更新した時にも時刻が更新される。つまりcontentカラム以外自動挿入である。

find_byメソッド〜データベースから特定のidのデータを取得する。〜
特定のidを取得するには「find_by」を使う。
名前のように「〜から見つけてくる」という意味になるので、図のように、「モデル名.find_by(カラム名: 値)」と見つけてくる場所を指定してあげることで、その値を持ったデータをデータベースから取得することができる。

投稿詳細ページを作る
ルーティングのURL部分に「:」を用いて「posts/:id」と指定することで、「/posts/1」でも「/posts/2」でもshowアクションにいくようにすることができる。
「posts/:id」と書くと「/posts/◯◯」のような全てのURLが該当する。
こうすることで同じようなコードの繰り返しをせずに済むようになる。

「posts/:id」というルーティングは「posts/index」より下に書かなければいけない。
ルーティングは合致するURLを上から順に探すため、「posts/index」よりも上に書くと、「posts/:id」が、「localhost:3000/posts/index」という「posts/index」と合致させるためのアクションと合致してしまう。

controllerのaction内ではrootingで設定したURLと:idの値を取得することができるが、その値はparamsという変数にハッシュとして入っている。(1を設定したら1が取得できるということ?)
そのため、params[:id]とすることで、その値を取得することができる。アクションファイル内設定したファイルをviewファイルでは使うことができないので、「@」付けてviewファイルに渡してあげるのを忘れないように。

showアクションで変数@postを定義し、idカラムの値がparams[:id]と等しい投稿をデータベースから取得して代入します(つまり下の画像で言えば id: params[:id])がそれである。テーブルのidはURLのidと同じということになる。)
@postをshow.html.erbで表示することで、各URLに対応した投稿のデータが表示されるようにしましょう!

詳細ページへのリンクを作成する。

入力フォームの作成
HTMLのコマンドである<textarea>タグや<input>タグを用いることで入力フォームを作成することができる。
送信ボタンにはtype="submit"と、value="投稿"を指定する。

投稿を保存する。
投稿データを保存するにはcreateアクション用意することでデータベースに保存できる。下の画像で言えばpostsデータを保存する場所をcreateしろと命令してるイメージだろうか。

createアクションのrooting
これまでアクションを作成するときは「get」を用いてきたが、投稿のアクションを作るには「post」を用意する必要がある。これはクラス名のPostには一切関係ない。「そういうもの」、である。

フォームの申請先を指定する。
「form_tag」を用いることでフォームに入力されたデータを保存することができる。form_tagは、「form_tag(送信先のURL) do」のように送信先のURLを指定する。
これにより、投稿ボタンを押すことで指定されたURL(この画像では/posts/create)にデータが保存される。

createアクションではビューを用意する代わりに、リダイレクトという、他のURLに転送する機能を用いる。

リダイレクトを実行するには「redirect_to("URL")」コマンドが必要になる。これにより指定したURLに転送することができる。

しかしこの状態ではリダイレクトはしていても、データベースへの保存はできていない。そこで、<textarea>タグにname属性を指定すると、入力データを送信することができるようになり、name属性の値をキーとしたハッシュがRails側に送られるようになる。

以下の図のように、Postインスタンスを作成する際にparams[:content]を用いる。そのPostインスタンスを保存することで投稿機能が完成する。

orderメソッド
orderメソッドを用いることで、投稿一覧を並び替えることができる。
order(カラム名: 並び替えの順序)のように使います。並び替えの順序には、昇順(:asc)と降順(:desc)のどちらかを指定できる。
created_atを基準に降順(:desc)に並べ替えると、新しいものから順番に表示するようになる。この辺りはSQLと似ている。




