Skip to content

Commit a396da1

Browse files
authored
Merge pull request #17 from carsdotcom/issue-16
fix: refresh has to invalidate json model attribute cache
2 parents 5a16df6 + 82be87e commit a396da1

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

app/Traits/HasJsonModelAttributes.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,14 @@ public function isEmpty(): bool
355355
{
356356
return collect($this->jsonModelAttributeCache)->every->isEmpty() && parent::isEmpty();
357357
}
358+
359+
/**
360+
* The Laravel method ->refresh tries to reuse the object reference while reloading data from disk.
361+
* Reload the new cache this attribute introduces, too.
362+
*/
363+
public function refresh(): static
364+
{
365+
$this->emptyJsonModelAttributeCache();
366+
return parent::refresh();
367+
}
358368
}

tests/Unit/Traits/HasJsonModelAttributesTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Tests\BaseTestCase;
1616
use Tests\MockClasses\ConcreteJsonModel;
1717
use Tests\MockClasses\ConcreteNullableJsonModel;
18+
use Tests\MockClasses\EventedModelWithJsonAttributes;
1819

1920
/**
2021
* Class HasJsonModelAttributes
@@ -424,4 +425,23 @@ public function testAttributeCanBeTestedWithIsset()
424425
self::assertFalse($model->jsonModel->a ?? false);
425426
self::assertFalse($model->jsonModel->other ?? false);
426427
}
428+
429+
public function testAttributeIsResetByRefresh()
430+
{
431+
$model = mock(EventedModelWithJsonAttributes::class)->makePartial()->shouldAllowMockingProtectedMethods();
432+
// We're mocking the guts of Model::refresh to not actually require a database
433+
$model->shouldReceive('setKeysForSelectQuery')->once()->andReturnSelf();
434+
$model->shouldReceive('useWritePdo')->andReturnSelf();
435+
$model->shouldReceive('firstOrFail')->andReturn((object)['attributes' => ['thing' => ['a' => "aneurysm"]]]);
436+
437+
$model->thing->a = "Apple";
438+
self::assertSame("Apple", $model->thing->a);
439+
440+
// You have to tell the model it exists (on disk) or refresh doesn't do anything.
441+
$model->exists = true;
442+
// The change wasn't saved, the model reverts to "disk"
443+
$model->refresh();
444+
self::assertEmpty(getProperty($model, 'jsonModelAttributeCache'));
445+
self::assertSame('aneurysm', $model->thing->a);
446+
}
427447
}

0 commit comments

Comments
 (0)