Skip to content

Commit

Permalink
Merge pull request #56 from dbushy727/support-closures-for-model-data
Browse files Browse the repository at this point in the history
Support closures for model data
  • Loading branch information
christophrumpel authored Jul 2, 2020
2 parents 1139add + 627161f commit 38d5407
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 14 deletions.
32 changes: 32 additions & 0 deletions example/tests/Factories/IngredientFactoryUsingClosure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace ExampleAppTests\Factories;

use Christophrumpel\LaravelFactoriesReloaded\BaseFactory;
use ExampleApp\Models\Ingredient;
use Faker\Generator;

class IngredientFactoryUsingClosure extends BaseFactory
{
protected string $modelClass = Ingredient::class;

public function create(array $extra = []): Ingredient
{
return parent::build($extra);
}

public function make(array $extra = []): Ingredient
{
return parent::build($extra, 'make');
}

public function getDefaults(Generator $faker): array
{
return [
'name' => 'Pasta',
'description' => function (array $ingredient) {
return "Super delicious {$ingredient['name']}";
},
];
}
}
2 changes: 1 addition & 1 deletion src/BaseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static function new(): self

protected function build(array $extra = [], string $creationType = 'create')
{
$modelData = $this->transformFactoriesToRelationIds(
$modelData = $this->transformModelFields(
array_merge($this->getDefaults($this->faker), $this->overwriteDefaults, $extra)
);
$model = $this->unguardedIfNeeded(fn () => $this->modelClass::$creationType($modelData));
Expand Down
34 changes: 24 additions & 10 deletions src/TranslatesFactoryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,30 @@ private static function isFactory($item): bool
return $item instanceof BaseFactory || $item instanceof FactoryBuilder;
}

private function transformFactoriesToRelationIds(array $defaultModelFields): array
private static function isCallable($field): bool
{
return collect($defaultModelFields)
->map(function ($item) {
if ($this->isFactory($item)) {
return $item->create()->getKey();
}

return $item;
})
->toArray();
return is_callable($field) && ! is_string($field) && ! is_array($field);
}

private function transformModelFields(array $defaultModelFields): array
{
foreach ($defaultModelFields as &$field) {
$field = $this->transformField($field, $defaultModelFields);
}

return $defaultModelFields;
}

private function transformField($field, array $defaultModelFields)
{
if ($this->isFactory($field)) {
return $field->create()->getKey();
}

if ($this->isCallable($field)) {
return $field($defaultModelFields);
}

return $field;
}
}
32 changes: 29 additions & 3 deletions tests/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

namespace Christophrumpel\LaravelFactoriesReloaded\Tests;

use ExampleApp\Models\Group;
use ExampleApp\Models\Ingredient;
use ExampleApp\Models\Recipe;
use ExampleAppTests\Factories\GroupFactory;
use ExampleAppTests\Factories\GroupFactoryUsingFaker;
use ExampleAppTests\Factories\IngredientFactoryUsingClosure;
use ExampleAppTests\Factories\RecipeFactory;
use ExampleAppTests\Factories\RecipeFactoryUsingFactoryForRelationship;
use ExampleAppTests\Factories\RecipeFactoryUsingLaravelFactoryForRelationship;
use ExampleApp\Models\Group;
use ExampleApp\Models\Ingredient;
use ExampleApp\Models\Recipe;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
Expand Down Expand Up @@ -192,6 +193,31 @@ public function it_lets_you_use_faker_for_defining_data(): void
$this->assertIsString($group->mobile);
}

/** @test * */
public function it_lets_you_use_a_closure_for_defining_default_data(): void
{
$ingredient = IngredientFactoryUsingClosure::new()->create();

$this->assertIsString($ingredient->name);
$this->assertIsString($ingredient->description);
$this->assertEquals($ingredient->name, 'Pasta');
$this->assertEquals($ingredient->description, 'Super delicious Pasta');
}

/** @test * */
public function it_lets_you_use_a_closure_for_overriding_default_data(): void
{
$ingredient = IngredientFactoryUsingClosure::new()->create([
'name' => fn (array $ingredient) => 'Basil',
'description' => fn (array $ingredient) => "Super delicious {$ingredient['name']}",
]);

$this->assertIsString($ingredient->name);
$this->assertIsString($ingredient->description);
$this->assertEquals($ingredient->name, 'Basil');
$this->assertEquals($ingredient->description, 'Super delicious Basil');
}

/** @test * */
public function it_lets_you_add_a_related_model(): void
{
Expand Down

0 comments on commit 38d5407

Please sign in to comment.