RailsでToDoサービスを作ろう(第3回)〜ユーザを紐付ける 〜

にゅ〜ぶる
にゅ〜ぶる

こんにちは、にゅ〜ぶるです。

こんにちは〜、ぶるこだよ〜💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

さて、第3回目ですね!前回は、こちら
今日は、「ユーザを紐付ける」について、進めていきたいと思います!

にゅ〜ぶる
にゅ〜ぶる

自分だけのToDoリストであれば、不要かもしれませんが、多くの方に利用して貰うには、「ユーザ」は必須になりますよね。
それでは、やっていきましょ〜🎶

にゅ〜ぶる
にゅ〜ぶる

コマンドは、こんな感じ

名前 … nameというカラム名の文字列型(string)

にゅ〜ぶる
にゅ〜ぶる

その他、追加したいカラムは自由に追加してみてください。

年齢 … ageというカラム名の整数型(integer) など

にゅ〜ぶる
にゅ〜ぶる

テーブルを作成するmigrateファイルも作成されますので、
migrateコマンドも忘れずにね!

わ〜お、忘れるところだった💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

Userの画面を作ったので、「rails s」で起動した後、
「http://127.0.0.1:3000/users」にアクセスしてみてね!

にゅ〜ぶる
にゅ〜ぶる

そして、自分のユーザを登録してみましょう。
作成されたCRUDの画面を使って登録しても良いのですが、
今回は、少し脱線しますが、Seedを使ってみましょう。

にゅ〜ぶる
にゅ〜ぶる

でも今回使うSeedは、標準で使えるSeedではなく、「Seed Fu」をオススメします。
実行するたびにデータが新規登録されるSeedに比べ、更新が楽になりますので、「Seed Fu」を使っています。

にゅ〜ぶる
にゅ〜ぶる

では早速、使ってみましょう。
まずは、Gemfileに以下を追加します。

Rails 3.1, 3.2, 4.0, 4.1, 4.2, 5.0では、2.3以上である必要があるため、この指定をしています。

参考 https://github.com/mbleigh/seed-fu

にゅ〜ぶる
にゅ〜ぶる

そして、Gemfileを修正したら「bundle install」ですね。

にゅ〜ぶる
にゅ〜ぶる

そして、Seedファイルを置く場所を作成します。

このディレクトリは固定ですか?

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

そうだね、変更する事も可能だけど、
基本的には、db/fixtures配下にseedファイルを作成したら良いと思います。
そして、development/productionディレクトリ配下にseedファイルを作成すると、その環境下でのみ実行されるseedファイルになります。

にゅ〜ぶる
にゅ〜ぶる

今回は、ユーザ情報を作成しますので、開発環境(development)だけに作成してみましょう。
※seedファイルのファイル名は自由につけても構いませんが、アルファベット順に実行される事に注意してください。

にゅ〜ぶる
にゅ〜ぶる

では、実行してみましょう!

にゅ〜ぶる
にゅ〜ぶる

こんな感じのログが出力されて、usersテーブルに登録されているのが確認出来るかと思います。

にゅ〜ぶる
にゅ〜ぶる

データに変更が発生した際は、このファイルを修正して、再度コマンドを実行するだけでOKです。是非、試してみて下さい。

おぉぉお!!すごぉ〜い💕
データを消したり、DBを作り直したりしなくても変更できた!!

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

その他、Seed-Fuには色々な書き方がありますが、必要あれば調べてみて下さいね。
では、これで初期データも出来たので、次に進みましょうか!

は〜い💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

次は、作成したTaskとUserを紐づけることをしてみましょう。
紐づける事によって、「にゅ〜ぶるのTask」と「ぶるこのTask」といったように分けることが出来るようになります。

にゅ〜ぶる
にゅ〜ぶる

まずは、紐づいた情報を管理するために、テーブルを修正します。
修正する際は、generate機能のmigrationを使います。

にゅ〜ぶる
にゅ〜ぶる

中身はこんなファイルが作成されたと思います。

にゅ〜ぶる
にゅ〜ぶる

rails generate migration の後に、「AddUserToTask」としたことで、自動でTaskに追加するのだと判断されて、「user:references」を指定したことで、Userへの参照用のカラムだと判断され、Migrationファイルが自動生成されました。

にゅ〜ぶる
にゅ〜ぶる

では、rails db:migrateを実行して、テーブルがどう変わったか確認してみましょう。

うわ〜ん😭
エラーが出ちゃったよおぉぉ😭

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

あっ!
前回、Taskを作成した際に、何かデータを登録してますね?
そのデータに対して、ユーザが紐づいていない状態なのに、紐付けキー(必須になる)を作成してしまった為、MySQLのエラーが出ちゃいましたね…💦
※エラーが出なかった方は、少しお待ちください。

にゅ〜ぶる
にゅ〜ぶる

では、DBをリセットしましょう。(登録した中身は消えちゃいますが…)

にゅ〜ぶる
にゅ〜ぶる

はい。すっきり笑

よかったぁ〜💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

初期データも消えてしまったので、「rake db:seed_fu」も再度実行しておいて下さいね。

にゅ〜ぶる
にゅ〜ぶる

これでDB上ではTaskとUserが紐づいたのですが、Railsにも紐づいている事を教えてあげなければいけません。その時に使うのが、Modelに「has_one/many」「belongs_to」です。

