Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with listeningToModelEvents([ ]) #29

Closed
dreamingmind opened this issue Dec 3, 2020 · 10 comments
Closed

Problem with listeningToModelEvents([ ]) #29

dreamingmind opened this issue Dec 3, 2020 · 10 comments

Comments

@dreamingmind
Copy link
Contributor

dreamingmind commented Dec 3, 2020

Using the test code:

$LocationsTable = LocationFactory::make()
    ->listeningToModelEvents(
        [
            'Model.beforeSave' => 'beforeSave',
        ]
    )
    ->persist();

the event is failing to run.

In an attempt to find the problem, I looked at the EventCollector after the listeningToModelEvents() method ran and saw this:

object(CakephpFixtureFactories\Factory\EventCollector) id:0 {
  private listeningBehaviors => [
    (int) 0 => 'Timestamp'
  ]
  private listeningModelEvents => [
    'Model.beforeSave' => 'beforeSave'
  ]
  private defaultListeningBehaviors => [
    (int) 0 => 'Timestamp'
  ]
  private factory => object(App\Test\Factory\LocationFactory) id:1 {
    protected applyListenersAndBehaviors => false
    protected marshallerOptions => [
      'validate' => false,
      'forceNew' => true
    ]
    protected saveOptions => [
      'checkRules' => false,
      'atomic' => false,
      'checkExisting' => false
    ]
    protected withModelEvents => false
  }
  private rootTableRegistryName => 'Locations'
}

The last property of the LocationFactory reads protected withModelEvents => false.

Based on this information I set LocationFactory::withModelEvents to true and the events ran properly. With this property set it does not matter whether I use the method listeningToModelEvents().

Either the code is wrong or this section of the documentation is wrong.

@pabloelcolombiano
Copy link
Collaborator

@dreamingmind which version of the Plugin are you using? Have you tried with the latest?

@dreamingmind
Copy link
Contributor Author

Ach! I'll get back to you on this. Probably my error.

@pabloelcolombiano
Copy link
Collaborator

O.K., I'll close it for the moment, feel free to re-open!

@dreamingmind
Copy link
Contributor Author

My issue appears to be with associated tables failing to run configured events.

I have a record Items which hasMany('Skus'). Skus are configured to use events in this way:

protected function setDefaultTemplate(): void
{
    $this->setDefaultData(function(Generator $faker) {
        return [
//          'hash' => $faker->text(20), //this should be set by the event
            'name' => $faker->text(15),
            'code' => $faker->text(5),
        ];
    })
        ->listeningToModelEvents(['Model.beforeSave']);
}

This code produces all the required records but does not run the events for Skus:

//In a test class
    public function testItem()
    {
        ItemFactory::make()->standAloneItem()->persist();
    }

//in the ItemFactory
    public function standAloneItem($parameter = null, int $n = 1): ItemFactory
    {
        return $this
            ->withPrimarySku()
            ->with('Tenant.Warehouse');
    }

    public function withPrimarySku($parameter = null): ItemFactory
    {
        return $this->with(
            'PrimarySku',
            \App\Test\Factory\SkuFactory::make(['base_sku' => 1])
        );
    }

If I call the SkuFactory directly, the configured events will run.

This code for example will produce one sku without the event running and a second with the event running.

    public function testSku() {
        $item = ItemFactory::make()->standAloneItem()->persist();
        SkuFactory::make(['item_id' => $item->id, 'tenant_id' => $item->tenant->id])->persist();
    }

I'm currently in Cake 4.1.6 and FixtureFactory 2.1.0

@dreamingmind
Copy link
Contributor Author

I don't know how to re-open this issue. Should I just make a new one?

@pabloelcolombiano
Copy link
Collaborator

pabloelcolombiano commented Dec 9, 2020

@dreamingmind I see your issue. The event manager will apply events to the main factory, but not to its associations.

Therefore, in testSku(), the event is not triggered when Skus are associated, but triggered when called directly.

I agree that this behavior of the package is wrong, since per default the SkuFactory listens to the beforeSave event. The event should be triggered.

I suggest as a turn around that you explicitly enable the event in your ItemFactory as follows

public function withPrimarySku($parameter = null): ItemFactory
    {
        return $this->with(
            'PrimarySku',
            \App\Test\Factory\SkuFactory::make(['base_sku' => 1])->listeningToModelEvents('Model.beforeSave')
        );
    }

Does this trigger the beforeSave event?

I have re-opened the issue and will work in the coming days on a fix.

@pabloelcolombiano
Copy link
Collaborator

@dreamingmind I have added a few tests to make sure that the model events were triggered in associations too. They are, including when the event is activated in the defautl template.

You can have a look here:
https://github.com/vierge-noire/cakephp-fixture-factories/blob/master/tests/TestCase/Factory/EventCollectorTest.php#L329

You can ignore my previous post. The error seems to be on your side. Which version of the plugin do you use? Do you use the latest v2.1.0 (v1.1.0 on Cake3)?

@dreamingmind
Copy link
Contributor Author

Ok. I'm digging deeper. I've pulled your recent code and see the passing test. I'll see if I can either figure out what's wrong or write a failing test.

@pabloelcolombiano
Copy link
Collaborator

@dreamingmind can I close this for now?

@dreamingmind
Copy link
Contributor Author

Yes. I got sidetracked on another time sensitive task and will open a new issue if my research turns something up.

The two specific details I will look into is the use of a static callable in the event handler and the triggering of an event that is more than 1 association away.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants