Laravel で Ruby on Rails チュートリアル【3章】セットアップ

## 環境
- Laravel 8.6
- PHP 8.0
- Bootstrap 5.1

## 3.1 セットアップ

### Laravel

Laravelのプロジェクトを作成する

```bash
curl -s https://laravel.build/laravel_tutorial | bash

// 中略

[sudo] password for user: // 左のメッセージが表示されたらrootパスワードを設定する

// 中略

Thank you! We hope you build something incredible. Dive in with: cd laravel_tutorial && ./vendor/bin/sail up // 左のメッセージが出たら作成成功
```

Laravelのルートディレクトリに移動してDockerコンテナを起動する

```bash
cd laravel_tutorial
./vendor/bin/sail up -d
```

http://localhost にアクセスしてページが表示されればコンテナの起動成功

sailコマンドを使用するたびに相対パスを指定するのは面倒なので、Bashエイリアスを設定

```bash
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
```

Laravelに必要なパッケージを追加する

```bash
sail composer require laravel/ui
sail php artisan ui bootstrap
sail npm install bootstrap@next @popperjs/core --save-dev
sail npm install bootstrap @popperjs/core --save-dev
sail npm install
sail composer require laravelcollective/html
sail composer require symfony/dom-crawler --dev
```

### heroku

LaravelをHerokuで動かす際に以下のファイルが必要なので作成

```bash:Procfile
web: vendor/bin/heroku-php-apache2 public/
```

Herokuで新しいアプリを作成

```bash
heroku create
```

Laravel 暗号化鍵を設定

```bash
heroku config:set APP_KEY=
```

Herokuにデプロイ

```bash
git push heroku master
```

## 3.2 静的なページ

下記コマンドでコントローラーを作成

```bash
sail artisan make:controller StaticPagesController
```

```php:/app/Http/Controllers/StaticPagesController.php
class StaticPagesController extends Controller
{
    public function home()
    {
        return view('static_pages/home');
    }

    public function help()
    {
        return view('static_pages/help');
    }
}
```

ルート定義

```php:/routes/web.php
use App\Http\Controllers\StaticPagesController;
use Illuminate\Support\Facades\Route;

Route::get('static_pages/home', [StaticPagesController::class, 'home']);
Route::get('static_pages/help', [StaticPagesController::class, 'help']);
```

ビューの作成

```html:/resources/views/static_pages/home.blade.php
<h1>Sample App</h1>

<p>
    This is the home page for the
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>
```

```html:/resources/views/static_pages/help.blade.php
<h1>Help</h1>

<p>
    Get help on the Ruby on Rails Tutorial at the
    <a href="https://railstutorial.jp/help">Rails Tutorial help page</a>.
    To get help on this sample app, see the
    <a href="https://railstutorial.jp/#ebook"><em>Ruby on Rails Tutorial</em>
    book</a>.
</p>
```

## 3.3 テスト

### 3.3.1 テストの実行

テストの作成

```
sail artisan make:test StaticPagesControllerTest --unit
```

```php:/tests/Unit/StaticPagesControllerTest.php
use Tests\TestCase;

class StaticPagesControllerTest extends TestCase
{
    public function testGetHome()
    {
        $response = $this->get('/static_pages/home');
        $response->assertStatus(200);
    }

    public function testGetHelp()
    {
        $response = $this->get('/static_pages/help');
        $response->assertStatus(200);
    }
}
```

テスト実行

```
sail test
```

### 3.3.2 Red

未作成のページにアクセスしてテストが失敗することを確認する

```php
    public function testGetAbout()
    {
        $response = $this->get('/static_pages/about');
        $response->assertStatus(200);
    }
```

### 3.3.3 Green

ページを作成して上のテストを成功させる

```php:/routes/web.php
Route::get('static_pages/about', [StaticPagesController::class, 'about']);
```

```php:/app/Http/Controllers/StaticPagesController.php
    public function about()
    {
        return view('static_pages/about');
    }
```

```html
<h1>About</h1>

<p>
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    is a <a href="https://railstutorial.jp/#ebook">book</a> and
    <a href="https://railstutorial.jp/#screencast">screencast</a>
    to teach web development with
    <a href="http://rubyonrails.org/">Ruby on Rails</a>.
    This is the sample application for the tutorial.
</p>
```

### 3.3.4 Refactor

## 3.4 少しだけ動的なページ

### 3.4.1 タイトルをテストする (Red)

テストで使用する関数を追加

```php:/tests/TestCase.php
use Symfony\Component\DomCrawler\Crawler;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    public function dom($html)
    {
        $dom = new Crawler();
        $dom->addHTMLContent($html, "UTF-8");
        return $dom;
    }
}
```

タイトルのテストを追加

```php:/tests/Unit/StaticPagesControllerTest.php
class StaticPagesControllerTest extends TestCase
{
    public function testGetHome()
    {
        $response = $this->get('/static_pages/home');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Home | Ruby on Rails Tutorial Sample App", $dom->filter("title")->text());
    }

    public function testGetHelp()
    {
        $response = $this->get('/static_pages/help');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Help | Ruby on Rails Tutorial Sample App", $dom->filter("title")->text());
    }

    public function testGetAbout()
    {
        $response = $this->get('/static_pages/about');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("About | Ruby on Rails Tutorial Sample App", $dom->filter("title")->text());
    }
}
```

追加したテストが失敗することを確認する

### 3.4.2タイトルを追加する (Green)

ビューを修正

```html:/resources/views/static_pages/home.blade.php
<!DOCTYPE html>
<html>
    <head>
        <title>Home | Ruby on Rails Tutorial Sample App</title>
    </head>
    <body>
        <h1>Sample App</h1>
        <p>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
        </p>
    </body>
</html>
```

