Created
January 25, 2013 12:37
-
-
Save laurencer/4634135 to your computer and use it in GitHub Desktop.
Enables mutator support (ala Backbone.Mutators) for Backbone-NestedModel.
This file contains hidden or 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
# Written by Laurence Rouesnel (laurencer) | |
# Based on https://github.com/asciidisco/Backbone.Mutators | |
class Backbone.NestedModelWithMutators extends Backbone.NestedModel | |
constructor: -> | |
if _.isFunction(@mutators) then @mutators = @mutators() | |
super(arguments...) | |
get: (attr) => | |
mutator = @mutators[attr] | |
# Exit early if no mutator exists. | |
return super(attr) if not mutator? | |
# Check if this is a mutator property. | |
return mutator.call(this) if _.isFunction(mutator) | |
# Check for a deeper nested getter mutation. | |
return mutator.get.call(this) if _.isObject(mutator) and _.isFunction(mutator.get) | |
# No mutator so invoke default. | |
return super(attr) if not mutator? | |
set: (key, value, options) => | |
# Normalize the style of setter (object vs key-value) | |
if _.isObject(key) or key is null | |
attrs = key | |
options = value | |
else | |
attrs = {} | |
attrs[key] = value | |
# Determine whether an update is to a mutator or plain property | |
anyPlainUpdates = false | |
plainUpdates = {} | |
anyMutatorUpdates = false | |
mutatorUpdates = {} | |
for key, value of attrs | |
mutator = @mutators[key] | |
if mutator? and _.isFunction(mutator?.set) | |
mutatorUpdates[key] = value | |
anyMutatorUpdates = true | |
else | |
plainUpdates[key] = value | |
anyPlainUpdates = true | |
# The return value | |
ret = false | |
# Apply the mutator updates. | |
if anyMutatorUpdates | |
for key, value of mutatorUpdates | |
mutator = @mutators[key] | |
ret = ret || mutator.set.call(@, key, value, options, _.bind(super, @)) | |
if anyPlainUpdates | |
ret = super(attrs, options) || ret | |
return ret | |
toJSON: => | |
attributes = super() | |
for key, mutator of @mutators | |
newValue = if _.isFunction(mutator) | |
mutator() | |
else if _.isFunction(mutator?.get) | |
mutator.get() | |
path = Backbone.NestedModel.attrPath(key) | |
currentObj = attributes | |
for link, idx in path | |
if idx is path.length - 1 | |
# If we are at the end of the path then set the value. | |
currentObj[link] = newValue | |
else | |
if currentObj[link]? and _.isObject(currentObj[link]) | |
# If the object at the next link exists - set it to the current object. | |
currentObj = currentObj[link] | |
else if not currentObj[link]? | |
# If the object doesn't exist at the next link - create it. | |
currentObj[link] = {} | |
currentObj = currentObj[link] | |
else | |
# Break if it is not an object at this stage of the link. | |
console.log "Could not set mutator value in toJSON because non-object in path", { | |
mutatorKey: key | |
currentStep: path[0 ... idx] | |
newValue: newValue | |
currentValue: currentObj[link] | |
} | |
break | |
return attributes |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment