-
Notifications
You must be signed in to change notification settings - Fork 0
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
Implement initial default adapter for upcoming adapter pattern #51
Implement initial default adapter for upcoming adapter pattern #51
Conversation
Signed-off-by: Brandon Duff <[email protected]>
Great PR description! 💯 |
|
||
expect(abort).toHaveBeenCalledTimes(0); | ||
expect(stubAdapter.fetchCollection).toHaveBeenCalledWith('posts', { | ||
dispatch: jasmine.any(Function), |
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.
If anyone looking this code over has a good idea for testing that correct dispatch and getState were passed into this and every other action, feel free to suggest it. This is my solution for now since it turns out the dispatch passed in from the param of a called thunk is not the same as the dispatch that is evoked on line 81 above.
We could also call this.fetch(arguments)(dispatchSpy, getStateSpy) and that should do the trick, but I don't know if that's needed.
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.
Yeah, I think we're fine for now. Appreciate the comment, it will be good for historical context if it is ever dug up.
- pass the adapter to collection fetch from make_brainstem_type - fix code formatting issues around indentations and trailing commas Signed-off-by: Ellie Day <[email protected]>
Signed-off-by: Bobby Brown <[email protected]>
… state - fix lint error around lengthy line of code in make brainstem type Signed-off-by: Ellie Day <[email protected]>
…ded methods in model actions for adapter pattern
spec/actions/model-spec.js
Outdated
@@ -205,7 +205,7 @@ describe('model action creators', () => { | |||
this.destroy = modelActions.destroy; | |||
}); | |||
|
|||
it('calls destroy on the adapter', function () { | |||
it('calls destroy on the adapter', () => { |
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.
uh, bad merge conflict? Let's not nest it
blocks!
spec/actions/model-spec.js
Outdated
const xhr = dispatch(); | ||
expect(xhr.done).toEqual(jasmine.any(Function)); | ||
expect(xhr.fail).toEqual(jasmine.any(Function)); | ||
it('calls destroy on the adapter', () => { |
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.
What is going on here.
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.
There are nested it
specs in it
specs. Can we fix that?
spec/actions/model-spec.js
Outdated
this.destroy = modelActions.destroy; | ||
}); | ||
|
||
it('calls destroy on the adapter', () => { |
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.
What is going on here.
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.
To reply to your past few comments re: "what is going on here", I'd suggest looking at the diff side by side as it will be easier to see that the existing specs were wrapped in an additional describe block. This causes the diff to appear a bit wonky, which you've likely seen before. I hope that clears things up!
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.
There are nested it
specs in it
specs. Can we fix that?
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.
Ah, I see what you mean. Fixed it!
@juanca, this PR is nearly ready for a review, so I'll be sure to ping you in the next day or so when it's all cleaned up. There aren't plans to add much more to this PR. If you're curious, an adapter implementation is in progress here: https://github.com/mavenlink/mavenlink/pull/10353 |
@juanca, this is ready for a final look over. I've published a beta with a version of |
Can you verify that the examples are working? |
|
||
if (postFetchAction) xhr.done(collection => dispatch(postFetchAction(collection.pluck('id')))); | ||
if (postFetchAction) { | ||
xhr.done(collection => |
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.
How is .done
going to work when the XHR is not from jQuery?
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.
We have our mavenlink adapter return a deferred object like so:
fetchCollection: (brainstemKey, { dispatch, fetchOptions }) => {
const deferred = $.Deferred();
networkHelpers.fetchFromAPI(baseUrl, { params: fetchOptions.params, method: 'GET' })
.then((result) => {
dispatch(brainstemActions.syncCollections(result));
deferred.resolve(result[brainstemKey]);
});
return deferred;
},
|
||
if (trackKey) xhrs[trackKey] = xhr; | ||
|
||
return new Promise((resolve, reject) => xhr | ||
.done(collection => resolve(collection.map(model => model.attributes))) | ||
.done(collection => resolve(adapter.collectionToArray(collection))) |
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.
What's the use-case for overriding collection.map
? EDIT: And I'm assuming it's the same for overriding model.get('id')
?
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.
We are delegating the handling of items in a collection to the adapter. Brainstem redux is now indifferent to the shape of the collection being passed in.
@@ -1,4 +1,4 @@ | |||
const { StorageManager } = require('brainstem-js'); |
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.
Removing the dependency to the StorageManager
is fantastic! I know it's outta scope so I made a follow-up issue about removing it from the defaults as well:
lib/adapters/default.js
Outdated
fetchCollection: (brainstemKey, options) => { | ||
const storageManager = StorageManager.get(); | ||
return storageManager.storage(brainstemKey) | ||
.fetch(Object.assign(options.fetchOptions, { remove: false })); |
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.
We should never be modifying anything we don't own -- unless you can guarantee that the object is thrown away.
Let's make sure we're cloning and creating a new object.
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.
Oh, I see that's how it was before. Let's still make the edit -- it happens that the previous code had a mistake.
lib/reducers/sync-collections.js
Outdated
|
||
collectionNames.forEach((collectionName) => { | ||
mergedCollections[collectionName] = { | ||
...state[collectionName], |
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 don't think we've added ES6 spreads as dependencies.
Let's switch these to Object.assign
.
@@ -114,10 +114,21 @@ describe('makeBrainstemType', () => { | |||
}); | |||
|
|||
it('forwards the request to brainstem-redux', () => { | |||
const options = 'OPTIONS'; | |||
const options = { stuff: 'options' }; |
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.
This teaches me a lesson to use stubbed data objects that are similar to the real life object.
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.
Juanca = 👨🎓
(says Bobby)
spec/actions/model-spec.js
Outdated
this.save = modelActions.save; | ||
}); | ||
|
||
it('send save to the subscriber for the existing model', function () { |
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.
sends*
…ginal objects Signed-off-by: Ellie Day <[email protected]>
Signed-off-by: Bobby Brown <[email protected]>
Signed-off-by: Ellie Day <[email protected]>
lib/types/make-brainstem-type.js
Outdated
@@ -7,9 +7,16 @@ const defaultTypeOptions = { | |||
}; | |||
|
|||
module.exports = function makeBrainstemType(brainstemKey, typeOptions = defaultTypeOptions) { | |||
const mergedOptions = { ...defaultTypeOptions, ...typeOptions }; |
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.
Object.assign
and the rest of the spreads please.
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.
Contingent on no usage of ...
operators
…isting object Signed-off-by: Bobby Brown <[email protected]>
…ainstem-redux into add_adapter_pattern
…redux into add_adapter_pattern
Signed-off-by: Ellie Day <[email protected]>
Make options object as second param of makeBrainstemType
Signed-off-by: Ellie Day <[email protected]>
Re-merge to correctly merge adapter pattern (PR #51) into master
Summary
This PR includes changes to the model and collection actions present in this repo. Specifically, an "adapter pattern" has been introduced to allow the invoker of the above-mentioned actions to provide an adapter that responds to a standard set of method calls, like
adapter.fetchCollection
oradapter.saveModel
with the purpose of syncing records with a remote brainstem backend.Usage of this pattern moves the process of syncing from within these model and collection actions to a given adapter.
The motivation for this change is to allow usage of
brainstem-redux
without the involvement of StorageManager/Backbone. Using Backbone models through StorageManager is a detriment to application performance when a large number of records are loaded into the front-end. This change will allow Mavenlink (or others) to write a custom adapter that bypasses StorageManager and loads many records directly into state.brainstem in a more performant manner.While this is a substantial change to how
brainstem-redux
can function, all existing functionality provided by this library will be preserved as the default behavior. This is achieved by providing a default adapter to each action that calls the existing StorageManager-specific code. So while it is possible to use a custom adapter, the backbone-centric implementation will continue to the default option, ensuring backwards compatibility.Test plan
This behavior is verified through tests that verify the existing StorageManager-specific code is called when an adapter is not passed in as an option and that a passed in adapter has it's methods called as expected. With the exception of the defaultAdapter that includes storage manager code, we don't care how the adapter implements its syncing, but instead that it responds to calls in the expected ways. Adapters will be responsible for unit testing their syncing functionality.
General upkeep checklist