Skip to content
This repository has been archived by the owner on Nov 28, 2017. It is now read-only.

Commit

Permalink
Merge a11e43d into 4a1d8d4
Browse files Browse the repository at this point in the history
  • Loading branch information
joostverdoorn committed Jul 30, 2014
2 parents 4a1d8d4 + a11e43d commit 663fc69
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 96 deletions.
2 changes: 1 addition & 1 deletion Gruntfile.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ module.exports = ( grunt ) ->
grunt.loadNpmTasks 'grunt-contrib-watch'

grunt.registerTask 'default', ['watch']
grunt.registerTask 'spec', ['coffee:dist', 'coffee:spec', 'jasmine', 'clean:spec']
grunt.registerTask 'spec', ['clean:spec', 'coffee:dist', 'coffee:spec', 'jasmine', 'clean:spec']
grunt.registerTask 'build', ['coffee:dist', 'uglify:dist']
136 changes: 85 additions & 51 deletions dist/tails.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/tails.min.js

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions spec/mixins/collectable.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,47 @@ describe "Tails.Mixins.Collectable", ->
createModel()
expect(createModel).toThrow()

it "should allow the creation of named scopes", ->
class Fruit extends @Model
@scope 'fresh', where: { rotten: false}
@scope 'rotten', where: { rotten: true }

goodBanana = new Fruit({ rotten: false })
badBanana = new Fruit({ rotten: true })

expect(Fruit.fresh.contains(goodBanana)).toBe(true)
expect(Fruit.fresh.contains(badBanana)).toBe(false)
expect(Fruit.rotten.contains(goodBanana)).toBe(false)
expect(Fruit.rotten.contains(badBanana)).toBe(true)

goodBanana.set('rotten', true)
expect(Fruit.fresh.contains(goodBanana)).toBe(false)
expect(Fruit.rotten.contains(goodBanana)).toBe(true)

Fruit.fresh.add(badBanana)
expect(badBanana.get('rotten')).toBe(false)
expect(Fruit.fresh.contains(badBanana)).toBe(true)
expect(Fruit.rotten.contains(badBanana)).toBe(false)

it "should allow the creation of anonymous scopes", ->
class Fruit extends @Model

freshFruits = Fruit.scope where: { rotten: false }
rottenFruits = Fruit.scope where: { rotten: true }

goodBanana = new Fruit({ rotten: false })
badBanana = new Fruit({ rotten: true })

expect(freshFruits.contains(goodBanana)).toBe(true)
expect(freshFruits.contains(badBanana)).toBe(false)
expect(rottenFruits.contains(goodBanana)).toBe(false)
expect(rottenFruits.contains(badBanana)).toBe(true)

goodBanana.set('rotten', true)
expect(freshFruits.contains(goodBanana)).toBe(false)
expect(rottenFruits.contains(goodBanana)).toBe(true)

freshFruits.add(badBanana)
expect(badBanana.get('rotten')).toBe(false)
expect(freshFruits.contains(badBanana)).toBe(true)
expect(rottenFruits.contains(badBanana)).toBe(false)
3 changes: 0 additions & 3 deletions spec/mixins/relations.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,3 @@ describe "Tails.Mixins.Relations", ->
fruit = new Fruit({id: 1, container_id: 1})

expect(basket.get('fruits').contains(fruit)).toBe(true)



36 changes: 36 additions & 0 deletions src/mixins/collectable.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,42 @@ Tails.Mixins.Collectable =
get: ( id ) ->
@collection().get(id) or new @ id: id

scope: ( name, options ) ->
options = name unless typeof name is 'string'

collection = new Tails.Collection @collection().where(options.where), { model: @, parent: @ }

for attr, value of options.where
@collection().on "change:#{attr}", ( model, v ) =>
if v isnt value and collection.contains model
collection.remove model

else if v is value and not collection.contains model
collection.add model

# When the model is added to the all() collection, the change events
# on the foreign key may have already been triggered. So we check each
# added model if it has us as its foreign key.
@collection().on "add", ( model ) =>
if model.get(attr) is value and not collection.contains model
collection.add model

@collection().on "remove", ( model ) =>
if model.get(attr) is value and collection.contains model
collection.remove model

# Watch our own collection for changes.
collection.on "add", ( model ) =>
unless model.get(attr) is value
model.set(attr, value)

collection.on "remove", ( model ) =>
if model.get(attr) is value
model.set(attr, undefined)

@[name] = collection if name?
return collection

extended: ( ) ->
methods = [
'forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
Expand Down
42 changes: 2 additions & 40 deletions src/mixins/relations.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -66,46 +66,8 @@ Tails.Mixins.Relations =
for foreignName, klass of _(relations).omit('foreignKey')
do ( foreignKey, foreignName, klass ) =>
foreignKey ||= inflection.foreign_key(@constructor.name)

# Create the collection of relations
collection = new Tails.Collection null, { model: klass, parent: @ }
@set foreignName, collection

# Find all models of klass that have already set us as their relation.
collection.add(klass.find ( model ) => model.get(foreignKey) is @id)

# Listen to the all() collection of the related class for changes in
# foreign keys. If they're not in our collection and they set their
# foreign key to us, add them. If they are in our collection and
# set their foreign key to something else, remove them.
klass.on "change:#{foreignKey}", ( model, id ) =>
if id isnt @id and collection.contains model
collection.remove model

# We have to check if the collection is currently syncing. This
# is necessary because else
else if id is @id and not collection.contains model
collection.add model

# When the model is added to the all() collection, the change events
# on the foreign key may have already been triggered. So we check each
# added model if it has us as its foreign key.
klass.on "add", ( model ) =>
if model.get(foreignKey) is @id and not collection.contains model
collection.add model

klass.on "remove", ( model ) =>
if model.get(foreignKey) is @id and collection.contains model
collection.remove model

# Watch our own collection for changes.
collection.on "add", ( model ) =>
unless model.get(foreignKey) is @id
model.set(foreignKey, @id)

collection.on "remove", ( model ) =>
if model.get(foreignKey) is @id
model.set(foreignKey, undefined)
(selector = {})[foreignKey] = @id
@set foreignName, klass.scope where: selector

ClassMethods:
belongsTo: ( relations ) ->
Expand Down

0 comments on commit 663fc69

Please sign in to comment.