Skip to content

Instantly share code, notes, and snippets.

@davidgilbertson
Last active August 2, 2017 13:52
Show Gist options
  • Save davidgilbertson/afe0dcb8ce0b9879de2c8cd8ffc0c816 to your computer and use it in GitHub Desktop.
Save davidgilbertson/afe0dcb8ce0b9879de2c8cd8ffc0c816 to your computer and use it in GitHub Desktop.
// Three mostly separate examples: Adding, reading/listening, and removing multiple items from firebase
// Firebase V3.0.0
// one school has many courses and many studens
// one course has many students and is in only one school
// one student is in many courses and only one school
const db = firebase.database().ref('test');
const userId = firebase.auth().currentUser.uid;
/* -- ADDING -- */
// an example using a single atomic `update()` to create objects in three 'tables' that reference each other.
const school1Key = db.child('data/schools').push().key;
const course1Key = db.child('data/courses').push().key;
const course2Key = db.child('data/courses').push().key;
const student1Key = db.child('data/students').push().key;
const student2Key = db.child('data/students').push().key;
const school1 = {
name: 'A magnificent school',
courseKeys: {
[course1Key]: true,
[course2Key]: true,
},
studentKeys: {
[student1Key]: true,
[student2Key]: true,
},
};
const course1 = {
name: 'An excellent course',
schoolKey: school1Key,
studentKeys: {
[student1Key]: true,
[student2Key]: true,
},
};
const course2 = {
name: 'An second excellent course',
schoolKey: school1Key,
studentKeys: {
[student2Key]: true,
},
};
const student1 = {
name: 'Bobby Brown',
schoolKey: school1Key,
courseKeys: {
[course1Key]: true,
},
};
const student2 = {
name: 'Sally Mae',
schoolKey: school1Key,
courseKeys: {
[course1Key]: true,
[course2Key]: true,
},
};
const newData = {
[`users/${userId}/schoolKeys/${school1Key}`]: true,
[`users/${userId}/mruSchool`]: school1Key,
[`users/${userId}/courseKeys/${course1Key}`]: true,
[`users/${userId}/courseKeys/${course2Key}`]: true,
[`users/${userId}/studentKeys/${student1Key}`]: true,
[`users/${userId}/studentKeys/${student2Key}`]: true,
[`data/schools/${school1Key}`]: school1,
[`data/courses/${course1Key}`]: course1,
[`data/courses/${course2Key}`]: course2,
[`data/students/${student1Key}`]: student1,
[`data/students/${student2Key}`]: student2,
};
db.update(newData);
/* -- READING/LISTENING -- */
// an example of listening to multiple items
const userRef = db.child('users').child(userId);
function dispatch(action) {
console.log(action);
}
const TYPES = {
SCHOOL: {
dbPath: 'data/schools',
actions: {
upsert: item => dispatch({type: 'UPSERT_SCHOOL', item}),
remove: key => dispatch({type: 'REMOVE_SCHOOL', key}),
},
},
COURSE: {
dbPath: 'data/courses',
actions: {
upsert: item => dispatch({type: 'UPSERT_COURSE', item}),
remove: key => dispatch({type: 'REMOVE_COURSE', key}),
},
},
STUDENT: {
dbPath: 'data/students',
actions: {
upsert: item => dispatch({type: 'UPSERT_STUDENT', item}),
remove: key => dispatch({type: 'REMOVE_STUDENT', key}),
},
},
};
class Watcher {
constructor(snapshot, type) {
this.type = type;
this.key = snapshot.key;
this.ref = db.child(this.type.dbPath).child(this.key);
this.ref.on('value', this.onChange.bind(this));
}
onChange(snapshot) {
if (!snapshot) return; // this fires when the object is removed. But the child_removed event handles the removal
this.type.actions.upsert({
[this.key]: snapshot.val(),
});
}
remove() {
this.type.actions.remove(this.key);
this.ref.off('value', this.onChange);
}
}
class FirebaseWatcher {
constructor() {
this.cache = {};
}
watchList(ref, type) {
ref.on('child_added', snap => this.onChildAdded(snap, type));
ref.on('child_removed', snap => this.onChildRemoved(snap));
}
onChildAdded(snapshot, type) {
this.cache[snapshot.key] = new Watcher(snapshot, type);
}
onChildRemoved(snapshot) {
this.cache[snapshot.key].remove();
delete this.cache[snapshot.key];
}
}
const firebaseWatcher = new FirebaseWatcher();
firebaseWatcher.watchList(userRef.child('schoolKeys'), TYPES.SCHOOL);
firebaseWatcher.watchList(userRef.child('courseKeys'), TYPES.COURSE);
firebaseWatcher.watchList(userRef.child('studentKeys'), TYPES.STUDENT);
/* -- REMOVING -- */
// an example using a single atomic `update()` to remove an item and references to it
function removeStudent(studentKey) {
db.child('data/students').child(studentKey).once('value', studentSnapshot => {
const student = studentSnapshot.val();
const removeData = {
[`data/students/${studentKey}`]: null,
[`data/schools/${student.schoolKey}/studentKeys/${studentKey}`]: null,
[`users/${userId}/studentKeys/${studentKey}`]: null,
};
Object.keys(student.courseKeys).forEach(courseKey => {
removeData[`data/courses/${courseKey}/studentKeys/${studentKey}`] = null;
});
db.update(removeData);
});
}
removeStudent('<some student key>');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment