Railsチュートリアル 第14章
14.1 Relationshipモデル
14.1.1
マイグレーションした際にschema.rb
に反映されませんでした. しかしバッファにはなんのエラーも出ませんでした. ちょっと調べてみましょう.
以下のコマンドでデータベースに接続できます.
$ rails db
私のようにDockerで環境構築している場合は次のようになるでしょう. ちなみに私はMySQLをRailsとは別のコンテナで起動させています.
$ docker-compose exec web rails db
するとパスワードが求められるので, database.yml
で指定したパスワードを入力します. すると以下のようなプロンプトが表示されます.
MySQL [myapp_development]>
myapp_development
はデータベース名ですね. マイグレーションしたテーブルが存在するかを確認してみます.
MySQL [myapp_development]> show tables; +-----------------------------+ | Tables_in_myapp_development | +-----------------------------+ | ar_internal_metadata | | microposts | | relationships | | schema_migrations | | users | +-----------------------------+ 5 rows in set (0.01 sec)
しかしschema.rb
に反映されていないのはおかしいので, マイグレーションをやりなおしましょう.
MySQL [myapp_development]> exit Bye $ docker-compose exec web rails db:rollback $ docker-compose exec web rails db:migrate
すると以下のようなエラーが出ました.
Mysql2::Error: Table 'relationships' already exists
そもそも最初のマイグレーションがうまくいってないから, ロールバックによってテーブルが削除されなかったようですね. では手動でテーブルを削除しましょう.
$ docker-compose exec web rails db MySQL [myapp_development]> drop table relationships; Query OK, 0 rows affected (0.02 sec) MySQL [myapp_development]> exit Bye
ここでもう一度マイグレーションをしたところ, ちゃんとschema.rb
に反映されました.
演習1
答えが問題文中に書かれていますね. 図14.7を見ると以下の配列が得られることがわかります.
[2, 7, 10, 8]
演習2
id
が2であるユーザーはid
が1のユーザーしかフォローしていません. したがってこのユーザーだけからなる配列が得られます.
したがってuser.followind.map(&:id)
は[1]
に等しいですね.
14.1.2
演習1, 2
省略.
14.1.3
演習1
たしかにバリデーションを解除してもテストは成功しました.
14.1.4
演習1, 2
以下の通りです.
>> first = User.first >> second = User.second >> first.following?(second) SELECT 1 AS one FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 AND `users`.`id` = 2 LIMIT 1 => false >> first.follow(second) INSERT INTO `relationships` (`follower_id`, `followed_id`, `created_at`, `updated_at`) VALUES (1, 2, '2018-07-05 15:19:20', '2018-07-05 15:19:20') >> first.following?(second) => true >> first.unfollow(second) DELETE FROM `relationships` WHERE `relationships`.`id` = 1 >> first.following?(second) => false
14.1.5
演習1
>> user = User.first >> second = User.second >> last = User.last >> second.follow(user) >> last.follow(user) >> user.followers.map(&:id) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 => [2, 100]
演習2, 3
前者はデータベースの中で数えていますが, 後者はRubyの配列として数えています. したがって前者のほうがパフォーマンスが高いですね.
user.followers.count SELECT COUNT(*) FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 => 2 >> user.followers.to_a.count => 2
14.2 [follow]のWebインターフェース
14.2.1
演習1, 2
>> user = User.first >> user.following.count => 49 >> user.followers.count => 38
14.2.2
演習1, 2
省略.
演習3
プロフィールテストに書きました.
# test/integration/users_profile_test.rb test "stats" do log_in_as(@user) get root_path assert_select '#following', text: "#{@user.following.count}" assert_select '#followers', text: "#{@user.followers.count}" get user_path(@user) assert_select '#following', text: "#{@user.following.count}" assert_select '#followers', text: "#{@user.followers.count}" end
以下のように数字のままだとダメでした.
assert_select '#following', text: @user.following.count
14.2.3
演習1, 2
省略.
14.2.4
演習1
省略.
演習2
Follow, Unfollowどちらを押しても, users/show
が描画されています.
Rendered users/show.html.erb within layouts/application
14.2.5
演習1
Safariの開発メニューからJavascriptを無効にした場合もちゃんと動作しました.
演習2
省略.
14.2.6
演習1, 2
省略.
14.3 ステータスフィード
14.3.1
演習1
新しい順に取得するので, 以下のようになるでしょう.
user.feed.map(&:id) => [10, 9, 7, 5, 4, 2, 1]
14.3.2
演習1
feed
メソッドを以下のように変更すればいいですね.
def feed Micropost.where("user_id IN (?)", following_ids) end
この場合はmichael
自身の投稿を確認するテストで失敗します.
演習2
これは13章で実装した通りですね.
def feed Micropost.where("user_id = ?", id) end
するとlana
の投稿を確認するテストで失敗します.
演習3
feed
メソッドを以下のように変更すればいいですね.
def feed Micropost.all end
するとarcher
の投稿を確認するテストで失敗します.
14.3.3
演習1
以下の通りです.
test "feed on Home page" do get root_path @user.feed.paginate(page: 1) do |micropost| assert_match CGI.escapeHTML(micropost.content), response.body end end
演習2
ヒントから, 以下のmicropostがまずいんでしょうが, よくわかりませんでした.
tone: content: "I'm sorry. Your words made sense, but your sarcastic tone did not." created_at: <%= 10.minutes.ago %> user: lana