基本的なRailsの文法

## はじめに

ドットインストールにてRailsを勉強しているのですが、知識を記憶に定着させるため、学んだこと、調べたこと、自分で考えたことなどを書いていきます。
何かご指摘があれば教えていただければ幸いです！

## 環境

Ruby: 2.6.5p114
Rails: 5.1.7
教材内のバージョンに合わせました。

## ログファイルの場所

```ruby
log/development.log
```

## モデル作成

```:zsh
rails g model Post title:string body:text
```

Modelは個々のデータ構造を定義するので、Postのように単数形になる。

上記を実行した後、いろいろなファイルが作成され、今作ったデータの構造をデータベースに反映させるには、下記を実行する。

```:zsh
rails db:migrate
```

## データベースを使う

```:zsh
rails dbconsole # rails dbと省略できる
.tables # 存在するテーブルを見る
```

## 初期データの流し込み

rails cを使って手入力で初期データを入れるのではなく、ファイルで初期データを管理する。

```:db/seeds.rb
5.times do |i|
	Post.create(title: "title #{i}", body: "body #{i}")
end
```

その後、下記を実行することにより、上記の内容をデータベースに流し込める。

```:zsh
rails db:seed
```

## テーブルの中身の削除

```:zsh
rails db:migrate:reset
```

テーブルの中身を削除し、また新しく作り直す。

## コントローラー作成

```:zsh
rails g controller Posts
```

Controllerでは複数のデータを扱うので、Postsと複数形になる。

## ルーティング

どのURLにアクセスされた時に、controllerのどのメソッドを実行するかを設定することをルーティングと呼ぶ。

```config/routes.rb
Rails.application.routes.draw do
	resources: posts
end
```

一般的な処理を一度に設定するならばresouces: postsと書く。

```:bash
rails routes
```

これで、設定されたルーティングを一覧で確認できる。

## Viewの作成

app/views/postsの中にViewファイルを作成する。

```index.html.erb
<% @posts.each do |post| %>
	<li><%= post.title %></li>
<% end %>
```

\<% %>の中にRubyの命令を書き込むことができる。
Rubyの命令を埋め込むときに、アクションの中で設定したインスタンス変数を使うことができる。

## rootパスの設定

```routes.rb
Rails.application.routes.draw do
  resources :posts

  root "posts#index" # 追加
end
```

rails routesコマンドで確認するとroot GET     /         posts#indexとなっており、postsコントローラーのindexアクションがルートに設定されていることがわかる。

## link_toヘルパー

Viewで使える命令をヘルパーと呼ぶ。

```ruby
<ul>
<% @posts.each do |post| %>
  <li>
  <%= link_to post.title, post_path(post) %>
  </li>
<% end %>
</ul>
```
link_toはリンクを生成する命令。htmlのaタグと同じ。
上記では、post.titleを表示させて、そこにpost_path(post)のリンクを付けている。
post_pathはrails routesで表示させるPrefix Verbに_pathをつけたものになる。
今回だと個別のpostの詳細を表示させたいので、postsコントローラーのshowアクションが実行させるため、post_pathにidをつける必要がある。よって、post_path(post.id)とする。.idは省略してもRailsがうまく解釈してくれるので、post_path(post)となる。

## フォームヘルパー

Railsガイドによると、

