Last active
May 13, 2016 04:58
-
-
Save Zaggen/63f2a132180806ae0cd577c328b3373e to your computer and use it in GitHub Desktop.
WIP: Backbone base model, that adds schema system with associations
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
class App.Models.Base extends Backbone.Model | |
schema: {} | |
set: (attributes, options)-> | |
if _.isString(attributes) | |
[key, val] = [attributes, options] | |
(attributes = {})[key] = val | |
options = null | |
super(@filter(attributes), options) | |
validate: (attrs)-> | |
# Here we should iterate on all attributes in our schema, | |
# first validating presence of (required), then type, and then the rest | |
###errorObj = {} | |
for attrName, options of @schema | |
if attrs[attrName]? | |
@_types[options.type](attrs[attrName]) | |
else | |
if options.required | |
errorObj[attrName] = {'rule': 'required', msg: "This field is required but its not defined"} | |
if not _.isEmpty(errorObj) | |
return errorObj | |
else | |
return null### | |
return null | |
# Parses model attributes to validate its types and applies filtering | |
# and transformations if those were set. | |
filter: (attrs)-> | |
if @schema | |
filteredAttrs = {} | |
for attrName, attrOptions of @schema | |
#TODO: Take into account boolean and null values that could be valid | |
if attrOptions.collection and _.isArray(attrs[attrName]) | |
@_filterCollection(filteredAttrs, attrs, attrOptions, attrName) if attrs[attrName]? | |
else if attrOptions.model | |
@_filterModel(filteredAttrs, attrs, attrOptions, attrName) if attrs[attrName]? | |
else if (value = if attrs[attrName]? then attrs[attrName] else attrOptions.defaultsTo)? | |
filteredAttrs[attrName] = | |
if _.isEmpty(attrOptions.filters) then value | |
else | |
_.reduce(attrOptions.filters,((a, filterName)=> @_filters[filterName](value)), value) | |
#TODO: Implement whitelisting attributes | |
# _whiteListedAttributes | |
return filteredAttrs | |
else | |
return attributes | |
_filterCollection: (filteredAttrs, attrs, attrOptions, attrName)-> | |
#@_filterRelation(Array::concat.call(arguments, 'collection', 'Collections')...) | |
@_filterRelation(filteredAttrs, attrs, attrOptions, attrName, 'collection', 'Collections') | |
_filterModel: (filteredAttrs, attrs, attrOptions, attrName)-> | |
#@_filterRelation(Array::concat.call(arguments, 'model', 'Models')...) | |
@_filterRelation(filteredAttrs, attrs, attrOptions, attrName, 'model', 'Models') | |
_filterRelation: (filteredAttrs, attrs, attrOptions, attrName, relationType, relationNameSpace)-> | |
# When the passed attribute (new) is already an instance of certain model or collection | |
# we can safely assign it to the specified attribute slot (No further processing) | |
if attrs[attrName] instanceof App[relationNameSpace][attrOptions[relationType]] | |
filteredAttrs[attrName] = attrs[attrName] | |
else | |
# When the passed attribute is not an instance of the specified model/collection we | |
# must parse it. The passed attribute could either be an object or array of objects with | |
# the expected format. If there is already a model/collection with that attribute name | |
# on this model, we use set, if there is not then we must create the proper instance | |
if @get(attrName) instanceof App[relationNameSpace][attrOptions[relationType]] | |
@get(attrName).set(attrs[attrName]) | |
else | |
filteredAttrs[attrName] = new App[relationNameSpace][attrOptions[relationType]](attrs[attrName]) | |
return filteredAttrs | |
_types: | |
string: (attributeName, value)-> _.isString(value) | |
int: (attributeName, value)-> _.isInteger(value) | |
array: (attributeName, value)-> _.isArray(value) | |
json: (attributeName, value)-> _.isObject(value) | |
object: (attributeName, value)-> _.isObject(value) | |
date: (attributeName, value)-> true # Not implemented yet | |
_errorMessages: | |
string: (k, v)-> "#{k}(#{typeof v}) is not a string" | |
int: (k, v)-> "#{k}(#{typeof v}) is not an integer" | |
array: (k, v)-> "#{k}(#{typeof v}) is not an array" | |
json: (k, v)-> "#{k}(#{typeof v}) is not an object" | |
object: (k, v)-> "#{k}(#{typeof v}) is not an object" | |
date: (k, v)-> "#{k}(#{typeof v}) is not a Date" | |
_validations: | |
notEmpty: -> | |
required: (attributeName, value)-> if value? then true else "#{attributeName} is required" | |
_filters: | |
trim: (string)-> string.trim() | |
nestedTrim: (obj)-> | |
for k, v of obj | |
obj[k] = v.trim() | |
return obj | |
# This values won't be stripped by filter even if they don't appear on the schema | |
_whiteListedAttributes: ['id' ,'_csrf', '_method'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment