28.话题删除的 Bug
- 本系列文章为
laracasts.com
的系列视频教程——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明
- 对应视频第 28 小节:The Activity Deletion Bug
本节内容
现在我们的系统存在一个 Bug,那就是如果我们创建了话题,然后再删除,然后访问个人页面的话就会出现 Bug。因为我们在动作流里试图关联一个被删除了的话题对象。我们来试一下。
首先创建一个话题:
查看个人页面:
删除该话题后再查看个人页面:
我们来修复这个 Bug。首先我们在删除话题的测试中增加相关测试代码:
forum\tests\Feature\CreateThreadsTest.php
.
.
/** @test */
public function authorized_users_can_delete_threads()
{
$this->signIn();
$thread = create('App\Thread',['user_id' => auth()->id()]);
$reply = create('App\Reply',['thread_id' => $thread->id]);
$response = $this->json('DELETE',$thread->path());
$response->assertStatus(204);
$this->assertDatabaseMissing('threads',['id' => $thread->id]);
$this->assertDatabaseMissing('replies',['id' => $reply->id]);
$this->assertDatabaseMissing('activities',[
'subject_id' => $thread->id,
'subject_type' => get_class($thread)
]);
}
.
.
单独运行测试:
forum\app\RecordsActivity.php
.
.
trait RecordsActivity
{
protected static function bootRecordsActivity()
{
if(auth()->guest()) return ;
foreach (static::getActivitiesToRecord() as $event){
static::$event(function ($model) use ($event){
$model->recordActivity($event);
});
}
static::deleting(function ($model){
$model->activity()->delete();
});
}
.
.
我们在Trait
中进行监听对应模型的deleting
事件,所以当thread
被删除时我们会将相关的动作流也进行删除。我们再次测试:
我们的 Bug 修复了吗?没有完全修复。因为当thread
被删除时,与该thread
相关的回复也会被删除,但是该回复的动作流却不会被删除。我们进一步进行修复:
forum\tests\Feature\CreateThreadsTest.php
.
.
/** @test */
public function authorized_users_can_delete_threads()
{
$this->signIn();
$thread = create('App\Thread',['user_id' => auth()->id()]);
$reply = create('App\Reply',['thread_id' => $thread->id]);
$response = $this->json('DELETE',$thread->path());
$response->assertStatus(204);
$this->assertDatabaseMissing('threads',['id' => $thread->id]);
$this->assertDatabaseMissing('replies',['id' => $reply->id]);
$this->assertDatabaseMissing('activities',[
'subject_id' => $thread->id,
'subject_type' => get_class($thread)
]);
$this->assertDatabaseMissing('activities',[
'subject_id' => $reply->id,
'subject_type' => get_class($reply)
]);
}
.
.
forum\app\Thread.php
.
.
protected static function boot()
{
parent::boot();
static::addGlobalScope('replyCount',function ($builder){
$builder->withCount('replies');
});
static::deleting(function ($thread) {
$thread->replies->each->delete();
});
}
.
.
我们把批量删除与话题关联的回复改为逐条删除,使得Reply
模型的deleting
事件被监听到,从而删除与该回复相关的动作流。我们再次运行测试:
我们还能让测试更简洁一些:
forum\tests\Feature\CreateThreadsTest.php
.
.
/** @test */
public function authorized_users_can_delete_threads()
{
$this->signIn();
$thread = create('App\Thread',['user_id' => auth()->id()]);
$reply = create('App\Reply',['thread_id' => $thread->id]);
$response = $this->json('DELETE',$thread->path());
$response->assertStatus(204);
$this->assertDatabaseMissing('threads',['id' => $thread->id]);
$this->assertDatabaseMissing('replies',['id' => $reply->id]);
$this->assertEquals(0,Activity::count());
}
.
.
运行全部测试:
现在 Bug 已经修复,你可以再次创建一个话题,并进行回复,然后删除该话题,查看个人页面进行确认。
注:在测试之前要先把最开始测试时生成的那条动作流从
activities
表中删除