Skip to content

Instantly share code, notes, and snippets.

@zaius
Created December 3, 2013 22:16
Show Gist options
  • Save zaius/7778558 to your computer and use it in GitHub Desktop.
Save zaius/7778558 to your computer and use it in GitHub Desktop.
Relationship mixin factory
App.Post = App.Model.extend App.RelationshipMixinFactory('comments'),
comments: DS.hasMany('comment', async: true)
App.RelationshipMixinFactory = (name) ->
Ember.Mixin.create
init: ->
# Filters aren't computed, but they call:
# store.recordArrayManager.registerFilteredRecordArray
# Which makes them get updated when stuff gets pushed into the store.
# See: ember.data/packages/ember-data/lib/system/store.js
@_super.apply this, arguments
singular = @constructor.typeKey
filter = @store.filter name.singularize(), (obj) =>
# Using data means it won't force a lookup on the async project
# relationship if it isn't loaded.
obj.get("data.#{singular}.id") == @get('id')
parent = this
obj = Ember.Object.create
# All records from the store that relate to this object.
filter: filter
# Holds content before the change so we can tell what was added / removed.
contentWas: []
obj.addBeforeObserver "filter.@each", (value) ->
@set "contentWas", @get("filter.content").dup()
obj.addObserver "filter.@each", (value) ->
# Don't force an async lookup if unloaded
return unless parent.get "data.#{name}"
# Don't mess with the initial populating of the relationship
return unless parent.get "#{name}.content"
# TODO: work out whether this can ever get called with > 1 change
added = @get('filter.content').diff @get('contentWas')
parent.get(name).unshiftObject added[0] if added.length == 1
removed = @get('contentWas').diff @get('filter.content')
parent.get(name).removeObject removed[0] if removed.length == 1
@set "_#{name}", obj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment