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

Store Managed Adapters & Serializers #2617

Conversation

jmurphyau
Copy link
Contributor

Pull request to make a store instance responsible for it's own adapter and serializer instances - as suggested fix to #2588 by @tomdale.

Serializers and Adapters are no longer singletons.

Failing test included.

@@ -185,6 +185,8 @@ Store = Ember.Object.extend({
store: this
});
this._pendingSave = [];
this._adapterInstances = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.create(null) seems appropriate for this

@igorT
Copy link
Member

igorT commented Dec 19, 2014

Thanks for the PR, left some comments

@jmurphyau
Copy link
Contributor Author

Thanks for the comments @igorT. Didn't know about Object.create(null) before now (looked it up).

The addition of lookupSerializer and lookupAdapter in the commit was due to the complexity of the 4 different lookups performed in serializerFor (typeKey, 'application', adapter.defaultSerializer, '-default') overcrowding the function.

Having to:

  • Check if the serializer is in the cache
  • If not found, then look up the serializer in the container
  • If successfully looked up/created, add the store as a parameter and add to cache

For potentially 4 different serializer types is the justification - and then if you have lookupSerializer why not be consistent with lookupAdapter?

I wasn't sure if it should be a function outside of the object (such as serializerFor, defaultSerializer, serializerForAdapter, at the bottom of the file) or a function on the instance.

