Skip to content

Commit

Permalink
Merge pull request #773 from Tofandel/patch-2
Browse files Browse the repository at this point in the history
Avoid loading already loaded relations and allow loading non studly relation names
  • Loading branch information
rubenvanassche authored Jun 13, 2024
2 parents 8ff9118 + 7c4a354 commit 214d69e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ jobs:
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
- name: Execute tests
run: vendor/bin/pest
run: vendor/bin/pest --enforce-time-limit --fail-on-risky
33 changes: 15 additions & 18 deletions src/Normalizers/Normalized/NormalizedModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function getProperty(string $name, DataProperty $dataProperty): mixed

protected function initialize(Model $model): void
{
$this->properties = $model->toArray();
$this->properties = $model->withoutRelations()->toArray();

foreach ($model->getDates() as $key) {
if (isset($this->properties[$key])) {
Expand All @@ -49,14 +49,6 @@ protected function initialize(Model $model): void
}
}
}

foreach ($model->getRelations() as $key => $relation) {
$key = $model::$snakeAttributes ? Str::snake($key) : $key;

if (isset($this->properties[$key])) {
$this->properties[$key] = $relation;
}
}
}

protected function isDateCast(string $cast): bool
Expand All @@ -77,18 +69,23 @@ protected function fetchNewProperty(string $name, DataProperty $dataProperty): m
return $this->properties[$name] = $this->model->getAttribute($name);
}

if (! $dataProperty->attributes->contains(fn (object $attribute) => $attribute::class === LoadRelation::class)) {
return UnknownProperty::create();
}

$studlyName = Str::studly($name);
$camelName = Str::camel($name);

if (! method_exists($this->model, $studlyName)) {
return UnknownProperty::create();
if ($dataProperty->attributes->contains(fn (object $attribute) => $attribute::class === LoadRelation::class)) {
if (method_exists($this->model, $name)) {
$this->model->loadMissing($name);
} elseif (method_exists($this->model, $camelName)) {
$this->model->loadMissing($camelName);
}
}

$this->model->load($studlyName);
if ($this->model->relationLoaded($name)) {
return $this->properties[$name] = $this->model->getRelation($name);
}
if ($this->model->relationLoaded($camelName)) {
return $this->properties[$name] = $this->model->getRelation($camelName);
}

return $this->properties[$name] = $this->model->{$studlyName};
return $this->properties[$name] = UnknownProperty::create();
}
}
5 changes: 5 additions & 0 deletions tests/Fakes/Models/FakeModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public function fakeNestedModels(): HasMany
return $this->hasMany(FakeNestedModel::class);
}

public function alt_fake_nested_models(): HasMany
{
return $this->hasMany(FakeNestedModel::class);
}

public function accessor(): Attribute
{
return Attribute::get(fn () => "accessor_{$this->string}");
Expand Down
27 changes: 25 additions & 2 deletions tests/Normalizers/ModelNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@
->date->toEqual($data->date);
});

it('does not loop infinitely on relations', function () {
$m1 = FakeModel::factory()->makeOne();
$m2 = FakeNestedModel::factory()->makeOne();
$m2->setRelation('parent', $m1);
$m1->setRelation('pivot', $m2);

$data = FakeModelData::from($m1);

expect($m1)
->string->toEqual($data->string)
->nullable->toEqual($data->nullable)
->date->toEqual($data->date);

});

it('can get a data object with nesting from model and relations when loaded', function () {
$model = FakeModel::factory()->create();

Expand Down Expand Up @@ -103,8 +118,12 @@
$dataClass = new class () extends Data {
#[LoadRelation, DataCollectionOf(FakeNestedModelData::class)]
public array $fake_nested_models;

#[LoadRelation, DataCollectionOf(FakeNestedModelData::class)]
public array $alt_fake_nested_models;
};

$model->load('alt_fake_nested_models');
DB::enableQueryLog();

$data = $dataClass::from($model);
Expand All @@ -114,6 +133,10 @@
expect($data->fake_nested_models)
->toHaveCount(2)
->each->toBeInstanceOf(FakeNestedModelData::class);

expect($data->alt_fake_nested_models)
->toHaveCount(2)
->each->toBeInstanceOf(FakeNestedModelData::class);
expect($queryLog)->toHaveCount(1);
});

Expand Down Expand Up @@ -154,8 +177,8 @@
it('can use mappers to map the names', function () {
$model = FakeModel::factory()->create();

$nestedModelA = FakeNestedModel::factory()->for($model)->create();
$nestedModelB = FakeNestedModel::factory()->for($model)->create();
FakeNestedModel::factory()->for($model)->create();
FakeNestedModel::factory()->for($model)->create();

$dataClass = new class () extends Data {
#[DataCollectionOf(FakeNestedModelData::class), MapInputName(SnakeCaseMapper::class)]
Expand Down

0 comments on commit 214d69e

Please sign in to comment.