Working with objects, serialization & defaults
willviles opened this issue · comments
In my production app RiskMap, we store a lot of cookie information. We like to store certain values in objects for the sake of tidiness, and because it's logical that all data stored in the same object should expire at the same time.
Currently, updating cookie objects is a multi-step process, parsing and stringifying back-and-forth:
let myCookie = this.get('cookies').read('my-cookie');
myCookie = Ember.Object(JSON.parse(myCookie));
myCookie.set('foo-bar', true);
myCookie = JSON.stringify(myCookie);
this.get('cookies').write('my-cookie', myCookie, { maxAge: defaultCookieMaxAge });
This is a pattern we use a lot at RiskMap, so I've extended Ember Cookies to make working with objects easier and more DRY. TL;DR, the above example becomes:
this.get('cookies').writeObjProperty('myCookie', 'fooBar', true);
@marcoow @Turbo87, I'd be interested to know whether you'd be interested in merging some of the following features into Ember Cookies:
Configuration
Serialization
A global way of serializing cookie name and property keys so camel cased attributes can be used in js, but cookie JSON stored in a consistent manner.
// config/environment.js
ENV['ember-cookies'] = {
serializer: 'dasherize'
}
Default max age/expires
Our user session is set to expire after 30 days. We want most of our other cookies to expire after that, too. The default value can be expressed either as defaultMaxAge
or defaultExpires
.
// config/environment.js
ENV['ember-cookies'] = {
defaultMaxAge: 60 * 60 * 24 * 30,
defaultExpires: 60 * 60 * 24 * 30
}
Object methods
readObj
readObj
reads the cookie, automatically parses the object to JSON and asserts whether it is a valid object.
this.get('cookies').readObj('myCookie');
// returns Ember.Object instance || null
readObjProperty
readObjProperty
returns the property value from the cookie object.
this.get('cookies').readObjProperty('myCookie', 'fooBar');
// => returns parsed value
Because all cookie objects are parsed into Ember Object instances, we can get deep property values using dot notation:
this.get('cookies').readObjProperty('myCookie', 'fooBaz.isGettable');
writeObj
writeObj
asserts whether a POJO or Ember Object instance is passed and stringifies it as JSON before writing:
this.get('cookies').writeObj('myCookie', { fooBar: true }/*, options*/);
// "my-cookie" === { "foo-bar": true }
writeObjProperty
writeObjProperty
enables updating an individual property inside a cookie object:
this.get('cookies').writeObjProperty('myCookie', 'fooBar', false/*, options*/);
// "my-cookie" === { "foo-bar": false }
clearObj
clearObj
is just an alias for clear
, for the sake of consistency.
this.get('cookies').clearObj('myCookie'/*, options*/);
// my-cookie === null
clearObjProperty
clearObjProperty
simply sets a property to null, before stringifying and writing.
this.get('cookies').clearObjProperty('myCookie', 'fooBar'/*, options*/);
// "my-cookie" === { }
Thanks for the great writeup!
I honestly don't believe this is something that belongs in ember-cookies though. The idea behind ember-cookies is really to provide a low level cookies API that works both in the browser as well as in Node. Introducing functionality that allows using cookies as an object store that also has to deal with serialization etc. introduces a lot of additional complexity that just isn't necessary for the majority of use cases. Also using cookies in this way isn't actually advisable I'd argue (there might be edge cases in which doing this is actually fine and your app might be one of these edge cases) and I don't think we should advocate this kind of usage by providing dedicated APIs for it.
@marcoow I totally understand that and in fact I thought that would be the case!
I'd be interested to hear more as to why you say storing objects in cookies isn't advisable and whether you think it'd be worth me authoring an accompanying plugin - something like Ember Cookies Object Store?
I'd be interested to hear more as to why you say storing objects in cookies isn't advisable
You might run into problems with max cookie size, having to migrate data in cookies etc. In general you want to store only enough information in a cookie to be able to restore your full state from that. For more advanced things it's probably better to use localStorage
or sessionStorage
or even things like IndexedDB
or so.
and whether you think it'd be worth me authoring an accompanying plugin - something like Ember Cookies Object Store?
I think everything's worth exploring ;)