Emberfire version 3 #542
Replies: 28 comments
-
Pinging #531, #529, #522, #511, #465, #366, @olivierchatry, @rmmmp, and @tstirrat |
Beta Was this translation helpful? Give feedback.
-
These APIs are a work in progress of BTW, really looking forward to pulling in feedback. |
Beta Was this translation helpful? Give feedback.
-
@jamesdaniels, first of all thanks for putting this out. Really appreciate it. I agree with not wrapping Firebase JS SDK in Ember Data. Though sometimes it just can't be help if we want a good developer experience in Ember. ;) Anyways, here's my comments. Queries I really like the concept of using the Firebase API instead of the old one. However, this wouldn't work in the adapter as it's expecting an object rather than a callback. You'll have to extend the this.get('store').query('post', {
filter(reference) {
return reference.limit(10);
}
}); Now we can add more configs in the object should there be any. I think one config we can add is to be able to specify what collection we'd like to query the data from. const userId = 'user_a';
this.get('store').query('user', {
// Not sure if userId would be looked up correctly here.
// Maybe we could change it to buildReference: (db) => {} instead to make it work.
buildReference(db) {
return db.collection('users').doc(userId).collection('friends');
},
filter(reference) {
return reference.limit(10);
}
}); Without providing a Realtime service Not totally convinced here. This will add a lot of codes for just to consume what brought many of us to Firebase in the first place. I think we can provide a configuration for every request to opt-in users for the realtime feature. this.get('store').query('user', {
isRealtime: true,
filter(reference) {
return reference.limit(10);
}
});
this.get('store').findRecord('user', 'user_a', {
adapterOptions: {
isRealtime: true
}
});
this.get('store').createRecord('user', {
name: 'Foobar',
age: 10,
}).save({
adapterOptions: {
isRealtime: true
}
}); The Adapter would definitely be more bigger and complex but those issue can be managed by clean codes. In fact, I think it'd be more complex if we have a separate service for that. I mean, how would the service figure out what As for FastBoot, the Adapter must be forced to not fetch realtime changes regardless of the configuration when in that environment so the user wouldn't have to compromise for that. They can use Shoebox if they're not utilizing the realtime feature. Shoebox is pointless for apps that use realtime fetching as you'll end up fetching twice either way. Custom transforms Generally +1 on this. Although I really think the approach should be to only update the changed attributes when updating. This should fix the security rules problem of not allowing some properties to be updated and we wouldn't need to have the I can't imagine how hasMany My unpopular opinion for But how would we save the relationships if we use Nevertheless, there'd be some that prefer to use Authentication Haven't used Other stuff For Cloud Firestore, I think we should extend the this.get('store').query('post', {
filter(ref) {
return ref.where('author', '==', user.get('__reference__');
}
}); Instead of const db = firebase.firestore();
this.get('store').query('post', {
filter(ref) {
return ref.where('author', '==', db.collection('users').doc('user_a'));
}
}); Lastly, the firebase service as a separate addon here is just something that would be a nice to have. I already created an addon for that but it would be just nice if it's officially owned by Firebase. :) |
Beta Was this translation helpful? Give feedback.
-
I agree with everything @rmmmp wrote. hasMany is really bad in the way it is handle by ember-data as you need to do multiple save, and can end up in a broken database state. So doing a multipath update manually seems like a good idea ( even if it is more work ). More importantly, making realtime update a kind of second class citizen ( meaning you have to take care of it yourself ) remove most of the interest in using emberfire and firebase. |
Beta Was this translation helpful? Give feedback.
-
RE Realtime: So my primary concern is how to stop listening, as we've lost those lifecycle events around unloading and I don't want developers to have to pull mixins into their models. In other frameworks that have embraced Rx I can just use Observables, sadly that's not the case in Ember. @rmmmp in my current proof-of-concept, i've been putting the ref/query in the metadata. That's how the service can pick it up from the adapter. I'm also working to get an API to pass the query hash into the Firebase SDK, so on rehydration the data won't be fetched twice; just delta updates. This is a priority for all of our SSR goals in the next two quarters. I could see, by default, having the listener attached (w/an option to disable) + then being able to detach it with the service. Let me think on this... |
Beta Was this translation helpful? Give feedback.
-
RE hasMany: Agreed, in my proof of concept; I've hacked the adapter to just make this a query; unless the embedIds option is on there. What I'm hearing here is that the whole embedIds option would be a nightmare and that's one of the things I want to avoid (at least by default). I could see absolutely cutting that entirely and instead pointing users that want that (for Firestore has-and-belongs-to-many type querying) to a doc describing how to do that with Cloud Functions. Also yes, composite indexes in Firestore are limited to 20k keys. |
Beta Was this translation helpful? Give feedback.
-
RE onlyOn & readOnly: Two things: A) maybe it's just scar tissue from my using ember-data before it was fully baked but I don't trust ember-data's dirty state tracking, is this something I should be trusting absolutely now? Part of the problem here is that when interacting with a REST API, the backend-developer can just ignore attributes the user doesn't have permission to write (e.g, Rails). Whereas with Firebase Security Rules, this write will fail and data rolled back. B) I'm also anxious about the case of saving an "out of date" model. I'd rather last write win, if they aren't using a transaction, over surprising the end user / developer by only updating the dirty attributes. @olivierchatry @rmmmp thoughts? |
Beta Was this translation helpful? Give feedback.
-
@jamesdaniels for stopping the listener, wouldn't extending Dirty state tracking works fine although it's only for attributes. Relationships doesn't have a dirty state. I'm a little bit confused with the security part. How I write mine is I allow updates "generally" but don't allow a specific field to change I'm not sure what you mean in the race-condition/transaction issue. Can you give an example? |
Beta Was this translation helpful? Give feedback.
-
@rmmmp the adapter is no longer informed of unload, I don't know what version of ember-data that changed in. A mixin would be necessary to disconnect the listener and I'd rather not go down that route. True, relationships not having dirty state is more points towards dropped embedded ids entirely. RE the race condition, consider a user updating the same record as another but they're out of sync, maybe because one was offline or they hit save within the update window. If we're only updating the dirty attributes, say one user updating Title, another updating Body then the result will be a blended version of the two vs. last write wins. Maybe this isn't an issue but especially if backed by a form I feel this violates expectations. Maybe we give the option for a save w/transaction? |
Beta Was this translation helpful? Give feedback.
-
@rmmmp we could do automatic realtime listeners if the developer is willing to pull a firebase-realtime mixin into their model. Seem like a fair compromise? Another thought, could we achieve the same thing with a decorator? |
Beta Was this translation helpful? Give feedback.
-
I was thinking about that. I think it would be ok to have a firebase-model
and hook on load / unload.
…On Wed, Jan 31, 2018 at 8:57 PM, James Daniels ***@***.***> wrote:
@rmmmp <https://github.com/rmmmp> we could do automatic realtime
listeners if the developer is willing to pull a firebase-realtime mixin
into your model. Seem like a fair compromise?
Could we achieve this with a decorator?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/firebase/emberfire/issues/542#issuecomment-362052029>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABNXG52KTkn50h_P7_PCxPLZydGEcAU5ks5tQMXBgaJpZM4RzBso>
.
|
Beta Was this translation helpful? Give feedback.
-
@jamesdaniels I'm not sure why you need the adapter to be informed of the unload. When someone calls the Am I missing something? Why do we need a lifecycle hook for this? For the race-condition, I have no strong opinion on that. I don't even think that the first update of user-1 would reflect on user-2 as |
Beta Was this translation helpful? Give feedback.
-
Here's also a snippet on how I've written my rules with Firebase before that allows updating "generally" but not allow a "posts": {
".read": "true",
"$post_id": {
"createdOn": {
".validate": "newData.isNumber() && newData.val() == (data.val() == null ? now : data.val())"
},
".write": "auth != null",
}
} With the security rules above, updating only dirty attributes should work. |
Beta Was this translation helpful? Give feedback.
-
Alright, removed the embedded ids and attr options from the proposal. Happy to simplify, going to play around with my proof-of-concept app tomorrow and see how I am feeling RE realtime listener patterns. |
Beta Was this translation helpful? Give feedback.
-
Great work with this @jamesdaniels, I'm excited to see the progress :) I am very happy to see the back of embedded id's for Embedded HasMany I currently use embedded hasMany in a few places. My use case is record HasMany <-> HasMany: How would relationships that are Realtime: A lot of my records are loaded by ember-data through templates, rather than explicitly in the model hook. I don't think I would have a change to register them with a service. Either extending The majority of times I request data I want to retrieve realtime updates. Looking at my configuration this divides on model types. Maybe consider adding a property to the Model to define the default behaviour, I do need to be able to completely unload records and removed any active ref's, this is broken in my application at the moment for the reasons being discussed. During a users session their firebase authentication can change, so I unload the records owned by the previous session. This was working fine until the changes to life cycle hooks. With the Atomic Saving of Relationship changes: In order to save relationships atomically, I have a 'relationships' service. This updates multiple ref's in an atomic operation. In the proposal Other: I group all records belonging to a 'team' under Off topic: I would find it very useful if, in the SDK, there was a way to list all listening ref's. |
Beta Was this translation helpful? Give feedback.
-
Going back to import { hasMany } from 'ember-data/relationships';
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default Model.extend({
age: attr('number'),
username: attr('string'),
friends: hasMany('user', {
filter(reference, record) {
return reference.limit(10);
}
}),
}); Here's how to change the relationship option dynamically for use-cases such as changing Disclaimer: I'm not sure if changing the relationship option has any drawbacks in Ember Data or if this is even the recommended way. I assume that there's none as long as you don't change built-in options such as const user = await this.store.findRecord('user', 'user_a');
const friends = await user.get('friends');
const newLimit = 20;
friends.relationship.relationshipMeta.options.filter = (reference, record) => {
return reference.where('age', '>=', record.get('age')).limit(newLimit);
};
friends.reload(); This may be enough to fix the bad rap against using |
Beta Was this translation helpful? Give feedback.
-
Since I haven't seen it mentioned here, will this rewrite also support Firebase Storage which also appears to be missing from Emberfire? |
Beta Was this translation helpful? Give feedback.
-
Not sure how it can fit with ember data.
…On Feb 26, 2018 23:16, "Eric Higgins" ***@***.***> wrote:
Since I haven't seen it mentioned here, will this rewrite also support
Firebase Storage which also appears to be missing from Emberfire?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/firebase/emberfire/issues/542#issuecomment-368750428>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABNXG_6ppsA4rnWjFFMyGr8wtlEWnM-3ks5tY4_HgaJpZM4RzBso>
.
|
Beta Was this translation helpful? Give feedback.
-
@olivierchatry Honestly, I'd be happy if there was just a generic ember service included. I've had to include the following in all of my projects and I'm not even sure if it's correct.
|
Beta Was this translation helpful? Give feedback.
-
Looking forward to this project, and checking in to see if there are any updates with EmberFire in regards to fixing any issues (babel versions) and other bugs until support for FireStore is ready :) |
Beta Was this translation helpful? Give feedback.
-
Definitely looking forward to this! |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
-
Release candidate 1 has been cut. https://github.com/firebase/emberfire/releases/tag/v3.0.0-rc.1 |
Beta Was this translation helpful? Give feedback.
-
For all people having problems with the lack of documentations right now, I really suggest looking at the dummy-app in the test folder: This really helped me alot! |
Beta Was this translation helpful? Give feedback.
-
Good point @tdiddi, thanks. I'll work on getting the documentation all back in order shortly. Beyond the one or two major gaps that's my next blocker to calling it 3.0 final. Feel free to provide any feedback you'd be up for sharing about your experience with the RC, I can be reached at [email protected] |
Beta Was this translation helpful? Give feedback.
-
I will for sure @jamesdaniels , after I am prototyping my project. So far the "new" emberfire is really awesome. Keep up the work! |
Beta Was this translation helpful? Give feedback.
-
FYI we sorted out NPM details and replaced the legacy build tools that were holding us back a bit. Release candidate 2 was just published at |
Beta Was this translation helpful? Give feedback.
-
EmberFire |
Beta Was this translation helpful? Give feedback.
-
Emberfire v3 Proposal
I propose a rewrite of Emberfire. I've made a proof of concept application which I'll extract the Firebase bits from and put into a WIP branch this week.
Before I jump into the what, I'd like to touch on the why. A lot has changed since emberfire v2 was released:
We've also had a number of issues, since the inception of the project, which we've not fundamentally addressed:
All of this, to me adds up to a new version; while of course trying to keep the API as close as possible.
Rewrite Goals
New API
Two adapters! Firebase Realtime Database and Cloud Firestore.
Also allow configuration of multiple Firebase applications and add multi-database support. This API is still being thought out.
Changes to the ember-data adapters
Querying
Fundamentally, unchanged, regardless of the adapter chosen.
But what if you want the last 10 published posts? Rather than wrapping the query interface for RTDB and Firestore, I propose we take a lesson from angularfire and just allow modification of the Firebase Query:
Moving realtime updates to a service
One of Firebase's super-powers is it's realtime subscriptions, allowing you to get changes to your model and query in milliseconds. This however violates every assumption that ember-data makes + makes integration with Fastboot and Shoebox difficult. We've also lost life-cycle events we need to do realtime in an efficient manner.
I propose a model mixin, which would interact with a new realtime-service (rather than shoving everything in the adapter). This mixin would giving us the unload detection we need to do things efficiently, start/stop listening methods, etc.
Mixin:
TDB
Service:
Now we'd be playing nicely with Fastboot, Shoebox, reduce our adapter complexity by an order of magnitude while giving you much more control over your subscriptions.
Putting this together:
Types
Strong typing in Firestore
In addition to serializing the built-in ember-data types to something reasonable on the Firestore side; we should add new ember-data types for those strong types, so emberfire will play nicely with native applications:
I'm still working these out.
hasMany
hasMany
relationships are where we need to improve the most.Developers can now secure their queries in the Realtime Database, so we should back hasMany with a query rather than using embedded ids; which were very fragile before.
We also have sub-collections in Firestore.
Options:
query
(Database) => Query
embedded
any
subcollection
any
Putting this together:
Authentication
Here I propose two changes, the first of which is supporting Ember Simple Auth out of the box. Should be fairly self explanatory ;)
The next, no longer wrapping any Firebase SDK calls. Neither the Torii or Simple Auth adapters will have login options themselves, instead logging in should be done with the Firebase JS SDK. This simplifies our code and increases our agility (there's been a lot of churn on these APIs) while giving you all the power of working with the authentication calls yourself.
Summary
First and foremost, we should not be wrapping the Firebase JS SDK! The Firebase JS SDK is battle tested and Promise based, so it plays nicely with the Ember ecosystem out of the box. We shouldn't do anything that gets in the developer's way or decreases our ability to keep up with the Firebase SDK, like inventing our own API.
Second, support Cloud Firestore as an ember-data adapter. Firestore is Firebase's next-generation datastore and what we're recommending people to use. It combines all the awesomeness of the Realtime Database with Google's planet scale goodness and querying capabilities. Seriously check it out.
Finally, fix all the deficiencies of the project: Fastboot support, Realtime Listeners,
hasMany
relationships, and give the adapter options that allow you to work around Firebase's lack of a intermediate server (filtering, schemas, etc.) while decreasing the amount of code.Let's discuss!!! I'll post my WIP branch shortly.
Beta Was this translation helpful? Give feedback.
All reactions