Railsチュートリアル 第14章 ユーザーをフォローする - [Follow] のWebインターフェイス - フォローのサンプルデータ

# サンプルデータの必要性

サンプルデータを先に用意すれば、バックエンドの実装とフロントエンドの実装を切り離すことができます。その期待できる効果の一例として、以下のようなものが挙げられます。

* コントローラー関係の実装なしでビューの実装のみを先に作ることができる
* `POST`や`DELETE`等のHTTPリクエストに対するテストと、`GET`リクエストに対するテストを切り離すことができる

# リレーションシップのサンプルデータを生成するためのコード

リレーションシップのサンプルデータを生成するためのコードの本体は、以下のようになります。

```ruby:
users = User.all
user = users.first
following = users[2..50]
followers = users[3..40]
following.each { |followed| user.follow(followed) }
followers.each { |follower| follower.follow(user) }
```

上記のコードは、以下のような動作をします。

* 最初のユーザーに、3番目から51番目までのユーザーをフォローさせる
* 4番目から41番目までのユーザーに、最初のユーザーをフォローさせる

上記のコードを追加するファイルは、`db/seeds.rb`となります。当該変更を反映した`db/seeds.rb`の全体像は、以下のようになります。

```diff:db/seeds.rb
  # ユーザー
  User.create(name:                 "Example User",
              email:                "example@railstutorial.org",
              password:             "foobar",
              password_confirmation: "foobar",
              admin: true,
              activated: true,
              activated_at: Time.zone.now)

  99.times do |n|
    name = Faker::Name.name
    email = "example-#{n+1}@railstutorial.org"
    password = "password"
    User.create!( name:                  name,
                  email:                 email,
                  password:              password,
                  password_confirmation: password,
                  activated: true,
                  activated_at: Time.zone.now)
  end

  # マイクロポスト
  users = User.order(:created_at).take(6)
  50.times do
    content = Faker::Lorem.sentence(5)
    users.each { |user| user.microposts.create!(content: content) }
  end
+
+ # リレーションシップ
+ users = User.all
+ user = users.first
+ following = users[2..50]
+ followers = users[3..40]
+ following.each { |followed| user.follow(followed) }
+ followers.each { |follower| follower.follow(user) }
```

# RDB上のサンプルデータを作り直す

## Production環境における、RDBそのものの再構築

まずは`rails db:migrate:reset`コマンドを実行し、Production環境のRDBをまっさらな状態にしておきます。

```
# rails db:migrate:reset
Dropped database 'db/development.sqlite3'
Dropped database 'db/test.sqlite3'
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'

...略

== ...略: migrating ==============================
...略
== ...略: migrated (0.0282s) =====================
```

私の環境では、以下のマイグレーションが実行されました。

* `CreateUsers`
* `AddIndexToUsersEmail`
* `AddPasswordDigestToUsers`
* `AddRememberDigestToUsers`
* `AddAdminToUsers`
* `AddActivationToUsers`
* `AddResetToUsers`
* `CreateMicroposts`
* `AddPictureToMicroposts`
* `CreateRelationships`

マイグレーションの歴史は機能追加の歴史であり、Railsチュートリアルを進めていった歴史でもあります。こうして改めて並べてみると感慨深いです。

## 再構築したRDBに対するサンプルデータの投入

再構築したRDBに対してサンプルデータを投入するコマンドは、`rails db:seed`コマンドですね。

```
# rails db:seed
```

`rails db:seed`コマンドの実行には時間がかかります。`db/seeds.rb`の内容に問題がなければ、`rails db:seed`コマンドが正常終了するまで、コンソールには何も出力されません。

### サンプルデータ投入時の注意事項

`rails db:seed`コマンドが失敗した場合、`rails db:migrate:reset`からやり直す必要があります。RDBに中途半端な状態でデータが残っていると、中途半端に残ったデータが原因で`rails db:seed`コマンドが失敗するおそれがあるためです。以下はそのような失敗の例です。

```
# rails db:seed
rails aborted!
NameError: undefined local variable or method `user' for main:Object
Did you mean?  users
...スタックトレース略

# rails db:seed
rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
...スタックトレース略
```