にゅ〜ぶる
にゅ〜ぶる

まずは、「has_one/many」を設定しましょう。
has_XXXとなっている事から分かる通り、親と子の関係で、親の方に設定します。

にゅ〜ぶる
にゅ〜ぶる

そして、子の方に、「belongs_to」を設定します。

にゅ〜ぶる
にゅ〜ぶる

こう設定する事で、
User.tasksで、そのUserのTask一覧が取得でき、
Task.userで、そのTaskのUserが取得出来ます。

では、実際に試してみましょう。

にゅ〜ぶる
にゅ〜ぶる

ちょっと試したいなという時に便利なのが、「rails console」です。
コンソール上からRailsのサービスにアクセスする事が出来ます。

にゅ〜ぶる
にゅ〜ぶる

Rubyをやった事のある方ならご存知、irbのコンソールが起動します。
このコンソール上で、自由にプログラムを実行させる事が出来るのです。

にゅ〜ぶる
にゅ〜ぶる

こんな感じにテストデータを作成してみましょう。

にゅ〜ぶる
にゅ〜ぶる

この状態で、次のように実行してみて下さい。なんと返ってくるでしょう?

にゅ〜ぶる
にゅ〜ぶる

こんな結果が返ってきますね。

にゅ〜ぶる
にゅ〜ぶる

ほら、TaskとUserが紐づいた!

やったぁ〜💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

これで完成!!!!
と言いたいところですが、画面も直さないといけないですね。

にゅ〜ぶる
にゅ〜ぶる

では、画面のどこを直す必要があるでしょうか?

えっと〜
新規登録(C)はいるでしょ〜💕
あとはぁ〜変更(U)に参照(R)に
削除(D)も?

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

削除は画面がないので、修正する必要はないんだけど、
親を削除したら子も一緒に削除はしておきたいよね。それを最後にやろっか。

にゅ〜ぶる
にゅ〜ぶる

では、新規登録の画面は、
「app/views/tasks/new.html.erb」になるんだけど、中身はこんな感じ

にゅ〜ぶる
にゅ〜ぶる

renderを使って、別ファイルになっているんだ。
そのファイルが「app/views/tasks/_form.html.erb」

にゅ〜ぶる
にゅ〜ぶる

これに、ユーザを追加してみましょう。
ユーザはリスト表示したいので、「form_withのselect」を使います。

好きなところに、以下を追加してみて下さい。

おぉ〜💕
出た出た〜登録しよ〜💕

ぶるこ
ぶるこ

が〜ん❗️

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

Userに値が入ってない!!って怒られたね。
原因は、ここ。

にゅ〜ぶる
にゅ〜ぶる

Strong Parametersっていうんだけど、
要は、受け取る可能なパラメータリストを指定して、それ以外の不正なパラメータを受け取らないようにしている感じだね。

にゅ〜ぶる
にゅ〜ぶる

ここに、userを許可してあげないといけないんだ。
書き方はこう。

にゅ〜ぶる
にゅ〜ぶる

これで登録できるようになるよ。

わぁ〜💕
登録できたぁぁあ💕

ぶるこ
ぶるこ

次は、変更画面だね💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

そうだね。
でも実は、「app/views/tasks/_form.html.erb」が変更画面でも使われているので既に修正出来てるんだ。

なんやて工藤!!!

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

だから、次は、参照画面を修正するよ。
参照画面のViewは、「app/views/tasks/show.html.erb」だね。

にゅ〜ぶる
にゅ〜ぶる

これは単純に、@taskというインスタンス変数にTaskの情報が入っているから、
そのまま表示するだけだね。
次のコードを追加してみてね。

変な数字みたいなのが…

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

おっと、それは、クラスのオブジェクトIDなんだけど、まぁ気にしなくても大丈夫です。
こう置き換えてみてね。

おぉ〜ユーザの名前が出たぁ💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

うん。これで完成だね!
じゃあ、応用の課題として、一覧画面の「app/views/tasks/index.html.erb」にも修正してみて下さいね。
※回答はあえて載せません。合ってるかどうかの確認が必要であれば、コメントなりでご連絡くださいね。

わぁ〜い、かんせー💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

じゃ、ここからはおまけ?
Userを削除した際に、そのUserに関するTaskも一緒に削除される機能を追加するよ。

(*´∀`*)ワクワク
でも、難しそう…

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

そう思うかもだけど、実は簡単なんだ。
Modelの紐付け設定に、このオプション(dependent: :destroy)を追加するだけなんだ。

なんやて工藤!!!!

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

では、動作確認してみようか。
画面で動かしてみるのでも良いし、「rails console」を使うのでも良いよ。
「rails console」の場合は、こんな感じかな。

ほんとだぁ〜すご〜い💕

ぶるこ
ぶるこ
にゅ〜ぶる
にゅ〜ぶる

今回はここまでだよ。お疲れ様でした!
次回は、「Punditで認可の権限管理する」お楽しみにっ!!

最後まで読んでくれてありがとうございました!

現在、Railsのチュートリアル的な感じで、
「Todoサービスを作る!」をテーマにお送りしております。
アジェンダは、こちら

質問等ありましたら、コメントなりTwitterなりで頂ければ対応させて頂きますので、遠慮なく利用くださいね。