-
-
Notifications
You must be signed in to change notification settings - Fork 174
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
[BUGFIX] Change factoryFor to use factoryFor().create() #443
[BUGFIX] Change factoryFor to use factoryFor().create() #443
Conversation
@@ -189,6 +189,14 @@ function normalizeOptions(validations = {}, globalOptions = {}) { | |||
}); | |||
} | |||
|
|||
function classProperty(value, property) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BaseValidator requires this since it's imported and so does not go through factoryFor
. This method knows how to deal with reading constructor props off types output from factoryFor and regular types.
@@ -2,13 +2,30 @@ | |||
Utility to use `ApplicationInstance#factoryFor` if available (2.12+) and | |||
fallback to private `_lookupFactory` otherwise | |||
*/ | |||
export default function factoryFor(owner, type) { | |||
let factory; | |||
class LegacyFactoryForWrapper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mocks the same public API that we rely on so we can consistently use class/create throughout the rest of the app.
if (owner.factoryFor) { | ||
let maybeFactory = owner.factoryFor(type); | ||
factory = maybeFactory && maybeFactory.class; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug stemmed from this since we end up trying to instantiate object from maybeFactory.class
which do not carry forward the owner. What we want is really to return maybeFactory
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that factoryFor
was a drop-in replacement. Let me ask someone that understands the new feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is if you're not accessing props off the class, which is only available now via the class prop. Instances should not be created from that class prop AFAIK and which led to the owner not being injected.
@jasonmit this is a sleek approach but im not sure if its too much? To make the solution and code readability simpler, would it not be easier to just assume the no class returned from the factory carries over the owner and force inject it on create instead via May I'm just missing something here... @rwjblue have you thought of polyfilling |
Unsure what you mean by "assume the no class returned from the factory carries over the owner". |
Any attempt to return the owner from the class would introduce an unnecessary extend which would defeat the new factoryFor API. |
I think that we might not understand the new factory for. I've asked for help in slack and linked the original issue. Let's see what experts say is the right way of having the owner injected. I suspect that this might be because of the |
Should then, while we wait, revert the factoryFor PR as there is problems with anyone relying on the owner (i.e., inject.service) into validators. |
@jasonmit what I meant is that we just force inject the owner on create no matter what the situation is since we have access to the owner regardless. That should simplify the problem for now until we get a better alternative. factoryFor('validator:presence').create(owner.ownerInjection(), options); Same thing for the Messages class. Thoughts? |
For the record, @rwjblue explained me the Revert the change if you want, but I'm going to work on this in a moment. I want to create a failing test case first. |
Im not at my computer right now so I will look into this more in a few hours. Im curious to see if the returned object from factoryFor is a proxy of the class. If so, the solution here is just return owner.factoryFor ? owner.factoryFor(type) : owner_lookupFactory(type); Will report back once I have some answers. |
Unsure, but I'd say that mimics the behavior of the old API versus embracing the new API which could lead to other unknowns.
This will not work as the proxy throws (by design) when accessing anything other than The implementation asserting gets/sets: |
FWIW, I am working on a polyfill now to provide the new API to older Ember versions. Hope to have it published later today... |
https://github.com/rwjblue/ember-factory-for-polyfill should do the trick... |
PR updated with @rwjblue's polyfill. If everyone is in agreement on it I'll write some tests. |
@@ -564,7 +563,7 @@ function getCPDependentKeysFor(attribute, model, validations) { | |||
let dependentKeys = validations.map((validation) => { | |||
let { options } = validation; | |||
let type = validation._type; | |||
let Validator = type === 'function' ? BaseValidator : lookupValidator(owner, type); | |||
let Validator = type === 'function' ? BaseValidator : lookupValidator(owner, type).class; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need class here? I think I don't fully grasp when the proxied object is enough and when it isn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See: #443 (comment)
In this line, cp-validations is accessing constructor props, and has nothing to do with instantiating validators, which cannot be done on anything other than the constructor which lives off class
and not the factory manager. This is by the spec as mentioned in the comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand. In this case you are not getting the factory to create an instance of that class, you want to read some information from the class itself.
I'll keep working on this tonight, but I suspect that the polyfill doesn't support Ember < 2.3 yet (though I haven't tested). |
@rwjblue yup, the polyfill looks to fail with <= 2.0. |
} | ||
|
||
// If for some reason, we can't find the messages object (i.e. unit tests), use default | ||
errorMessages = errorMessages || Messages; | ||
errorMessages = errorMessages && errorMessages.class ? errorMessages : Messages; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once my PR into the polyfill is versioned, this line can be reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Published as v1.0.2.
FWIW LGTM |
Build is failing for Ember <= 2.0. Looks like the polyfill isnt being injected at all. cc @rwjblue |
ZOMG, should be working now. ember-polyfills/ember-getowner-polyfill#18 + ember-polyfills/ember-factory-for-polyfill@v1.0.2...v1.1.0. We will need to bump to ember-getowner-polyfill@1.2.0 though. |
Including only getowner polyfill should work, but I'd definitely appreciate testing. The coupling is somewhat complicated, and it's definitely possible that I've mucked something up. |
@offirgolan PR updated. Thanks. |
Released in |
Discussion: jasonmit/ember-i18n-cp-validations#29
This will extend types, with the owner preserved, while still allowing us to access class properties.
Squash on merge.