Rails 基礎

## ルーティング

### 名前付きルート
以下のようなルート定義があった場合、名前付きルート **help_path** と **help_url** が自動的に使用できるようになる。
名前付きルートは、ルートのパスやURLが変更されても自動的に更新されるため、リンクを生成する際に非常に便利。
```ruby:route.rb
Rails.application.routes.draw do
  root 'static_pages#home'
  get  '/help',    to: 'static_pages#help'
end
```

```erb:.erb
# ビューやコントローラー内で名前付きルートを使用する例
<%= link_to 'Help', help_path %>

# フルURLを取得する場合は help_url 
<%= link_to 'Help', help_url %>
```

### 基本的なルートの書き方
```ruby:route.rb
Rails.application.routes.draw do
  # indexアクションとshowアクションだけを指定(参照のみの画面など)
  resources :tweets, only: [:index, :snow]
end
```

- `resources`
resourcesを使ってリソースを定義することができます。resourcesを使うと、RESTfulなルーティングが簡単に設定できます。resourcesを使うと、一連の標準的なRESTfulアクションに対してルートが生成されます。
```
GET       /articles          index     articles#index
GET       /articles/new      new       articles#new
POST      /articles          create    articles#create
GET       /articles/:id      show      articles#show
GET       /articles/:id/edit edit      articles#edit
PATCH/PUT /articles/:id      update    articles#update
DELETE    /articles/:id      destroy   articles#destroy
```

- `collection`
collectionルートを使用すると、リソース全体に対してのアクションを定義できます。つまり、リソースに関連する全ての要素に対して実行されるアクションです。
```ruby:routes.rb
resources :articles do
  collection do
    get 'search'  # /articles/search にアクセスした際のアクションを定義
    get 'popular' # /articles/popular にアクセスした際のアクションを定義
  end
end
```

- `member`
memberルートを使用すると、特定のリソース要素に対してのアクションを定義できます。つまり、個々の要素に対して実行されるアクションです。

```ruby:routes.rb
resources :articles do
  member do
    get  'comments' # /articles/:id/comments にアクセスした際のアクションを定義
    post 'upvote'   # /articles/:id/upvote にアクセスした際のアクションを定義
  end
end
```


## モデル

- モデルの作成
`$ rails generate model Micropost`

- リレーション
```ruby:micropost.rb
class Micropost < ApplicationRecord
  #userに所属(belong)する
  #自動的にインデックスと外部キー参照付きのuser_idカラムが追加される
  belongs_to :user
end
```
```ruby:user.rb
class User < ApplicationRecord
  has_many :microposts
  .
  .
  .
end
```


| オプション | 所要時間 | 特徴 | 
| --- | --- | --- | 
| micropost.user | Micropostに紐付いたUserオブジェクトを返す | 返す | 

	
	
## ビュー

- `form_with`
form_with を利用して簡単にHTMLフォームを生成することができる。
```java:.html.erb
// 名前とメールアドレスを指定して、Userモデルを新規作成するサンプル
<%= form_with(model: @model_object, url: url_for_route, local: true/false) do |form| %>
  <%= form.label :name %>
  <%= form.text_field :name %>

  <%= form.label :email %>
  <%= form.text_field :email %>

  <%= form.submit "Create User" %>
<% end %>
```
model: フォームの対象となるモデルオブジェクト
url: フォームの送信先のURL
local: true：非Ajaxの通常のフォーム、false：Ajax対応フォーム。デフォルトtrue


- シンプルな一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/4a0a8e09-10aa-fff1-cb18-dcbabea34c98.png)

```java:.html.erb
<% provide(:title, 'All users') %>
<h1>All users</h1>

<ul class="users">
  <%= render @users %>
</ul>

<%= will_paginate @users %>
```
Railsは @users を User オブジェクトのリストであると解釈する。さらに、ユーザーのコレクションを与えて呼び出すと、Railsは自動的にユーザーのコレクションを列挙し、それぞれのユーザーを_user.html.erbパーシャルで出力しようとする。

## コントローラー

- `Strong Parameters`
paramsハッシュでは:user属性を必須とし、名前、メールアドレス、パスワード、パスワードの確認の属性をそれぞれ許可し、それ以外を許可しないようにする例
```
params.require(:user).permit(:name, :email, :password, :password_confirmation)
```

```ruby
# createアクションでStrong Parametersを使う例
class UsersController < ApplicationController
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```

## 処理の流れ
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/e7caba9f-354d-f316-0a2e-9f4ee57a481e.png">



## コントローラーからの画面遷移
redirectメソッド route参照して　アクション実行
renderメソッド route参照せずにviewを表示

## テスト
- rails test: Railsアプリケーション内のすべてのテスト（ユニットテスト、統合テスト、機能テスト、モデルテストなど）を実施する
- rails test:integration: Railsアプリケーション内の統合テストのみを実行します。主にブラウザシミュレーションを用いて、ユーザーエクスペリエンスやアプリケーションのワークフローをテストします。
- rails test:models モデルに関するテストのみ実施
- rails test test/integration/users_login_test.rb  特定のテストファイルのみ実施
  　プロジェクトルート
  　　└─test 　　<font color="red">テスト用フォルダ</font>
  　　　├─controllers ※コントローラのテスト
  　　　└─integration ※統合テスト

テスト用ファイル作成
```bash
$ rails generate integration_test users_edit
      invoke  test_unit
      create  test/integration/users_edit_test.rb
```

#### フィクスチャ
```ruby
@user = users(:michael)
```
このようにメソッド名の後ろにコロン（:）とフィクスチャ名を指定することで、フィクスチャからテストデータを取得します。このような構文はRailsのテストフレームワークによって提供されているものであり、通常のメソッド呼び出しではありません。

## generateコマンド
作成されるもの
| コマンド名 | コントローラー | ビュー | モデル | マイグレーション | アセット | ルート | テスト | ヘルパー | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| model | × | × | ○ | ○ | × | × | ○ | × |
| controller | ○ | ○ | × | × | ○ | ○ | ○ | ○ |
| scaffold | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| scaffold_controller | ○ | ○ | × | × | × | × | ○ | ○ |
| migration | × | × | × | ○ | × | × | × | × |

## 暗黙の戻り値
明示的なreturnがない場合、メソッド内で最後に評価された式の値が自動的に返される

```ruby
def string_message(str = '')
  if str.empty?
    "It's an empty string!"
  else
    "The string is nonempty."
  end
end
```

## 破壊的メソッド
```ruby
a = [42, 8, 17]

#メソッドの戻り値はソートされた配列だが、元の変数aはそのまま
a.sort

# !をつけると元の変数そのものも更新される
a.sort!
```

## クラスメソッド
`def User.digest(string)` の部分は一見メソッドの呼び出しにも見えるが、クラスメソッドを定義している。他の言語でいう `static` を表現するために 「クラス名.メソッド名」という書き方をする。

```ruby
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # 渡された文字列のハッシュ値を返す
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end
end
```

## 構文

### ブロック構文
Rubyのメソッド呼び出しにおいて、ブロック構文を使うかどうかはそのメソッドによって異なります。
例えば、Array#eachメソッドはブロックを取ります。以下はその例です：
```ruby
numbers = [1, 2, 3, 4, 5]

numbers.each do |num|
  puts num
end
```