Last active
August 2, 2017 13:52
-
-
Save davidgilbertson/afe0dcb8ce0b9879de2c8cd8ffc0c816 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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