@@ -250,7 +252,8 @@ Store = Ember.Object.extend({

if (DS.Adapter.detect(adapter)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@igorT @stefanpenner Do we still want passing a class here ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so because we just looked it up couple lines above?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inconsistent to me. I mean, I thought we now should always lookup adapter/serializer via the container and not instanciating it. Also, we encourage strings everywhere, but in this case we still want to fully support a store definition with an adapter property a class ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the adapter here a result of the looked up string?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hum, ok, I'm probably missing something, I thought the lookup returns an instance, not a class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah maybe you're right i thought you meant class vs a string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think I'm just too bad explaining what I have in mind 😖
So I will try again.

Historically, the user can affect a class or a string to the adapter property. As a result, there is this chain of checks. If the adapter property is a string, then the adapter is looked up via the container, or if it's a class (actually a subclass of DS.Adapter), then it is instantiated here.

My question is: do we still want to allow the user define the adapter property as a class ? It seems to me this would be inconsistent with the "string everywhere" paradigm.

Please, tell me it's clear now... or tell me to take an intensive English training course 😸

@jmurphyau
Copy link
Contributor Author

@sly7-7 (and others) in regards to removing adapter: '-rest'

I think if the order of lookup is/will change it might be an opportunity to simplify both the adapter and serializer lookup preferences..

Current preference/order

Adapters:

1 adapterFor: typeKey
2 adapterFor: 'application'
3 defaultAdapter: this.adapter (default to -rest)
4 defaultAdapter: 'application'
5 defaultAdapter: '-rest'

Serializers:

1 serializerFor: typeKey
2 serializerFor: 'application'
3 serializerFor: adapterFor(typeKey).defaultSerializer (this could return either the type specific adapter, the application wide adapter or the -rest adapter)
4 serializerFor: '-default'

Simplified

Adapters:

  • Remove this.adapter = '-rest' from the store making it only in use if the user provides it
  • Remove adapter:application lookups in adapterFor

Which would result in:
1 adapterFor: typeKey
2 defaultAdapter: this.adapter (default to undefined)
3 defaultAdapter: 'application'
4 defaultAdapter: '-rest'

Serializers:

  • Add defaultSerializer with the same logic as defaultAdapter, returning (in order): serializer:[this.serializer], serializer:application, serializer:-default
  • Remove references to serializer:application and serializer:-default from serializerFor and instead return the defaultSerializer
  • In serializerFor, be more explicit in using the defaultSerializer property from an adapter - use lookupAdapter(typeKey) which will only return the adapter for that type (not a default adapter such as 'application' or '-rest') and use the defaultSerializer property on that adapter.

Which would result in:
1 serializerFor: typeKey
2 serializerFor: this.lookupAdapter(typeKey).defaultSerializer
3 defaultSerializer: this.serializer (default to undefined)
4 defaultSerializer: 'application'
5 defaultSerializer: '-default'

@igorT
Copy link
Member

igorT commented Jan 6, 2015

@jmurphyau apologies for not getting back to you sooner. Getting up to speed now after the holidays. Wouldn't the simplified order prevent people from having custom adapters for custom stores?

@igorT
Copy link
Member

igorT commented Jan 6, 2015

Can you also please rebase/squash the PR?

@igorT
Copy link
Member

igorT commented Jan 6, 2015

Awesome work btw @jmurphyau

@jmurphyau
Copy link
Contributor Author

@igorT For a custom adapter on a custom store, this currently exists as item 3 in the current implementation:

defaultSerializer: this.adapter (default to -rest)

and item 2 in what I've documented as a simplified preference/order:

defaultAdapter: this.adapter (default to undefined)

Also, something worth noting that may not be completely obvious to everyone reading this PR - the "simplified preference/order" I've detailed in the comments above is not actually implemented in this PR - this PR is only about allowing multiple stores to work with the embedded record mixin.

Should I split out the preference/order discussion into something/somewhere else? If so, where is appropriate?

@jmurphyau
Copy link
Contributor Author

I think I've rebased this incorrectly - I'm not 100% sure??

Sorry guys don't really have much experience with Git.. I'll investigate see if I've fucked it up/need to change it..

@igorT
Copy link
Member

igorT commented Jan 7, 2015

Can you try
git reset --hard 3e424a46a563083600570bf00f72759247c8bf5c when you are in your branch
then force push the branch?

@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch from 45d9c6e to 3e424a4 Compare January 7, 2015 10:17
@jmurphyau
Copy link
Contributor Author

Done - that looks much better. Thanks @igorT.

I think using GitHub for Mac may have caused part of the problem

@@ -38,7 +38,7 @@ test("the deprecated serializer:_default is resolved as serializer:default", fun
deprecated = container.lookup('serializer:_default');
});

ok(deprecated === valid, "they should resolve to the same thing");
ok(deprecated.constructor === valid.constructor, "they should resolve to the same thing");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test that assert your config for singleton:false

@bmac bmac added this to the 1.0.0-beta.15 milestone Feb 10, 2015
@bmac
Copy link
Member

bmac commented Feb 12, 2015

ping @jmurphyau

@bmac bmac removed this from the 1.0.0-beta.15 milestone Feb 13, 2015
@jmurphyau
Copy link
Contributor Author

@bmac - I must have missed the last few comments from you.

I'll split out those tests & add the tests you mentioned over the next day or so.

@jmurphyau
Copy link
Contributor Author

@bmac - I've split the tests out - please review.

@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch 2 times, most recently from b362922 to ed0690c Compare February 14, 2015 12:13
@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch from ed0690c to 943d891 Compare February 14, 2015 12:24
@jmurphyau
Copy link
Contributor Author

@bmac @igorT @sly7-7 - any further thoughts/suggestions on this PR?

@@ -185,6 +185,7 @@ Store = Ember.Object.extend({
store: this
});
this._pendingSave = [];
this._containerCache = Ember.create(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need a cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's where the store holds its Serializers and Adapters instances - since each is now one instance per store rather than a singleton.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ok

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on destroy, we should be sure to also destroy these. So they can do needed cleanup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool - I'll get onto that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Adapters and Serializers are now store managed - with each store
instance holding a unique instance of each serializer and adapter. They
are no longer singletons.

This allows multiple stores to be used with ember-data.
@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch from 943d891 to 09f4fae Compare February 26, 2015 07:29
@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch from 09f4fae to 9fcf261 Compare February 26, 2015 07:32
@jmurphyau
Copy link
Contributor Author

@stefanpenner - I've made the changes discussed and a few additional ones since the serializerForAdapter function has moved.

@jmurphyau jmurphyau force-pushed the 2588-store-managed-adapters-serializers branch from 4587ce1 to 781c48b Compare February 27, 2015 03:20
These calls are not required here.
Since multiple store tests are now their own file and the secondary
stores are created in setup() there’s no need to create secondary
stores in this test
@bmac bmac added this to the 1.0.0-beta.16 milestone Feb 28, 2015
@igorT
Copy link
Member

igorT commented Mar 22, 2015

Thanks for the awesome work! We rebased it and merged it, but kept you as an author. Thanks!

@jmurphyau
Copy link
Contributor Author

Thanks everyone for all you help & feedback with this PR - it was my first PR ever. Was a good experience and I've since learnt a lot about Git and GitHub and moved away from GitHub for Mac in favour of the command line - so shouldn't have any issues with rebase again :)

I've created two other PRs that have stemmed from this PR

#2918 Remove serializerForAdapter

This has stemmed from @bmac's issue #2916 in relation to keeping things consistent.

#2919 Serializer & Adapter Lookups Preference/Order

This has stemmed from the above discussion started by @sly7-7 around the lookup order of serializers and adapters. Parts of the discussion are hidden behind outdated diffs (e.g. it started in 'sly7-7 commented on an outdated diff on Dec 20, 2014')

Serializer and adapter order/preference was discussed above but nothing really appeared to be decided - so I've started with a base - something to go off - which I hope gets things moving in this regard.
It can be changed or improved on or just closed (if now is not the time for this type of change, or if it's not a good idea)

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

Successfully merging this pull request may close these issues.

5 participants