Skip to content

Commit

Permalink
Merge branch 'model-factory-add-after' of https://github.com/Indemnit…
Browse files Browse the repository at this point in the history
…y83/framework into Indemnity83-model-factory-add-after
  • Loading branch information
taylorotwell committed Mar 12, 2018
2 parents 896d817 + 889970a commit 36163b9
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 4 deletions.
29 changes: 28 additions & 1 deletion src/Illuminate/Database/Eloquent/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ class Factory implements ArrayAccess
*/
protected $states = [];

/**
* The registered callbacks.
*
* @var array
*/
protected $after = [];

/**
* The Faker instance for the builder.
*
Expand Down Expand Up @@ -97,6 +104,26 @@ public function state($class, $state, $attributes)
return $this;
}

/**
* Define a callback to run after an action.
*
* @param string $class
* @param string $action
* @param callable $callback
* @return $this
*/
public function after($class, $action, $callback = null)
{
if (is_callable($action) && $callback === null) {
$callback = $action;
$action = 'create';
}

$this->after[$class][$action] = $callback;

return $this;
}

/**
* Create an instance of the given model and persist it to the database.
*
Expand Down Expand Up @@ -184,7 +211,7 @@ public function raw($class, array $attributes = [], $name = 'default')
*/
public function of($class, $name = 'default')
{
return new FactoryBuilder($class, $name, $this->definitions, $this->states, $this->faker);
return new FactoryBuilder($class, $name, $this->definitions, $this->states, $this->after, $this->faker);
}

/**
Expand Down
40 changes: 37 additions & 3 deletions src/Illuminate/Database/Eloquent/FactoryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ class FactoryBuilder
*/
protected $states;

/**
* The model callbacks.
*
* @var array
*/
protected $after = [];

/**
* The states to apply.
*
Expand Down Expand Up @@ -76,13 +83,14 @@ class FactoryBuilder
* @param \Faker\Generator $faker
* @return void
*/
public function __construct($class, $name, array $definitions, array $states, Faker $faker)
public function __construct($class, $name, array $definitions, array $states, array $after, Faker $faker)
{
$this->name = $name;
$this->class = $class;
$this->faker = $faker;
$this->states = $states;
$this->definitions = $definitions;
$this->after = $after;
}

/**
Expand Down Expand Up @@ -149,8 +157,10 @@ public function create(array $attributes = [])

if ($results instanceof Model) {
$this->store(collect([$results]));
$this->applyAfter(collect([$results]), 'create');
} else {
$this->store($results);
$this->applyAfter($results, 'create');
}

return $results;
Expand Down Expand Up @@ -182,16 +192,22 @@ protected function store($results)
public function make(array $attributes = [])
{
if ($this->amount === null) {
return $this->makeInstance($attributes);
$instance = $this->makeInstance($attributes);
$this->applyAfter(collect([$instance]), 'make');

return $instance;
}

if ($this->amount < 1) {
return (new $this->class)->newCollection();
}

return (new $this->class)->newCollection(array_map(function () use ($attributes) {
$instances = (new $this->class)->newCollection(array_map(function () use ($attributes) {
return $this->makeInstance($attributes);
}, range(1, $this->amount)));
$this->applyAfter($instances, 'make');

return $instances;
}

/**
Expand Down Expand Up @@ -328,4 +344,22 @@ protected function expandAttributes(array $attributes)

return $attributes;
}

/**
* Run after callback on a collection of models.
*
* @param \Illuminate\Support\Collection $models
* @param string $action
* @return void
*/
public function applyAfter($models, $action)
{
$models->each(function ($model) use ($action) {
if (! isset($this->after[$this->class][$action])) {
return;
}

call_user_func_array($this->after[$this->class][$action], [$model, $this->faker]);
});
}
}
98 changes: 98 additions & 0 deletions tests/Integration/Database/EloquentFactoryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ protected function getEnvironmentSetUp($app)
];
});

$factory->define(FactoryBuildableProfile::class, function (Generator $faker) {
return [
'user_id' => function () {
return factory(FactoryBuildableUser::class)->create()->id;
},
];
});

$factory->after(FactoryBuildableUser::class, 'make', function (FactoryBuildableUser $user, Generator $faker) {
$profile = factory(FactoryBuildableProfile::class)->make(['user_id' => $user->id]);
$user->setRelation('profile', $profile);
});

$factory->define(FactoryBuildableTeam::class, function (Generator $faker) {
return [
'name' => $faker->name,
'owner_id' => function () {
return factory(FactoryBuildableUser::class)->create()->id;
},
];
});

$factory->after(FactoryBuildableTeam::class, function (FactoryBuildableTeam $team, Generator $faker) {
$team->users()->attach($team->owner);
});

$factory->define(FactoryBuildableServer::class, function (Generator $faker) {
return [
'name' => $faker->name,
Expand Down Expand Up @@ -72,6 +98,23 @@ public function setUp()
$table->string('email');
});

Schema::create('profiles', function ($table) {
$table->increments('id');
$table->unsignedInteger('user_id');
});

Schema::create('teams', function ($table) {
$table->increments('id');
$table->string('name');
$table->string('owner_id');
});

Schema::create('team_users', function ($table) {
$table->increments('id');
$table->unsignedInteger('team_id');
$table->unsignedInteger('user_id');
});

Schema::connection('alternative-connection')->create('users', function ($table) {
$table->increments('id');
$table->string('name');
Expand Down Expand Up @@ -183,6 +226,14 @@ public function creating_models_on_custom_connection()
$this->assertTrue($user->is($dbUser));
}

/** @test **/
public function creating_models_with_after_callback()
{
$team = factory(FactoryBuildableTeam::class)->create();

$this->assertTrue($team->users->contains($team->owner));
}

/** @test */
public function making_models_with_a_custom_connection()
{
Expand All @@ -192,6 +243,14 @@ public function making_models_with_a_custom_connection()

$this->assertEquals('alternative-connection', $user->getConnectionName());
}

/** @test **/
public function making_models_with_after_callback()
{
$user = factory(FactoryBuildableUser::class)->make();

$this->assertNotNull($user->profile);
}
}

class FactoryBuildableUser extends Model
Expand All @@ -204,6 +263,45 @@ public function servers()
{
return $this->hasMany(FactoryBuildableServer::class, 'user_id');
}

public function profile()
{
return $this->hasOne(FactoryBuildableProfile::class, 'user_id');
}
}

class FactoryBuildableProfile extends Model
{
public $table = 'profiles';
public $timestamps = false;
protected $guarded = ['id'];

public function user()
{
return $this->belongsTo(FactoryBuildableUser::class, 'user_id');
}
}

class FactoryBuildableTeam extends Model
{
public $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];

public function owner()
{
return $this->belongsTo(FactoryBuildableUser::class, 'owner_id');
}

public function users()
{
return $this->belongsToMany(
FactoryBuildableUser::class,
'team_users',
'team_id',
'user_id'
);
}
}

class FactoryBuildableServer extends Model
Expand Down

0 comments on commit 36163b9

Please sign in to comment.