RubyMine で Rails Tutorial 14章

ようやく最後の14章

ブランチも多くなりましたね。

モデルの関係を作りますが、なかなかややこしいと思います。RubyMine で図を作ってみて、関係の線を見ると把握しやすいこともあります。

14.2.2 では演習がありました。users_profile_test.rb で、統計情報の表示について確認します。

  test "profile display" do
    get user_path(@user)
    assert_template 'users/show'
    assert_select 'title', full_title(@user.name)
    assert_select 'h1', text: @user.name
    assert_select 'h1>img.gravatar'
    assert_match @user.microposts.count.to_s, response.body
    assert_select 'ul.pagination'
    @user.microposts.paginate(page: 1).each do |micropost|
      assert_match micropost.content, response.body
    end

    assert_select 'strong#following'
    assert_match @user.following.count.to_s, response.body
    assert_select 'strong#followers'
    assert_match @user.followers.count.to_s, response.body
  end

Ajax での実装をすると、ログではこのように “as JS” と出てきます。

Started DELETE "/relationships/90" for 127.0.0.1 at 2018-05-30 14:14:23 +0900
Processing by RelationshipsController#destroy as JS
  Parameters: {"utf8"=>"✓", "commit"=>"Unfollow", "id"=>"90"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/helpers/sessions_helper.rb:17
  Relationship Load (0.1ms)  SELECT  "relationships".* FROM "relationships" WHERE "relationships"."id" = ? LIMIT ?  [["id", 90], ["LIMIT", 1]]
  ↳ app/controllers/relationships_controller.rb:14
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
  ↳ app/controllers/relationships_controller.rb:14
  Relationship Load (0.1ms)  SELECT  "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ?  [["follower_id", 1], ["followed_id", 4], ["LIMIT", 1]]
  ↳ app/models/user.rb:95
   (0.1ms)  begin transaction
  ↳ app/models/user.rb:95
  Relationship Destroy (0.3ms)  DELETE FROM "relationships" WHERE "relationships"."id" = ?  [["id", 90]]
  ↳ app/models/user.rb:95
   (1.5ms)  commit transaction
  ↳ app/models/user.rb:95
  Rendering relationships/destroy.js.erb
  Rendered users/_follow.html.erb (0.8ms)
   (0.1ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ?  [["followed_id", 4]]
  ↳ app/views/relationships/destroy.js.erb:2
  Rendered relationships/destroy.js.erb (3.7ms)
Completed 200 OK in 16ms (Views: 8.4ms | ActiveRecord: 2.4ms)

リスト 14.49 は最後の演習です。何をテストするのがいいのか難しかったのですが、|micropost| でぐるぐる回すということから、投稿の内容が含まれているということを見ればいいのかなと思いましてこのようにしてみました。

  test "feed on Home page" do
    get root_path
    @user.feed.paginate(page: 1).each do |micropost|
      assert_match CGI.escapeHTML(micropost.content), response.body
    end
  end

ヒントにある CGI.escapeHTML を外してみると、I’m sorry のような文字列が I'm sorry. となるのでマッチしないということになりそうです。

長い長いチュートリアルが終わりました。わたしもいい復習になったと思います。
RubyMine の使い方にも慣れることができて、記録を残してよかったです。
どなたかのお役に立っているとうれしいです。

RubyMine で Rails Tutorial 13章

13章やります。あと少しです。

ActiveRecord の関連付けをすると、図も生成できるようになります。
右クリックして Diagrams → Show Diagram → Rails Model Dependency Diagram で作ることができます。

また、この章でもテストと実装とを行き来することが多いですが、ショートカットキーを使うと便利です。

実装からテストへの移動も、テストから実装(テスト対象)への移動もともに shift + command + T でした。
こういう統合開発環境はメニューからさわって一つずつ覚えていくのが使いこなすためのコツですね。

リスト 13.28 では、div.pagination の要素を確認するテストをしていますが、いまは Bootstrap 4 に対応した will_paginate-bootstrap4 を使っているため、ul.pagination が出力されます。テストもそのように直して実行しました。

require 'test_helper'

class UsersProfileTest < ActionDispatch::IntegrationTest
  include ApplicationHelper

  def setup
    @user = users(:michael)
  end

  test "profile display" do
    get user_path(@user)
    assert_template 'users/show'
    assert_select 'title', full_title(@user.name)
    assert_select 'h1', text: @user.name
    assert_select 'h1>img.gravatar'
    assert_match @user.microposts.count.to_s, response.body
    assert_select 'ul.pagination'
    @user.microposts.paginate(page: 1).each do |micropost|
      assert_match micropost.content, response.body
    end
  end
end

13.3.2 の演習では if 〜 else 〜 end のそれぞれにパーシャルを作るというものでした。
RubyMine から簡単に切り出せるはずなのですが、後半はうまくできませんでした。

手で切り出します。

直したら test を流してエラーがないことを確認します。

リスト 13.57 の課題は、投稿数のテストです。fixtures で michael は34個(4個+30個)の投稿をするように設定しているので、その数を確認しています。

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'ul.pagination'

    # 無効な送信
    assert_no_difference 'Micropost.count' do
      post microposts_path, params: { micropost: { content: "" } }
    end
    assert_select 'div#error_explanation'

    # 有効な送信
    content = "This micropost really ties the room together"
    assert_difference 'Micropost.count', 1 do
      post microposts_path, params: { micropost: { content: content } }
    end
    assert_redirected_to root_url
    follow_redirect!
    assert_match content, response.body

    # 投稿を削除する
    assert_select 'a', text: 'delete'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end

    # 違うユーザーのプロフィールにアクセス (削除リンクがないことを確認)
    get user_path(users(:archer))
    assert_select 'a', text: 'delete', count: 0
  end

  test "micropost sidebar count" do
    log_in_as(@user)
    get root_path
    assert_match "34 microposts", response.body

    # まだマイクロポストを投稿していないユーザー
    other_user = users(:malory)
    log_in_as(other_user)
    get root_path
    assert_match "0 microposts", response.body
    other_user.microposts.create!(content: "A micropost")

    get root_path
    assert_match "1 micropost", response.body
  end
end

最後は画像のアップロード周りです。Rails 5.2.0 では carrierwave ではなく ActionStorage を使うのがいいようなのですが、ここではチュートリアルに従います。

# section 13
gem 'carrierwave'
gem 'mini_magick'
...
group :production do
  gem 'pg'
  gem 'fog'
end

リスト 13.63 のテストはそのままではうまく通りませんでした。post microposts_path には param の引数が必要なので、そのように括っておきます。

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'ul.pagination'
    assert_select 'input[type=file]'

    # 無効な送信
    assert_no_difference 'Micropost.count' do
      post microposts_path, params: { micropost: { content: "" } }
    end
    assert_select 'div#error_explanation'

    # 有効な送信
    content = "This micropost really ties the room together"
    picture = fixture_file_upload('test/fixtures/rails.png', 'image/png')
    assert_difference 'Micropost.count', 1 do
      post microposts_path, params: { micropost: { content: content, picture: picture } }
    end
    assert assigns(:micropost).picture?
    assert_redirected_to root_url
    follow_redirect!
    assert_match content, response.body

    # 投稿を削除する
    assert_select 'a', text: 'delete'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end

development ではローカルにアップロードしますが、production では fog を使って AWS S3 にアップロードするコードになっています。せっかくなので使ってみます。

13.4.4 にしたがって AWS で設定することで、無事 production でも画像のアップロードが動作しました。

AWSのコンソールからも確認できます。