LoginSignup
0
0

More than 3 years have passed since last update.

Rails Tutorial 拡張機能のメッセージ機能を作ってみた(その5):削除機能

Posted at

Rails Tutorialの第14章にある、メッセージ機能を作る件の続きです。

前回までで受信したDMが表示される機能ができました。
今回はDMを削除する機能を作ります。

DMを削除する機能の設計

DMを削除する機能を作ります。13.3.4を読みます。
micropostは自分が投稿したもののみ削除できました。DMでは、自分が受信したDMのみ削除できるようにします。削除はモデルを作った際に決めたとおり、deletedフラグをTRUEにします。

destroyアクション作成

destroyアクションを作ります。
「リスト 13.52: Micropostsコントローラのdestroyアクション 」を読みます。
削除対象のDMは、現在のユーザーが受信者になっているかをチェックします。
consoleで試してみます。

>> user1 = User.third
 => #<User id: 3, name: "Vivianne Sporer", 

>> user1.received_dms
=> #<ActiveRecord::Associations::CollectionProxy [#<Dm id: 305, content: "content5", sender_id: 1, receiver_id: 3, deleted: false, created_at: "2020-11-23 23:18:33", updated_at: "2020-11-23 23:18:33">, #<Dm id: 304, content: "content4", sender_id: 1, receiver_id: 3, deleted: false, created_at: "2020-11-23 00:45:49", updated_at: "2020-11-23 00:45:49">, 

>> dm1 = user1.received_dms.find_by(id: 305)                                                                              
=> #<Dm id: 305, content: "content5", sender_id: 1, receiver_id: 3, deleted: false, created_at: "2020-11-23 23:18:33", updated_at: "2020-11-23 23:18:33">

>> dm1.nil?
=> false

削除はdeletedフラグをTRUEにする更新なので、参考にユーザーの更新を読みます。
「リスト 11.31: アカウントを有効化するeditアクション 」を参考にします。

      user.update_attribute(:activated,    true)
      user.update_attribute(:activated_at, Time.zone.now)

試しに削除してみます。

dm15.png

コンソールで調べると、deletedフラグが正しく更新されています。

>> Dm.find(305)

=> #<Dm id: 305, content: "content5", sender_id: 1, receiver_id: 3, deleted: true, created_at: "2020-11-23 23:18:33", updated_at: "2020-11-29 02:02:01">

一覧画面では削除したのに表示されたままです。
chatを変更する必要があるからと分かりました。
コンソールでSQL文を確かめます。

>>     Dm.where("sender_id = :user_id OR (receiver_id = :user_id AND deleted = :flag) ", user_id: 3, flag: false)       

chatを変更します。

app/models/user.rb
 def chat
    #Dm.where("sender_id = ?", id)
    Dm.where("sender_id = :user_id OR (receiver_id = :user_id AND deleted = :flag) ", user_id: id, flag: false)
  end

chatを変更したことで、直す必要があるところがあるかもしれないので確認していきます。
コントローラーdms_controller.rbを読みます。indexメソッドでchatを使っていますが直す必要はなさそうです。

テストを実行してみます。REDになりました。

ubuntu:~/environment/sample_app (create-dm) $ rails test
 test_DM_interface#DmsTest (2.72s)
        <Michael Example> expected but was
        <from:Michael Example>..
        Expected 0 to be >= 1.
        test/integration/dms_test.rb:54:in `block in <class:DmsTest>'

前に行った「From」を加える変更をしたときに、テストも直す必要があったようです。どうやら変更後にテストをしていなかったようです。テストを修正しGREENになりました。

test/integration/dms_test.rb
    assert_select "span.user", "from:#{@user.name}"

削除のテストを書きます。「13.3.5 フィード画面のマイクロポストをテストする」を読みます。
テストする項目の一つ目は、receiverが自分以外のユーザーのマイクロポストは削除をしようとすると、適切にリダイレクトされることです。画面にはdeleteの選択肢が出ないので、このテストの対象は、人が画面から入力するケースではなく、クローラーなどのツールからPostするケースです。

「リスト 13.54: 間違ったユーザーによるマイクロポスト削除に対してテストする 」を読んで気が付いたのですが、
ログインしていないとDMの送信も削除もできないテストも必要そうなので、合わせて作ります。

「リスト 13.31: Micropostsコントローラの認可テスト」を参考にします。

test/controllers/dms_controller_test.rb
  def setup
    @dm = dms(:morning)
  end
.. 
  test "should redirect create when not logged in" do
    assert_no_difference 'Dm.count' do
      post dms_path, params: { dm1: { content: "hogehoge",
                                      receiver_name: "hoge_receiver"  } }
    end
    assert_redirected_to login_url
  end

  test "should redirect destroy when not loggged in" do
    assert_no_difference 'Dm.count' do
      delete dm_path(@dm)
    end
    assert_redirected_to login_url
  end

  test "should redirect destroy from wrong user" do
    log_in_as(users(:michael))
    assert_no_difference 'Dm.count' do
      delete dm_path(@dm)
    end
    assert_redirected_to dms_path
  end

テストがGREENになりました。

削除のテスト作成

統合テストに削除を追加します。テスト項目は、
・DMの削除
・送信者のDMには [delete] リンクが表示されないことを確認
です。

test/integration/dms_test.rb

  test "DM interface" do
    # 受信者が削除
    assert_select 'a', text: 'delete'
    first_dm = @receiver.received_dms.first
    assert_difference ' Dm.count', -1 do
      delete dm_path(first_dm)
    end

実行するとREDになりました。deleteしても数が減っていません。

test_DM_interface#DmsTest (1.37s)
        " Dm.count" didn't change by -1.
        Expected: 34
          Actual: 35

Dmの数は変わっていなくて、削除フラグを更新していたことを思い出しました。

test/integration/dms_test.rb
    # 受信者が削除
    assert_select 'a', text: 'delete'
    first_dm = @receiver.received_dms.first
    assert_difference '@receiver.chat.count', -1  do
      delete dm_path(first_dm)
    end

GREENになりました。

送信者のDMには [delete] リンクが表示されないことを確認するテストを考えます。

送信者=受信者のケースを考えると、このテストは逆にして、
受信者が自分でないDMには[delete]リンクが表示されないことを確認
にしたほうがよいと考えました。

ユーザーの削除リンクのテストを読みます。
「[リスト 10.62: 削除リンクとユーザー削除に対する統合テスト 」にありました。

   first_page_of_users = User.paginate(page: 1)
    first_page_of_users.each do |user|
      assert_select 'a[href=?]', user_path(user), text: user.name
      unless user == @admin
        assert_select 'a[href=?]', user_path(user), text: 'delete'
      end
    end

参考にしてテストを作り、GREENになりました。

test/integration/dms_test.rb
   # 受信者ば自分でないDMは削除リンクが表示されない
    delete logout_path
    log_in_as(@user)
    get dms_path

    first_page_of_chat_items = @user.chat.paginate(page: 1)
    first_page_of_chat_items.each do |chat|
      if chat.receiver_id == @user.id 
        assert_select 'a[href=?]', dm_path(chat), text: 'delete' 
      else
        assert_select 'a[href=?]', dm_path(chat), text: 'delete', count: 0
      end
    end

すべてのテストがGREENになり、完成です。

所要時間

11/29から12/5までの5.0時間です。

メッセージ機能全体では、
10/31から12/5までの33.0時間です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0