question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Proposal] Allow paths in ids

See original GitHub issue

Proposal

Allow paths in ids e.g. project1/-abcdef so that deep data structures can be supported. Deep structures are often used in Firebase apps and are particularly useful when locking things down via security rules.

Detailed explanation

Without storing within deep paths, it is difficult to write security rules that allow listening for live changes across a subset of records. For example, if you were to have a chat app where messages were stored under the messages collection and secured so that no single user can read all messages:

// data
messages : {
  -Xyz: { from: 'user1', to: 'user2', ... },
  -Xzz: { from: 'user2', to: 'user3', ... },
}

// rules
"messages": {
  ".read": false,
  "$messageId": {
    ".read": "auth.uid == data.child('from').val() || ..."
}

This will prevent a realtime query on messages. You cannot do a query on the top level, because “.read” is false. Your current option is to store each message in a hasMany relationship under user.messages, or create some other intermediate object with hasMany links.

If we could use paths in both ids and queries:

// data
messages : {
  conversation1: {
    -Xyz: { from: 'user1', to: 'user2', conversationId: 'conversation1', ... },
    -Xzz: { from: 'user1', to: 'user2', conversationId: 'conversation1', ... },
  },
  room1: {
    -Abc: { to: 'room1', ... },
  }
}

// rules
"messages": {
  ".read": false,
  "$conversationId": {
    ".read": "root.child('rooms').child($roomId).child('members').child(auth.uid).val() == true",
}

Example API

// chat room message
const conversationId = room.get('id');

// private conversation
const conversationId = [me.get('id'), you.get('id')].sort().join('_');

// get messages via a raw firebase query
const messageQuery = this.get('firebase').child(`messages/${conversationId}`).limitToLast(100);
store.query(messageQuery).then(liveArray => {
  this.set('model', liveArray);
});

// save new message
const newId = this.get('firebase').push().key;
const message = store.createRecord('message', {
  id: `${conversationId}/${newId}`,
  roomId: conversationId,
  body: 'Hello world',
}).save(); // saves at /messages/:conversationId/:pushId

Breaking changes

The intent is for this to be backwards compatible with the existing API and data structure.

Open questions

  • How would relationships be saved in the db? with slashes, replace dots with slashes?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:21 (15 by maintainers)

github_iconTop GitHub Comments

6reactions
mikkopaderescommented, Oct 29, 2016

For me it kinda feels not ember data-ish.

Right now in ember data, the current standard for querying data as shown in the guides should be of this syntax:

this.get('store').query('person', {
  filter: {
    name: 'Peter'
  }
});

Of course, it depends on the adapter if they’ll handle that syntax. But I think it would be nice if emberfire will be as close to it as possible. Like this:

// Grab 100 ids under /userPosts/${userId} and return each one as a post model
this.get('store').query('post', {
  path: `userPosts/${userId}`,
  filter: {
    limitToLast: 100
  }
});

// Grab 100 ids under /posts and return each one as a post model
this.get('store').query('post', {
  filter: {
    limitToLast: 100
  }
});
4reactions
tstirratcommented, Oct 6, 2016

+1 to having a path in the query.

I was also thinking we could help with your situation currently by letting the query know if you’re expecting objects, or links to objects. If it was expecting links to objects you could use it for your structure above.

this.store.query('post', {
  path: `userPosts/${userId}`,
  type: 'ids', // expecting ids, not objects
  limitToLast: 100,
});

We could look for id1: true and convert this to an async object lookup for store.findRecord('post', 'id1')

edit: type is probably not the right parameter name, but you get the idea.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Path Auxiliary Proposal for MCMC in Discrete Space
Comment: This paper provides a novel path auxiliary algorithm for more efficiently exploring discrete state spaces within a Metropolis-Hastings sampler for ...
Read more >
Proposal for the Acquisition and Use of Photo-ID Badges
Proposal. The Emergency Response and Security Task Force proposes that the Library begin a process of securing ID cards for employees by appropriating...
Read more >
enhancement-proposals/cell-id.md at master - GitHub
Most resource applications include ids as a standard part of the resource / sub-resources. This proposal focuses only on a cell ID. Out...
Read more >
Michigan Proposal 2, Voting Policies in Constitution ...
Secure MI Vote also supported an indirect initiative, which was designed to require an identification card to cast an in-person or absentee ballot...
Read more >
Before You Start - ServiceChannel Developer Portal
Get the Proposal ID; Validate a Proposal; Retrieve the RFP ID ... in the UI does not allow you to take action on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found