```html:/resources/views/static_pages/help.blade.php
<!DOCTYPE html>
<html>
    <head>
        <title>Help | Ruby on Rails Tutorial Sample App</title>
    </head>
    <body>
        <h1>Help</h1>
        <p>  Get help on the Ruby on Rails Tutorial at the
            <a href="https://railstutorial.jp/help">Rails Tutorial help
            page</a>.
            To get help on this sample app, see the
            <a href="https://railstutorial.jp/#ebook">
            <em>Ruby on Rails Tutorial</em> book</a>.
        </p>
    </body>
</html>
```

```html:/resources/views/static_pages/about.blade.php
<!DOCTYPE html>
<html>
    <head>
        <title>About | Ruby on Rails Tutorial Sample App</title>
    </head>
    <body>
        <h1>About</h1>
        <p>
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            is a <a href="https://railstutorial.jp/#ebook">book</a> and
            <a href="https://railstutorial.jp/#screencast">screencast</a>
            to teach web development with
            <a href="http://rubyonrails.org/">Ruby on Rails</a>.
            This is the sample application for the tutorial.
        </p>
    </body>
</html>
```

テストの一部を共通化

```php:/tests/Unit/StaticPagesControllerTest.php
class StaticPagesControllerTest extends TestCase
{
    private $base_title;

    protected function setUp(): void
    {
        parent::setUp();
        $this->base_title = "Ruby on Rails Tutorial Sample App";
    }

    public function testGetHome()
    {
        $response = $this->get('/static_pages/home');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Home | {$this->base_title}", $dom->filter("title")->text());
    }

    public function testGetHelp()
    {
        $response = $this->get('/static_pages/help');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Help | {$this->base_title}", $dom->filter("title")->text());
    }

    public function testGetAbout()
    {
        $response = $this->get('/static_pages/about');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("About | {$this->base_title}", $dom->filter("title")->text());
    }
}
```

### 3.4.3 レイアウトと埋め込み~~Ruby~~PHP (Refactor)

レイアウトを作成

```html:/resources/views/layouts/application.blade.php
<!DOCTYPE html>
<html>
    <head>
        <title>@yield('title') | Ruby on Rails Tutorial Sample App</title>
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <script data-turbolinks-track="reload" src="{{ mix('/js/app.js') }}"></script>
        <link media="all" type="text/css" rel="stylesheet" data-turbolinks-track="reload" href="{{ mix('/css/app.css') }}">
    </head>

    <body>
        @yield('content')
    </body>
</html>
```

ビューを修正

```html:/resources/views/static_pages/home.blade.php
@extends('layouts.application')

@section('title', 'Home')

@section('content')
<h1>Sample App</h1>
<p>
    This is the home page for the
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>
@endsection
```

```html:/resources/views/static_pages/help.blade.php
@extends('layouts.application')

@section('title', 'Help')

@section('content')
<h1>Help</h1>
<p>  Get help on the Ruby on Rails Tutorial at the
    <a href="https://railstutorial.jp/help">Rails Tutorial help
    page</a>.
    To get help on this sample app, see the
    <a href="https://railstutorial.jp/#ebook">
    <em>Ruby on Rails Tutorial</em> book</a>.
</p>
@endsection
```

```html:/resources/views/static_pages/about.blade.php
@extends('layouts.application')

@section('title', 'About')

@section('content')
<h1>About</h1>
<p>
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    is a <a href="https://railstutorial.jp/#ebook">book</a> and
    <a href="https://railstutorial.jp/#screencast">screencast</a>
    to teach web development with
    <a href="http://rubyonrails.org/">Ruby on Rails</a>.
    This is the sample application for the tutorial.
</p>
@endsection
```

#### 演習

contactのテストを追加

```php:/tests/Unit/staticPagesControllerTest.php
    public function testGetContact()
    {
        $response = $this->get('/static_pages/contact');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Contact | {$this->base_title}", $dom->filter("title")->text());
    }
```

contactのページを追加

```php:/routes/web.php
Route::get('static_pages/contact', [StaticPagesController::class, 'contact']);
```

```html:/resources/views/static_pages/contact.blade.php
@extends('layouts.application')

@section('title', 'Contact')

@section('content')
<h1>Contact</h1>
<p>
    Contact the Ruby on Rails Tutorial about the sample app at the
    <a href="https://railstutorial.jp/contact">contact page</a>.
</p>
@endsection
```

```php:/app/Http/Coontrollers/staticPagesController.php
    public function contact()
    {
        return view('static_pages/contact');
    }
```

### 3.4.4 ルーティングの設定

Rootのルートを追加

```php:/routes/web.php
Route::get('/', [StaticPagesController::class, 'home']);
```

Rootのテストを追加

```php:/tests/Unit/staticPagesControllerTest.php
    public function testGetRoot()
    {
        $response = $this->get('/');
        $response->assertStatus(200);
        $dom = $this->dom($response->content());
        $this->assertSame("Home | {$this->base_title}", $dom->filter("title")->text());
    }
```

# 参考
https://dev.to/simodev/how-to-properly-install-bootstrap-5-and-vue-3-on-laravel-8-2e1m
https://readouble.com/laravel/8.x/ja/installation.html
https://readouble.com/laravel/8.x/ja/sail.html
https://readouble.com/laravel/8.x/ja/frontend.html
https://devcenter.heroku.com/ja/articles/getting-started-with-laravel
https://qiita.com/miya0001/items/178f31035f63bba63f67

https://qiita.com/sakuraya/items/411dbc2e1e633928340e