[レイアウトとレンダリング](https://railsguides.jp/layouts_and_rendering.html)

> フォームのマークアップは、フォームのコントロールの命名法や大量の属性を扱わなければならず、作成もメンテナンスも退屈な作業になりがちです。そこでRailsでは、フォームのマークアップを生成するビューヘルパーを提供し、こうした煩雑な作業を行わずに済むようにしました。
> 

とのこと。
自分なりに説明すると、フォームヘルパーを使うとformタグを使わずに簡単にフォームを作成できます。

```ruby
<%= form_for :post, url: posts_path do |f| %>
<p>
  <%= f.text_field :title, placeholder: 'enter title' %>
</p>
<p>
  <%= f.text_area :body, placeholder: 'enter body text' %>
</p>
<p>
  <%= f.submit value: 'Save' %>
</p>
<% end %>
```

\<%= form_for :post, url: posts_path do |f| %>の:postはpostモデルに対するフォームということを示す。urlはhtmlのformタグで言うと、action属性に対応し、送信先を指定する。最後にdo |f|とすることで、input[type=”text”]と書くところを、f.text_fieldのように簡単に書くことができるようになる。

## Strong Parameter

```posts_controller.rb
class PostsController < ApplicationController
  def def new
  end

  def create
    @post = Post.new(post_params)
    @post.save
    redirect_to posts_path
  end

  private

    def post_params
      params.require(:post).permit(:title, :body)
    end
  
end
```

送られてきたデータをparams[:post]で受け取り@post = Post.new(params[:post])の後、@post.saveでデータを登録できそうだが、できない。これは、送られてきたデータの中に悪意があるのものを防ぐため。実際にデータを登録するためには、params.require(:post).permit(:title, body)のように書いてデータを受け取る必要がある。これは、postをキーにして、titleとbodyがあるハッシュでないといけない、という意味になる。

## バリデーション

```app/models/post.rb
class Post < ApplicationRecord
  validates :title, presence: true, length: { minimum: 3, message: 'Too short to post!' }
  validates :body, presence: true
end
```

presence: trueと書くことにより、入力が必須となる。
legnth:により、文字数制限もつけることができる。


## renderメソッドとredirect_toメソッドの違い

### renderメソッド

Railsガイドによると、

> 同じコントローラから、デフォルト以外のテンプレートに対応するビューをレンダリングしたい場合は、`render`メソッドでビュー名を指定できます。
> 

と説明されています。また、

> Railsのコントローラは、デフォルトでは正しいルーティングに対応する名前を持つビューを自動的に選択し、それを使ってレスポンスをレンダリングします。
> 

> 「コントローラのアクションの末尾で明示的にレンダリングが指示されていない場合は、コントローラが利用可能なビューのパスから`アクション名.html.erb`というビューテンプレートを探し、それを使って自動的にレンダリングする」というルールが適用されます。
> 

とのことです。

つまり、今回のpostコントローラーのnewアクションで考えると、明示的にrenderを記載していないため、自動的にnew.html.erbというビューテンプレートを探し、自動的にレンダリングしているということになります。

createアクションの場合、受け取った値がvalidationに引っかかっていた場合は再度入力し直して欲しいため、render ‘new’としていたということが分かりました。

### redirect_toメソッド

Railsガイドでは以下のように説明されていました。

> `redirect_to`メソッドは、別のURLにリクエストを再送信するようブラウザに指示します。
> 

> `redirect_to`を呼び出すと、一時的なリダイレクトを意味する[HTTPステータスコード302](https://developer.mozilla.org/ja/docs/Web/HTTP/Status/302)
がブラウザに返され、ブラウザはそれに基いてリダイレクトを行います。
> 

redirect_toの後に記載するURLに対してHTTP GETリクエストを送っていると思います。

renderメソッドとredirect_toメソッドについて、それぞれがどういう定義なのかは調べて分かりましたが、今いち使い分け方が分からなかったのですが、以下の記事がとても分かりやすかったです。

[【Rails】renderとredirect_toの違いと使い分け](https://qiita.com/morikuma709/items/e9146465df2d8a094d78)

renderはvalidation等に引っかかっていたり、パスワードが違ったりした場合に使う。
redirect_toは、データの更新や削除、input、formなどでデータを送る処理に使う。

## 参考記事

- [Ruby on Rails 5入門](https://dotinstall.com/lessons/basic_rails_v3)
- [【Rails】renderとredirect_toの違いと使い分け](https://qiita.com/morikuma709/items/e9146465df2d8a094d78)

- [レイアウトとレンダリング](https://railsguides.jp/layouts_and_rendering.html)