Skip to content
Browse files

Make sure collections trigger changes when reaching into objects

  • Loading branch information...
1 parent 93d8411 commit 7d7898a73e880df26e0a40d8afe34e3fe514cbd8 Anders Carlsson and Jonas Nicklas committed Apr 2, 2012
Showing with 31 additions and 10 deletions.
  1. +10 −0 spec/model.spec.coffee
  2. +7 −2 spec/properties.spec.coffee
  3. +6 −4 src/associations.coffee
  4. +3 −1 src/collection.coffee
  5. +5 −3 src/properties.coffee
View
10 spec/model.spec.coffee
@@ -212,3 +212,13 @@ describe 'Serenade.Model', ->
serialized = post.serialize()
expect(serialized.commentsIds[0]).toEqual(5)
expect(serialized.commentsIds[1]).toEqual(8)
+ it 'can observe changes to items in the collection', ->
+ class Comment extends Serenade.Model
+ @property 'confirmed'
+ class Post extends Serenade.Model
+ @hasMany 'comments', as: -> Comment
+ @property 'confirmedComments', dependsOn: 'comments.confirmed'
+ post = new Post(name: "test")
+ post.comments = [{ id: 5, body: 'Hello', confirmed: true }, { id: 8, body: 'Monkey', confirmed: false }]
+ post.comments.get(1).confirmed = true
+ expect(post).toHaveReceivedEvent('change:confirmedComments')
View
9 spec/properties.spec.coffee
@@ -45,10 +45,15 @@ describe 'Serenade.Properties', ->
@object.set(author: extended())
oldAuthor.set(name: 'test')
expect(@object).not.toHaveReceivedEvent('change:name')
- it 'can reach into collections and observe changes to them', ->
- @object.property 'authorNames', dependsOn: 'authors.name'
+ it 'can reach into collections and observe changes to the entire collection', ->
+ @object.property 'authorNames', dependsOn: ['authors', 'authors.name']
+ @object.collection 'authors'
+ @object.authors.push(extended(name: "Anders"))
+ expect(@object).toHaveReceivedEvent('change:authorNames')
+ it 'can reach into collections and observe changes to each individual object', ->
@object.collection 'authors'
@object.authors.push(extended())
+ @object.property 'authorNames', dependsOn: ['authors', 'authors.name']
@object.authors.get(0).set(name: 'test')
expect(@object).toHaveReceivedEvent('change:authorNames')
it 'does not observe changes to elements no longer in the collcection', ->
View
10 src/associations.coffee
@@ -1,9 +1,9 @@
{AssociationCollection} = require './association_collection'
{Collection} = require './collection'
-{extend, map, get} = require './helpers'
+{extend, map, get, pairToObject} = require './helpers'
-class Associations
- @belongsTo: (name, attributes={}) ->
+Associations =
+ belongsTo: (name, attributes={}) ->
extend attributes,
set: (model) ->
if model.constructor is Object and attributes.as
@@ -16,13 +16,14 @@ class Associations
dependsOn: name
serialize: attributes.serializeId
- @hasMany: (name, attributes={}) ->
+ hasMany: (name, attributes={}) ->
extend attributes,
get: ->
unless @attributes[name]
@attributes[name] = new AssociationCollection(attributes.as, [])
@attributes[name].bind 'change', =>
@_triggerChangesTo([name])
+ @_defer(name)
@attributes[name]
set: (value) ->
@get(name).update(value)
@@ -32,6 +33,7 @@ class Associations
set: (ids) ->
objects = map(ids, (id) -> attributes.as().find(id))
@attributes[name] = new AssociationCollection(attributes.as, objects)
+ @_defer(name)
dependsOn: name
serialize: attributes.serializeIds
View
4 src/collection.coffee
@@ -50,9 +50,11 @@ class exports.Collection
item for item in @list when fun(item)
_in: (item) ->
- if item?._triggerChangesTo
+ if item?._useDefer
item._inCollections or= []
item._inCollections?.push(this)
_notIn: (item) ->
deleteItem(item._inCollections, this) if item?._inCollections
+
+ _useDefer: true
View
8 src/properties.coffee
@@ -27,7 +27,7 @@ Serenade.Properties =
@attributes[name] = new Collection([])
@attributes[name].bind 'change', =>
@_triggerChangesTo([name])
- @attributes[name]._deferTo = pairToObject(name, this)
+ @_defer(name)
@attributes[name]
set: (value) ->
@get(name).update(value)
@@ -78,7 +78,7 @@ Serenade.Properties =
_defer: (name) ->
deferred = @get(name)
- if deferred? and deferred?._triggerChangesTo
+ if deferred? and deferred?._useDefer
@gma
gma added a note Apr 17, 2012

This commit sent my app into an infinite loop, causing an error in chrome. I'll file an issue for it, but I'm not really sure how best to describe what's caused it (as I don't know, other than if I wind my HEAD back to 7d7898 and swap _useDefer back to _triggerChangesTo on line 81 of properties.coffee, the error goes away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
deferred._deferTo or= {}
deferred._deferTo?[name] = this
@@ -105,7 +105,7 @@ Serenade.Properties =
@trigger("change", changes)
- allDefers = (@_deferTo or [])
+ allDefers = (@_deferTo or {})
if @_inCollections
for collection in @_inCollections
extend(allDefers, collection._deferTo)
@@ -114,4 +114,6 @@ Serenade.Properties =
keys = map(changedProperties, (prop) -> "#{deferName}.#{prop}")
deferObject._triggerChangesTo(keys)
+ _useDefer: true
+
extend(Serenade.Properties, Events)

0 comments on commit 7d7898a

Please sign in to comment.
Something went wrong with that request. Please try again.