don't document Set::at

don't document Set::at

# /api/Data Structures/Batman.Set

A `Batman.Set` is an observable collection of _unique_ items. `Set` extends `Batman.Object` and mixes in much of its implementation from `Batman.SimpleSet`. `Set` also mixes in [`Batman.Enumerable`](/docs/api/batman.enumerable.html), which provides [many useful methods](/docs/api/batman.enumerable.html).

### SimpleSet vs Set

`SimpleSet` and `Set` are two distinct classes in batman.js:

- `SimpleSet` implements the basic set semantics, but it is *not* a `Batman.Object`, so it is not observable.
- `Set` is a `Batman.Object`, so it can be observed, and thus plays nicely with the rest of batman.js.

If you want an observable object, choose `Batman.Set`. Use a `Batman.SimpleSet` only when you don't need observers. In fact, if you don't need observers, consider using a native array, as iteration and membership checks will be faster!

## ::constructor(items: Array) : Set

Returns a new `Batman.Set` containing `items`.

    test 'new Set constructor can be called without arguments', ->
      set = new Batman.Set
      deepEqual set.toArray(), []

    test 'new Set constructor can be passed an Array of items to add to the set.', ->
      set = new Batman.Set(['a', 'b', 'c'])
      deepEqual set.toArray().sort(), ['a', 'b', 'c']

## ::%length : Number

Number of items in the `Set`. Always access it with `get`:

```coffeescript
mySet.get('length')
```

## ::has(item) : Boolean

Returns true if `item` is in the `Set`.

_Note_: Using `has(item)` in an accessor body will register base `Set` as a source of the property being calculated. @henever the `Set` changes, the property will be recalculated.

    test 'Set::has indicates if an item is a member of the set or not.', ->
      set = new Batman.Set(['a', 'b', 'c'])
      ok set.has('a')
      equal set.has('d'), false

    test 'Set::has registers the set as a source of an accessor', ->
      class Team extends Batman.Object
        constructor: ->
          @awards = new Batman.Set()

        @accessor 'bestEver?', -> @get('awards').has('Stanley Cup')

      result = null
      team = new Team
      team.observeAndFire 'bestEver?', (status) -> result = status
      team.get('awards').add 'Eastern Conference Champs'
      equal result, false
      team.get('awards').add 'Stanley Cup'
      equal result, true

## ::add(items...) : Array

Adds any `items` to the `Set` that aren't already in the `Set`. Returns `items` which were _actually added_. (If an item was already in the `Set`, it won't be returned).

If any items are added, `add` also fires the `itemsWereAdded` event with an array of added items.

    test 'Set::add adds an item to the set', ->
      set = new Batman.Set()
      equal set.has('a'), false
      deepEqual set.add('a'), ['a']
      equal set.has('a'), true

    test 'Set::add returns only the new items that weren\'t previously in the set', ->
      set = new Batman.Set(['a', 'b'])
      deepEqual set.add('b','c','d').sort(), ['c', 'd']
      deepEqual set.toArray().sort(), ['a', 'b', 'c', 'd']

    test 'Set::add fires the itemsWereAdded event with the items newly added to the set', ->
      results = null
      set = new Batman.Set(['a', 'b'])
      set.on('itemsWereAdded', (item) -> results = item)
      set.add('b','c','d')
      deepEqual results.sort(), ['c','d']

    test 'Set::add does not fire the itemsWereAdded event if the added items were already in the set.', ->
      results = undefined
      set = new Batman.Set(['a', 'b'])
      set.on('itemsWereAdded', (items) -> results = items)
      set.add('a', 'b')
      equal typeof results, 'undefined'

## ::addArray(items: Array) : Array

Just like `Batman.Set::add`, but takes an array of items.

## ::remove(items...) : Array

Removes `items` from the `Set` if they are present. Returns any items _actually removed_ from the `Set`. (If any of `items` weren't in the `Set`, they won't be returned.)

If any items were removed, the `Set` fires the `itemsWereRemoved` event with an array of removed items.

    test 'Set::remove removes an item from the set', ->
      set = new Batman.Set(['a'])
      equal set.has('a'), true
      deepEqual set.remove('a'), ['a']
      equal set.has('a'), false

    test 'Set::remove returns only the new items that were previously in the set', ->
      set = new Batman.Set(['a', 'b'])
      deepEqual set.remove('b','c','d').sort(), ['b']
      deepEqual set.toArray(), ['a']

    test 'Set::remove fires the itemsWereRemoved event with the items removed to the set', ->
      results = null
      set = new Batman.Set(['a', 'b', 'c'])
      set.on('itemsWereRemoved', (items) -> results = items)
      set.remove('b','c')
      deepEqual results.sort(), ['b','c']

    test 'Set::remove does not fire the itemsWereRemoved event if the removed items were not already members of the set.', ->
      results = undefined
      set = new Batman.Set(['a', 'b'])
      set.on('itemsWereRemoved', (items) -> results = items)
      set.remove('c', 'd')
      equal typeof results, 'undefined'

## ::removeArray(items: Array) : Array

Just like `Batman.Set::remove`, but takes an array of items.

## ::find(testFunction : Function) : Object

Returns the first item for which `testFunction` returns a truthy value. It returns `undefined` if no item returns a truthy value.

_Note_: `find` returns the _first_ matching item, but a `Set` does not have a specified order. If two items would pass `testFunction`, either one may be returned.

    test 'Set::find returns the first item for which the test function passes', ->
      set = new Batman.Set([1, 2, 3])
      equal set.find((x) -> x % 2 == 0), 2

    test 'Set::find returns undefined if no items pass the test function', ->
      set = new Batman.Set([1, 2, 3])
      equal typeof set.find((x) -> x > 5), 'undefined'

## ::forEach(iteratorFunction : Function[, context: Object]) : undefined

Calls `iteratorFunction` for each item in the set, passing the item as the first argument. If `context` is passed, it will be `@` inside `iteratorFuction`.

_Note_: `Set::forEach` is not ordered. Consider `Batman.SetSort` if you need sorted iteration.

_Note_: `Set::forEach` registers the `Set` as a source of the property being calculated. Whenever the `Set` changes, the property will be recalculated. If you modify members of `Set` inside an accessor function, you may trigger unexpected loops.

    test 'Set::forEach iterates over each item in the set', ->
      sum = 0
      set = new Batman.Set([1,2,3])
      set.forEach (x) -> sum += x
      equal sum, 6

    test 'Set::forEach iterates over each item in the set optionally in the provided context', ->
      context = {sum: 0}
      set = new Batman.Set([1,2,3])
      set.forEach((x) ->
        @sum += x
      , context)
      equal context.sum, 6

    test 'Set::forEach registers the set as a source if called in an accessor body', ->
      class Team extends Batman.Object
        constructor: ->
          @players = new Batman.Set()
        @accessor 'willWinTheCup?', ->
          sedinCount = 0
          @players.forEach (player) ->
            sedinCount++ if player.split(' ')[1] == 'Sedin'
          sedinCount >= 2

      result = null
      team = new Team()
      team.observeAndFire 'willWinTheCup?', (status) -> result = status
      equal team.get('willWinTheCup?'), false
      team.get('players').add 'Henrik Sedin'
      equal result, false
      team.get('players').add 'Daniel Sedin'
      equal result, true

## ::isEmpty() : Boolean

Returns `true` if the `Set` has no members.

_Note_: Using `Set::isEmpty` in an accessor body will register `isEmpty` as a source of the property being calculated, so that whenever the `Set` changes, the property will be recalculated.

    test 'Set::isEmpty returns true if the set has no items', ->
      set = new Batman.Set()
      ok set.isEmpty()
      set.add('a')
      equal set.isEmpty(), false

    test 'Set::isEmpty registers the set as a source of an accessor', ->
      class Team extends Batman.Object
        constructor: ->
          @games = new Batman.Set()
        @accessor 'seasonStarted?', -> !@games.isEmpty()

      team = new Team
      equal team.get('seasonStarted?'), false
      team.get('games').add({win: true})
      equal team.get('seasonStarted?'), true

## ::%isEmpty : Boolean

Accessor for `Set::isEmpty`.

## ::clear() : Array

Removes all items from the `Set`, returning an array of all removed items. If any items were removed, the `Set`   will fire the `itemsWereRemoved` event with an array of removed items.

_Note_: Set order is not defined, so the array of removed items is unordered.

    test 'Set::clear empties the set', ->
      set = new Batman.Set(['a', 'b', 'c'])
      equal set.isEmpty(), false
      deepEqual set.clear().sort(), ['a', 'b', 'c']
      ok set.isEmpty()

    test 'Set::clear fires the itemsWereRemoved event with all the items in the set', ->
      result = null
      set = new Batman.Set(['a', 'b', 'c'])
      set.on('itemsWereRemoved', (items) -> result = items)
      set.clear()
      deepEqual result.sort(), ['a', 'b', 'c']

## ::replace(collection : Enumerable) : Array

Removes all items from `Set`, then adds all the items found in `collection`. The `collection` must have a `toArray` function which returns an array representation of the collection. Returns the array of items added.

`replace` will fire the `itemsWereRemoved` event once with all the items in the set, and then the `itemsWereAdded` event once with the items from the incoming collection.

    test 'Set::replace empties the set and then adds items from a different collection', ->
      set = new Batman.Set(['a', 'b', 'c'])
      secondSet = new Batman.Set(['d', 'e', 'f'])
      set.replace(secondSet)
      deepEqual set.toArray().sort(), ['d', 'e', 'f']

    test 'Set::replace fires the itemsWereRemoved event with all the items in the set', ->
      result = null
      set = new Batman.Set(['a', 'b', 'c'])
      set.on('itemsWereRemoved', (items) -> result = items)
      set.replace(new Batman.SimpleSet())
      deepEqual result.sort(), ['a', 'b', 'c']

    test 'Set::replace fires the itemsWereAdded event with all the items in the incoming set', ->
      result = null
      set = new Batman.Set()
      set.on('itemsWereAdded', (items) -> result = items)
      set.replace(new Batman.SimpleSet(['a', 'b', 'c']))
      deepEqual result.sort(), ['a', 'b', 'c']

## ::toArray() : Array

Returns an _unordered_ array of the `Set`'s  members.

_Note_: Using `Set::toArray` in an accessor will register the `Set` as a source of the property being calculated, so that whenever the `Set` changes, the property will be recalculated.

    test 'Set::toArray returns an array representation of the set', ->
      set = new Batman.Set()
      deepEqual set.toArray(), []
      set.add('a', 'b', 'c')
      deepEqual set.toArray().sort(), ['a', 'b', 'c']

## ::%toArray : Array

Accessor for `Set::toArray`. Whenever items are added or removed on the set, the `toArray` property will change. This is the mechanism by which batman.js's view bindings get notified of collection updates.

    test 'observers on the toArray property fire when the set changes', ->
      results = null
      set = new Batman.Set(['a', 'b', 'c'])
      set.observe('toArray', (newArray) -> results = newArray.sort())
      deepEqual set.add('d'), ['d']
      deepEqual results, ['a', 'b', 'c', 'd']
      deepEqual set.remove('b'), ['b']
      deepEqual results, ['a', 'c', 'd']

## ::merge(collections... : Enumerable) : Set

Combines the `Set` and `collections` into a new `Set` and returns it. `collection` must implement `forEach`.

`Set::merge` is non-destructive: the `Set` won't be affected.

_Note_: Be careful about using `merge` within accessors. It registers the `Set` as a source, meaning the O(n * m) merge will occur again each time, and return an entirely new `Set` instance. If the previously returned `Set` instance is retained after recalculation, this is a __big memory leak__. Instead of merging in accessors, try to use a `Batman.SetUnion` or a `Batman.SetIntersection`.

    test 'Set::merge returns a new set with the items of the original set and the passed set', ->
      abc = new Batman.Set(['a', 'b', 'c'])
      def = new Batman.Set(['d', 'e', 'f'])
      equal Batman.typeOf(set = abc.merge(def)), 'Object'
      deepEqual set.toArray().sort(), ['a', 'b', 'c', 'd', 'e', 'f']

## ::indexedBy(key : String) : SetIndex

Returns a `Batman.SetIndex` based on the `Set`, grouping by `key`. This is batman.js's way of grouping `Set`s. See the `Batman.SetIndex` documentation for more information about using `Batman.SetIndex`es.

The `Batman.SetIndex` tracks the `Set` and its members (in case their value for `key` changes).

    test 'Set::indexedBy returns a new SetIndex with the items bucketed by the value of the key', ->
      set = new Batman.Set([Batman(colour: 'blue'), Batman(colour: 'green'), Batman(colour: 'blue')])
      index = set.indexedBy('colour')
      ok index.get('blue') instanceof Batman.Set
      equal index.get('blue').get('length'), 2
      equal index.get('green').get('length'), 1

## ::%indexedBy

Accessor for `Set::indexedBy`. `mySet.get('indexedBy.myKey')` returns the same result as  `mySet.indexedBy('myKey')`. This is convenient in view bindings:

```html
<ul>
  <li data-foreach-colorgroup='collection.indexedBy.color'>
    <!-- colorgroup is a SetIndex for collection, by color -->
  </li>
</ul>
```

    test "Set::get('indexedBy.someKey') returns a new SetIndex for 'someKey'", ->
      set = new Batman.Set([Batman(colour: 'blue'), Batman(colour: 'green')])
      index = set.get('indexedBy.colour')
      equal index.get('blue').get('length'), 1

## ::indexedByUnique(key : String) : UniqueSetIndex

Returns a `Batman.UniqueSetIndex` based on `Set`, indexed by `key`. See the `Batman.UniqueSetIndex` documentation for more information.

The `Batman.UniqueSetIndex` tracks the `Set` and its members (in case their value for `key` changes).

    test 'Set::indexedByUnique returns a new UniqueSetIndex with the items hashed by the value of the key', ->
      greenItem = Batman(colour: 'green')
      blueItem = Batman(colour: 'blue')
      set = new Batman.Set([greenItem, blueItem])
      index = set.indexedByUnique('colour')
      ok blueItem == index.get('blue')
      ok greenItem == index.get('green')
      equal undefined, index.get('red')

## ::%indexedByUnique

Accessor for `Set::indexedByUnique`. `mySet.get('indexedByUnique.myUniqueKey')` returns the same result as  `mySet.indexedByUnique('myUniqueKey')`.

    test "Set::get('indexedByUnique.someKey') returns a new UniqueSetIndex for 'someKey'", ->
      set = new Batman.Set([Batman(colour: 'blue'), Batman(colour: 'green')])
      index = set.get('indexedByUnique.colour')
      equal 'blue', index.get('blue').get('colour')

## ::sortedBy(key: String, order="asc") : SetSort

Returns a `Batman.SetSort` based on the `Set`, sorted by `key` in `order`. This is batman.js's way of sorting `Batman.Set`s. See the `Batman.SetSort` documentation for more information.

`order` may be `"asc"` or `"desc"`.

The `Batman.SetSort` tracks the `Set` and its members (in case their value for `key` changes).

    test 'Set::sortedBy returns a new SetSort who can be iterated in the sorted order of the value of the key on each item', ->
      set = new Batman.Set([Batman(place: 3, name: 'Harry'), Batman(place: 1, name: 'Tom'), Batman(place: 2, name: 'Camilo')])
      sort = set.sortedBy('place')
      deepEqual sort.toArray().map((item) -> item.get('name')), ['Tom', 'Camilo', 'Harry']

## ::%sortedBy

Accessor for `Set::sortedBy`. `mySet.get('sortedBy.myKey')` returns the same result as  `mySet.sortedBy('myKey')`.  This is very convenient in view bindings:

```html
<h1> Rankings: </h1>
<ul>
  <li data-foreach-player='players.sortedBy.rank'>
    <!-- players are rendered in order -->
  <li>
</ul>
```

    test "Set::get('sortedBy.someKey') returns a new SetSort on 'someKey'", ->
      set = new Batman.Set([Batman(place: 3, name: 'Harry'), Batman(place: 1, name: 'Tom'), Batman(place: 2, name: 'Camilo')])

      sort = set.get('sortedBy.place')
      equal 'Harry', sort.get('toArray')[2].get('name')

## ::%sortedByDescending

Like `Set::%sortedBy`, but returns a descending `Batman.SetSort`. `mySet.get('sortedByDescending.myKey')` returns the same result as  `mySet.sortedBy('myKey', "desc")`.

## ::mappedTo(key : String) : SetMapping

Returns a `Batman.SetMapping` on the `Set`, for values of `key`. A `Batman.SetMapping` is an observable `map` result. See the documentation for `Batman.SetMapping` for more information.

    test 'Set::mappedTo(key) returns SetMapping on `key`', ->
      set = new Batman.Set([
        Batman(place: 3, name: 'Harry'),
        Batman(place: 1, name: 'Tom'),
        Batman(place: 2, name: 'Camilo')
      ])
      mapping = set.mappedTo('place')
      deepEqual mapping.toArray(), [3,1,2]

## ::%mappedTo

Accessor for `Set::mappedTo`. `mySet.get('mappedTo.myKey')` returns the same result as  `mySet.mappedTo('myKey')`.

    test 'set.get("mappedTo.key") returns SetMapping on `key`', ->
      set = new Batman.Set([
        Batman(place: 3, name: 'Harry'),
        Batman(place: 1, name: 'Tom'),
        Batman(place: 2, name: 'Camilo')
      ])
      mapping = set.get('mappedTo.place')
      deepEqual mapping.toArray(), [3,1,2]

## ::at(idx)

Returns the item from the `Set` at `idx`. Note that sets have no specified order, so this may return a different value each time.

## ::%at

An accessor for `::at`. You can use like:

```coffeescript
mySet.get('at.0')       # => first; OR
mySet.get('at').get(1)  # => second
```


Document conditional filter

Document conditional filter

# /api/App Components/Batman.View/Batman.View Filters

Batman filters are evaluated from left to right, with the output of each filter being injected into the next. This allows you to form filter chains for display purposes. Accessor caching does not apply to filter chains. If any component of the chain changes, the entire chain will be recalculated for each binding in the template.

Batman.js ships with many built-in view filters:

Type | Filters
---|----
__Logical Operators__ |  `and`, `or`, `not`, `conditional`
__Comparison Operators__ | `equals`, `eq`, `neq`, `lt`, `gt`, `lteq`, `gteq`
__General Utilities__ | `get`, `[]`, `meta`, `default`
__Number Helpers__ | `ceil`, `floor`, `round`, `precision`, `fixed`, `delimitNumber`, `ordinalize`
__Set Helpers__ |  `join`, `sort`, `map`, `has`, `first`, `toSentence`
__String Helpers__ | `interpolate`, `escape`, `capitalize`, `titleize`, `singularize`, `underscore`, `camelize`, `trim`, `raw`, `matches`, `truncate`, `prepend`, `append`, `replace`, `downcase`, `upcase`, `pluralize`, `humanize`
__Event Helpers__ | `withArguments`, `toggle`, `increment`, `decrement`
__Debuggers__ | `log`, `logStack`

## Custom Filters

You can define custom filters by setting them on the `Batman.Filters` object. For example, a batman.js view filter that formats a date with [moment.js](http://momentjs.com):

```coffeescript
# `moment` is the moment.js object
Batman.Filters.dateFormat = (date, format) ->
  moment(date).format(format)
```

You can also define custom filters when defining custom views with [`Batman.View.filter`](docs/api/batman.view.html#class_function_filter).

## equals(left, right) or eq(left, right): Boolean

Checks if left content is equal to right content:

```html
<span data-showif="title | equals 'Batman Views'"></span>
<span data-showif="value | eq 10"></span>
<span data-showif="value | eq true"></span>
```

__Note__: there is actually _one_ difference between `eq` and `equals`: `equals` rejects undefined values, but `eq` allows them.

## lt(left, right) : Boolean

Checks if left content is `less than` the right content.

```html
<span data-showif="posts.length | lt 10"></span>
```

## gt(left, right) : Boolean

Checks if left content is `greater than` the right content.

```html
<span data-showif="posts.length | gt 10"></span>
```

## lteq(left, right) : Boolean

Checks if left content is `less than or equal to` the right content.

```html
<span data-showif="posts.length | lteq 10"></span>
```

## gteq(left, right) : Boolean

Checks if left content is `greater than or equal to` the right content.

```html
<span data-showif="posts.length | gteq 10"></span>
```

## neq(left, right) : Boolean

Checks if left content is `is NOT equal to` the right content.

```html
<span data-showif="posts.length | neq 10"></span>
```

## ceil(value) : string

The `ceil` filter will run `Math.ceil` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | ceil"></span>
```

## floor(value) : string

The `floor` filter will run `Math.floor` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | floor"></span>
```

## round(value) : string

The `round` filter will run `Math.round` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | round"></span>
```

## percision(value, toPlace) : string

The `precision` filter will run `toPrecision()` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | precision"></span>
<span data-bind="someValue | precision 3"></span>
```

## fixed(value, toPlace) : string

The `fixed` filter will run `toFixed()` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | fixed"></span>
<span data-bind="someValue | fixed 3"></span>
```

## delimitNumber(value) : string

The `delimitNumber` filter will comma delimit a 'number'. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | delimitNumber"></span>
```

## raw(value) : string

The `raw` filter renders the unescaped value.

```html
<span data-bind="someHTMLyString | raw"></span>
```

## get(value, key) : value

Calls the get function on the input value with the specified key. Can be used with `Batman.Accessible` and `Batman.TerminalAccessible`:

```html
<span data-bind="accessibleFunction | get 'item'"></span>
```

## value[key] : value

Shorthand for the `get` filter.

## and(inputValue, otherValue) : boolean

Returns `true` if `inputValue` and `otherValue` are truthy:

```html
<p data-showif='post.published | and currentUser.loggedIn'></p>
```

## or(inputValue, otherValue) : boolean

Returns `true` if either `inputValue` or `otherValue` are truthy:

```html
<p data-showif='post.published | or currentUser.isAdmin'></p>
```

## not(value) : boolean

Inverts the truthiness of the input value:

```html
<span data-hideif="title | equals 'Batman Views' | not | and action | equals 'show'"></span>
```

## conditional(testValue, truthyValue, falsyValue)

Returns either `truthyValue` or `falsyValue` based on the truthiness of `testValue`. For example, to show `"Create Post"` for a new `Post` but `"Edit Post"` for an already-saved one:

```html
<input type='submit' data-bind-value='post.isNew | conditional "Create Post", "Edit Post"'></input>
```

## matches(value, string) : boolean

Tests a string against the input value:

```html
<span data-showif="title | matches 'Bat'"></span>
```

## truncate(value, length, end = '...') : string

Limits the length of output to the specified length and appends the specified text if over the limit:

```html
<span data-bind="page.title | truncate 5, '…'"></span>
```
Would result in:
```html
<span data-bind="page.title | truncate 5, '…'">About…</span>
```

## default(value, defaultValue) : value

Provides a default value if the keypath is falsy:

```html
<input type="text" data-bind="page.title | default 'About Us'"></input>
```

## prepend(value, string) : string

Prepends the string to the input value:

```html
<span data-bind-class="page.tag | prepend 'ico-'"></span>
```
If page.tag is 'about' this would result in:
```html
<span data-bind-class="page.tag | prepend 'ico-'" class="ico-about"></span>
```

## append(value, string) : string

Appends the string to the input value:

```html
<span data-bind-class="page.tag | append '-ico'"></span>
```
If page.tag is 'about' this would result in:
```html
<span data-bind-class="page.tag | append '-ico'" class="about-ico"></span>
```

## replace(value, searchString, replaceString[, flags]) : string

Replaces content in the input value matching the `searchString` with the `replaceString` value:

```html
<span data-bind="page.title | replace 'html', 'HTML'"></span>
```

## downcase(value) : string

Downcases the input value:

```html
<span data-bind="page.title | downcase"></span>
```

## upcase(value) : string

Upcases the input value:

```html
<span data-bind="page.title | upcase"></span>
```

## pluralize(value, count, includeCount[=true]) : string

Pluralizes the input value based on the patterns specified in `Batman.helpers.inflector` and the count provided:

```coffeescript
( ->
  @singular /(analysis)$/i, '$1'
  @singular /(analy)ses$/i, '$1sis'
).call(Batman.helpers.inflector)
```

```html
<span data-bind="'analysis' | pluralize page.comments.count"></span>
```

## singularize(string) : string

Returns the singular inflection of `string`.

## humanize(string) : string

Takes a string and makes it human readable, for example 'an_underscored_string' would become 'An underscored string'.

```html
<span data-bind="'about_us_page' | humanize"></span>
```
Would result in:
```html
<span data-bind="'about_us_page' | humanize">About us page</span>
```

## titleize(value) : string

Humanizes `string` and capitalizes each word. For example,

```html
<span data-bind="'about_us_page' | titleize"></span>
```
Would result in:
```html
<span data-bind="'about_us_page' | titleize">About Us Page</span>
```

## underscore(string) : string

Converts `string` to underscore case.

## camelize(string, firstLetterLower[=false]) : string

Converts `string` to camel case. if `firstLetterLower` is true, the first letter will be lowercase.

## ordinalize(numberOrString) : string

Turns `numberOrString` into an ordinalized number, for example, `4 | ordinalize` becomes `4th`.

## join(array, separator = '') : string

Joins `array` into a single string with `separator`:

```html
<span data-bind="page.comments | map 'title' | join ', '"></span>
```

## toSentence(array) : string

Joins `array` with `, ` and ` and`, as appropriate. See [helpers.toSentence](/docs/api/batman.helpers.html#class_function_tosentence).

## sort(value) : value

Sorts an `array` using the default comparison:

```html
<span data-foreach-comment="page.comments | sort" data-bind="comment.title"><span>
```

## map(iterable) : value

Maps the specified keypath from an `array` of objects:

```html
<span data-foreach-author="page.comments | map 'author'" data-bind="author"><span>
```

## has(iterable, item) : boolean

Calls the `iterable`'s `has` function to check for the existence of the specified `item`.

```coffeescript
class Sample.FirstController extends Batman.Controller
  index: ->
    @set('things', new Batman.Set('thing1', 'thing2'))
```

```html
<input type="checkbox" data-bind-checked="things | has 'thing1'"></input>
```
If you were to dispatch `first#index`:
```html
<input type="checkbox" data-bind-checked="things | has 'thing1'" checked="true"></input>
```

## first(iterable) : value

Returns the first value from an `array`:

```html
<span data-context-firstComment="page.comments | first"></span>
```

## meta(value, keypath) : value

Looks up `keypath` on `value.meta`. The `value` must have a `meta` property to look up against.

## interpolate(string, valuesObject) : string

Allows you to use string interpolation:

```html
<span data-bind="'The page title is %{title}' | interpolate {'title': 'page.title'}"></span>
```

## withArguments(function, curriedArguments...) : function

Ensures that the function is called with the supplied arguments in addition to the arguments it would normally be called with. This is a form of currying. The argument order will be the curried arguments (those passed to withArguments) first, then the regular arguments. In the case of a click event, the regular arguments are node, event, view.

```coffeescript
class Sample.CloseWindowView extends Batman.View
  html: '<span data-event-click="closeWindow | withArguments true"></span>'

  closeWindow: (actuallyClose) ->
    window.close() if actuallyClose
```

```html
<div data-view="CloseWindowView"></div>
```

## escape(value) : string

Escapes HTML in the input value:

```html
<textarea data-bind="page.body_html | escape"></textarea>
```

## toggle(keypath) : function

Returns a handler for toggling `keypath`. Clicking this button will toggle `showMeMore` between `true` and `false`:

```html
<button data-event-click='showMeMore | toggle'></button>
```

## increment(keypath, change[=1]) : function

Returns a handler that increments `keypath` by `change`. If `keypath` 's value isn't set, it will be treated as 0.

```html
<button data-event-click='totalScore | increment'>Add 1</button>
```

## decrement(keypath, change[=1]) : function

Returns a handler that decrements `keypath` by `change`. If `keypath` 's value isn't set, it will be treated as 0.

```html
<button data-event-click='totalScore | decrement 3'>Subtract 3</button>
```

# /api/App Components/Batman.View/Batman.View Filters

Batman filters are evaluated from left to right, with the output of each filter being injected into the next. This allows you to form filter chains for display purposes. Accessor caching does not apply to filter chains. If any component of the chain changes, the entire chain will be recalculated for each binding in the template.

Batman.js ships with many built-in view filters:

Type | Filters
---|----
__Logical Operators__ |  `and`, `or`, `not`
__Comparison Operators__ | `equals`, `eq`, `neq`, `lt`, `gt`, `lteq`, `gteq`
__General Utilities__ | `get`, `[]`, `meta`, `default`
__Number Helpers__ | `ceil`, `floor`, `round`, `precision`, `fixed`, `delimitNumber`, `ordinalize`
__Set Helpers__ |  `join`, `sort`, `map`, `has`, `first`, `toSentence`
__String Helpers__ | `interpolate`, `escape`, `capitalize`, `titleize`, `singularize`, `underscore`, `camelize`, `trim`, `raw`, `matches`, `truncate`, `prepend`, `append`, `replace`, `downcase`, `upcase`, `pluralize`, `humanize`
__Event Helpers__ | `withArguments`, `toggle`, `increment`, `decrement`
__Debuggers__ | `log`, `logStack`

## Custom Filters

You can define custom filters by setting them on the `Batman.Filters` object. For example, a batman.js view filter that formats a date with [moment.js](http://momentjs.com):

```coffeescript
# `moment` is the moment.js object
Batman.Filters.dateFormat = (date, format) ->
  moment(date).format(format)
```

You can also define custom filters when defining custom views with [`Batman.View.filter`](docs/api/batman.view.html#class_function_filter).

## equals(left, right) or eq(left, right): Boolean

Checks if left content is equal to right content:

```html
<span data-showif="title | equals 'Batman Views'"></span>
<span data-showif="value | eq 10"></span>
<span data-showif="value | eq true"></span>
```

__Note__: there is actually _one_ difference between `eq` and `equals`: `equals` rejects undefined values, but `eq` allows them.

## lt(left, right) : Boolean

Checks if left content is `less than` the right content.

```html
<span data-showif="posts.length | lt 10"></span>
```

## gt(left, right) : Boolean

Checks if left content is `greater than` the right content.

```html
<span data-showif="posts.length | gt 10"></span>
```

## lteq(left, right) : Boolean

Checks if left content is `less than or equal to` the right content.

```html
<span data-showif="posts.length | lteq 10"></span>
```

## gteq(left, right) : Boolean

Checks if left content is `greater than or equal to` the right content.

```html
<span data-showif="posts.length | gteq 10"></span>
```

## neq(left, right) : Boolean

Checks if left content is `is NOT equal to` the right content.

```html
<span data-showif="posts.length | neq 10"></span>
```

## ceil(value) : string

The `ceil` filter will run `Math.ceil` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | ceil"></span>
```

## floor(value) : string

The `floor` filter will run `Math.floor` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | floor"></span>
```

## round(value) : string

The `round` filter will run `Math.round` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | round"></span>
```

## percision(value, toPlace) : string

The `precision` filter will run `toPrecision()` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | precision"></span>
<span data-bind="someValue | precision 3"></span>
```

## fixed(value, toPlace) : string

The `fixed` filter will run `toFixed()` on the input value. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | fixed"></span>
<span data-bind="someValue | fixed 3"></span>
```

## delimitNumber(value) : string

The `delimitNumber` filter will comma delimit a 'number'. Value can be either a `string` or `integer`

```html
<span data-bind="someValue | delimitNumber"></span>
```

## raw(value) : string

The `raw` filter renders the unescaped value.

```html
<span data-bind="someHTMLyString | raw"></span>
```

## get(value, key) : value

Calls the get function on the input value with the specified key. Can be used with `Batman.Accessible` and `Batman.TerminalAccessible`:

```html
<span data-bind="accessibleFunction | get 'item'"></span>
```

## value[key] : value

Shorthand for the `get` filter.

## and(inputValue, otherValue) : boolean

Returns `true` if `inputValue` and `otherValue` are truthy:

```html
<p data-showif='post.published | and currentUser.loggedIn'></p>
```

## or(inputValue, otherValue) : boolean

Returns `true` if either `inputValue` or `otherValue` are truthy:

```html
<p data-showif='post.published | or currentUser.isAdmin'></p>
```

## not(value) : boolean

Inverts the truthiness of the input value:

```html
<span data-hideif="title | equals 'Batman Views' | not | and action | equals 'show'"></span>
```

## matches(value, string) : boolean

Tests a string against the input value:

```html
<span data-showif="title | matches 'Bat'"></span>
```

## truncate(value, length, end = '...') : string

Limits the length of output to the specified length and appends the specified text if over the limit:

```html
<span data-bind="page.title | truncate 5, '…'"></span>
```
Would result in:
```html
<span data-bind="page.title | truncate 5, '…'">About…</span>
```

## default(value, defaultValue) : value

Provides a default value if the keypath is falsy:

```html
<input type="text" data-bind="page.title | default 'About Us'"></input>
```

## prepend(value, string) : string

Prepends the string to the input value:

```html
<span data-bind-class="page.tag | prepend 'ico-'"></span>
```
If page.tag is 'about' this would result in:
```html
<span data-bind-class="page.tag | prepend 'ico-'" class="ico-about"></span>
```

## append(value, string) : string

Appends the string to the input value:

```html
<span data-bind-class="page.tag | append '-ico'"></span>
```
If page.tag is 'about' this would result in:
```html
<span data-bind-class="page.tag | append '-ico'" class="about-ico"></span>
```

## replace(value, searchString, replaceString[, flags]) : string

Replaces content in the input value matching the `searchString` with the `replaceString` value:

```html
<span data-bind="page.title | replace 'html', 'HTML'"></span>
```

## downcase(value) : string

Downcases the input value:

```html
<span data-bind="page.title | downcase"></span>
```

## upcase(value) : string

Upcases the input value:

```html
<span data-bind="page.title | upcase"></span>
```

## pluralize(value, count, includeCount[=true]) : string

Pluralizes the input value based on the patterns specified in `Batman.helpers.inflector` and the count provided:

```coffeescript
( ->
  @singular /(analysis)$/i, '$1'
  @singular /(analy)ses$/i, '$1sis'
).call(Batman.helpers.inflector)
```

```html
<span data-bind="'analysis' | pluralize page.comments.count"></span>
```

## singularize(string) : string

Returns the singular inflection of `string`.

## humanize(string) : string

Takes a string and makes it human readable, for example 'an_underscored_string' would become 'An underscored string'.

```html
<span data-bind="'about_us_page' | humanize"></span>
```
Would result in:
```html
<span data-bind="'about_us_page' | humanize">About us page</span>
```

## titleize(value) : string

Humanizes `string` and capitalizes each word. For example,

```html
<span data-bind="'about_us_page' | titleize"></span>
```
Would result in:
```html
<span data-bind="'about_us_page' | titleize">About Us Page</span>
```

## underscore(string) : string

Converts `string` to underscore case.

## camelize(string, firstLetterLower[=false]) : string

Converts `string` to camel case. if `firstLetterLower` is true, the first letter will be lowercase.

## ordinalize(numberOrString) : string

Turns `numberOrString` into an ordinalized number, for example, `4 | ordinalize` becomes `4th`.

## join(array, separator = '') : string

Joins `array` into a single string with `separator`:

```html
<span data-bind="page.comments | map 'title' | join ', '"></span>
```

## toSentence(array) : string

Joins `array` with `, ` and ` and`, as appropriate. See [helpers.toSentence](/docs/api/batman.helpers.html#class_function_tosentence).

## sort(value) : value

Sorts an `array` using the default comparison:

```html
<span data-foreach-comment="page.comments | sort" data-bind="comment.title"><span>
```

## map(iterable) : value

Maps the specified keypath from an `array` of objects:

```html
<span data-foreach-author="page.comments | map 'author'" data-bind="author"><span>
```

## has(iterable, item) : boolean

Calls the `iterable`'s `has` function to check for the existence of the specified `item`.

```coffeescript
class Sample.FirstController extends Batman.Controller
  index: ->
    @set('things', new Batman.Set('thing1', 'thing2'))
```

```html
<input type="checkbox" data-bind-checked="things | has 'thing1'"></input>
```
If you were to dispatch `first#index`:
```html
<input type="checkbox" data-bind-checked="things | has 'thing1'" checked="true"></input>
```

## first(iterable) : value

Returns the first value from an `array`:

```html
<span data-context-firstComment="page.comments | first"></span>
```

## meta(value, keypath) : value

Looks up `keypath` on `value.meta`. The `value` must have a `meta` property to look up against.

## interpolate(string, valuesObject) : string

Allows you to use string interpolation:

```html
<span data-bind="'The page title is %{title}' | interpolate {'title': 'page.title'}"></span>
```

## withArguments(function, curriedArguments...) : function

Ensures that the function is called with the supplied arguments in addition to the arguments it would normally be called with. This is a form of currying. The argument order will be the curried arguments (those passed to withArguments) first, then the regular arguments. In the case of a click event, the regular arguments are node, event, view.

```coffeescript
class Sample.CloseWindowView extends Batman.View
  html: '<span data-event-click="closeWindow | withArguments true"></span>'

  closeWindow: (actuallyClose) ->
    window.close() if actuallyClose
```

```html
<div data-view="CloseWindowView"></div>
```

## escape(value) : string

Escapes HTML in the input value:

```html
<textarea data-bind="page.body_html | escape"></textarea>
```

## toggle(keypath) : function

Returns a handler for toggling `keypath`. Clicking this button will toggle `showMeMore` between `true` and `false`:

```html
<button data-event-click='showMeMore | toggle'></button>
```

## increment(keypath, change[=1]) : function

Returns a handler that increments `keypath` by `change`. If `keypath` 's value isn't set, it will be treated as 0.

```html
<button data-event-click='totalScore | increment'>Add 1</button>
```

## decrement(keypath, change[=1]) : function

Returns a handler that decrements `keypath` by `change`. If `keypath` 's value isn't set, it will be treated as 0.

```html
<button data-event-click='totalScore | decrement 3'>Subtract 3</button>
```


Add note about overwriting ::compare

Add note about overwriting ::compare

# /api/Data Structures/Batman.Set/Batman.SetProxy

`Batman.SetProxy` provides a wrapper around a `Batman.Set` which delegates most methods and accessors to the base `Set`. `SetProxy` extends [`Batman.Object`](/docs/api/batman.object.html) and [`Batman.Enumerable`](/docs/api/batman.enumerable.html). To see `Batman.SetProxy` in action, see [`Batman.SetSort`](/docs/api/batman.setsort.html).

## ::constructor(base : Set) SetProxy

Returns a new `SetProxy` tracking `base`.

## Methods delegated to base

- `add`
- `insert`
- `insertWithIndexes`
- `remove`
- `removeWithIndexes`
- `at`
- `find`
- `clear`
- `has`
- `merge`
- `replace`
- `filter`
- `toArray`
- `isEmpty`
- `indexedBy`
- `indexedByUnique`
- `sortedBy`

## Accessors delegated to base

- `first`
- `last`
- `isEmpty`
- `toArray`
- `length`
- `indexedBy`
- `indexedByUnique`
- `sortedBy`
- `sortedByDescending`

# /api/Data Structures/Batman.Set/Batman.SetSort

`Batman.SetSort` is a [`Batman.SetProxy`](/docs/api/batman.setproxy.html) which sorts the members of its `base` by provided `key` and `order`. Through `SetProxy`, `SetSort` extends [`Batman.Object`](/docs/api/batman.object.html) and [`Batman.Enumerable`](/docs/api/batman.enumerable.html). `SetSort`s are generally derived from `Set`s. For example:

    test "SetSorts are sorted proxies of their Sets", ->
      batmobile = new Batman.Object(name: "Batmobile", wheelCount: 4)
      batcycle = new Batman.Object(name: "Batcycle", wheelCount: 2)
      vehicles = new Batman.Set(batmobile, batcycle)

      vehiclesByWheelCount1 = new Batman.SetSort(vehicles, 'wheelCount') # order defaults to 'asc'
      vehiclesByWheelCount2 = vehicles.sortedBy('wheelCount')
      vehiclesByWheelCount3 = vehicles.get('sortedBy.wheelCount')

      batcopter = new Batman.Object(name: "Batcopter", wheelCount: 0)
      vehicles.add(batcopter)

      for setSort in [vehiclesByWheelCount1, vehiclesByWheelCount2, vehiclesByWheelCount3]
        deepEqual setSort.mapToProperty('wheelCount'), [0, 2, 4]

## ::constructor(base : Set, key : String, order : ["asc"|"desc", default "asc"]) : SetSort

Returns a new `SetSort`, tracking `base` and ordering by `key` in the direction of `order`.

## ::.isSorted[= true]

Returns `true`.

## ::.descending

`true` if `"desc"` was passed to as `order` to the constructor, otherwise `false`.
Descending `SetSort`s may also be made by getting `sortedByDescending` from a `Set`:

    test "get sortedByDescending creates a descending SetSort", ->
      batmobile = new Batman.Object(name: "Batmobile", wheelCount: 4)
      batcycle = new Batman.Object(name: "Batcycle", wheelCount: 2)
      vehicles = new Batman.Set(batmobile, batcycle)

      vehiclesByWheelCountDescending1 = new Batman.SetSort(vehicles, 'wheelCount', 'desc')
      vehiclesByWheelCountDescending2 = vehicles.get('sortedByDescending.wheelCount')

      for descendingSetSort in [vehiclesByWheelCountDescending1, vehiclesByWheelCountDescending2]
        equal descendingSetSort.descending, true
        deepEqual descendingSetSort.mapToProperty('wheelCount'), [4, 2]

## ::find(func : Function)

Returns the first item from the `SetSort` for which `func(item)` returns a truthy value.

## ::forEach(func : Function)

Calls `func(item)` for each item in the `SetSort`.

## ::toArray() : Array

Returns a sorted array representation of the `SetSort`'s contents.

## ::merge(other : Set) : SetSort

Returns a new `SetSort` whose items are the union of this `SetSort` and `other`. It will have the same `key` and `order` as the starting `SetSort`.

## ::compare(a, b) : Number

Returns:

- `-1` if `a` has higher precedence than `b`
- `0` if `a` and `b` have equal precedence or if precedence can't be determined
- `1` if `b` has higher precedence than `a`

Precedence is determined by testing for `undefined`, `null`, `false`, `true`, `NaN`, `a < b` and `a > b`. Please see [the source](https://github.com/batmanjs/batman/blob/master/src/set/set_sort.coffee#L91) for implementation details.

Since `::compareElements` delegates to `::compare`, you can acheive custom sorting by overriding `::compare` in a `SetSort` subclass.

## ::compareElements(a, b) : Number

Used by `SetSort` to compare its elements when sorting. Like `::compare`, it returns `-1`, `0`, or `1`. To arrive at this value, it:

- tries `a.get(@key)` (where `@key` is the `SetSort`s key)
- if the resulting value is a function, calls `resultingFunction(a)`
- calls `resultingValue.valueOf()`
- repeats the process for `b`
- delegates to `::compare` to compare the resulting values
- inverts the value if `::.descending`

By following this process, it provides sort values for `Batman.Object`s `a` and `b` according to `@key`.

# /api/Data Structures/Batman.Set/Batman.SetProxy

`Batman.SetProxy` provides a wrapper around a `Batman.Set` which delegates most methods and accessors to the base `Set`. `SetProxy` extends [`Batman.Object`](/docs/api/batman.object.html) and [`Batman.Enumerable`](/docs/api/batman.enumerable.html). To see `Batman.SetProxy` in action, see [`Batman.SetSort`](/docs/api/batman.setsort.html).

## ::constructor(base : Set) SetProxy

Returns a new `SetProxy` tracking `base`.

## Methods delegated to base

- `add`
- `insert`
- `insertWithIndexes`
- `remove`
- `removeWithIndexes`
- `at`
- `find`
- `clear`
- `has`
- `merge`
- `replace`
- `filter`
- `toArray`
- `isEmpty`
- `indexedBy`
- `indexedByUnique`
- `sortedBy`

## Accessors delegated to base

- `first`
- `last`
- `isEmpty`
- `toArray`
- `length`
- `indexedBy`
- `indexedByUnique`
- `sortedBy`
- `sortedByDescending`

# /api/Data Structures/Batman.Set/Batman.SetSort

`Batman.SetSort` is a [`Batman.SetProxy`](/docs/api/batman.setproxy.html) which sorts the members of its `base` by provided `key` and `order`. Through `SetProxy`, `SetSort` extends [`Batman.Object`](/docs/api/batman.object.html) and [`Batman.Enumerable`](/docs/api/batman.enumerable.html). `SetSort`s are generally derived from `Set`s. For example:

    test "SetSorts are sorted proxies of their Sets", ->
      batmobile = new Batman.Object(name: "Batmobile", wheelCount: 4)
      batcycle = new Batman.Object(name: "Batcycle", wheelCount: 2)
      vehicles = new Batman.Set(batmobile, batcycle)

      vehiclesByWheelCount1 = new Batman.SetSort(vehicles, 'wheelCount') # order defaults to 'asc'
      vehiclesByWheelCount2 = vehicles.sortedBy('wheelCount')
      vehiclesByWheelCount3 = vehicles.get('sortedBy.wheelCount')

      batcopter = new Batman.Object(name: "Batcopter", wheelCount: 0)
      vehicles.add(batcopter)

      for setSort in [vehiclesByWheelCount1, vehiclesByWheelCount2, vehiclesByWheelCount3]
        deepEqual setSort.mapToProperty('wheelCount'), [0, 2, 4]

## ::constructor(base : Set, key : String, order : ["asc"|"desc", default "asc"]) : SetSort

Returns a new `SetSort`, tracking `base` and ordering by `key` in the direction of `order`.

## ::.isSorted[= true]

Returns `true`.

## ::.descending

`true` if `"desc"` was passed to as `order` to the constructor, otherwise `false`.
Descending `SetSort`s may also be made by getting `sortedByDescending` from a `Set`:

    test "get sortedByDescending creates a descending SetSort", ->
      batmobile = new Batman.Object(name: "Batmobile", wheelCount: 4)
      batcycle = new Batman.Object(name: "Batcycle", wheelCount: 2)
      vehicles = new Batman.Set(batmobile, batcycle)

      vehiclesByWheelCountDescending1 = new Batman.SetSort(vehicles, 'wheelCount', 'desc')
      vehiclesByWheelCountDescending2 = vehicles.get('sortedByDescending.wheelCount')

      for descendingSetSort in [vehiclesByWheelCountDescending1, vehiclesByWheelCountDescending2]
        equal descendingSetSort.descending, true
        deepEqual descendingSetSort.mapToProperty('wheelCount'), [4, 2]

## ::find(func : Function)

Returns the first item from the `SetSort` for which `func(item)` returns a truthy value.

## ::forEach(func : Function)

Calls `func(item)` for each item in the `SetSort`.

## ::toArray() : Array

Returns a sorted array representation of the `SetSort`'s contents.

## ::merge(other : Set) : SetSort

Returns a new `SetSort` whose items are the union of this `SetSort` and `other`. It will have the same `key` and `order` as the starting `SetSort`.

## ::compare(a, b) : Number

Returns:

- `-1` if `a` has higher precedence than `b`
- `0` if `a` and `b` have equal precedence or if precedence can't be determined
- `1` if `b` has higher precedence than `a`

Precedence is determined by testing for `undefined`, `null`, `false`, `true`, `NaN`, `a < b` and `a > b`. Please see [the source](https://github.com/batmanjs/batman/blob/master/src/set/set_sort.coffee#L91) for implementation details.

## ::compareElements(a, b) : Number

Used by `SetSort` to compare its elements when sorting. Like `::compare`, it returns `-1`, `0`, or `1`. To arrive at this value, it:

- tries `a.get(@key)` (where `@key` is the `SetSort`s key)
- if the resulting value is a function, calls `resultingFunction(a)`
- calls `resultingValue.valueOf()`
- repeats the process for `b`
- delegates to `::compare` to compare the resulting values
- inverts the value if `::.descending`

By following this process, it provides sort values for `Batman.Object`s `a` and `b` according to `@key`.


add notes about association return values and polymorphic 'interface'

# /api/App Components/Batman.Model/Batman.Model Associations

Batman.js associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`:

- [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany)
- [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto)
- [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone)

Batman.js also supports [polymorphic associations](/docs/api/batman.model_associations.html#polymorphic_associations).

## Declaring Associations

To declare associations, use class functions in your model definition. Each function accepts a `label` and an `options` object.

For example, to describe the relationship between `ParentItem` and `ChildItem`:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'child_items', inverseOf: 'parent_item', saveInline: true

class App.ChildItem extends Batman.Model
  @belongsTo 'parent_item', inverseOf: 'child_items', autoload: true
```

## Association Accessors

When you declare an association, you also create an accessor for the `label` you pass in the declaration. You can `get` and `set` that `label` to work with the association.

When you __`get`__ an association value, it returns a `Batman.AssociationSet` or a `Batman.AssociationProxy`. These objects help manage the association and provide transparent access to the actual records.

If you __`set`__ an association value, it will return the value which you assigned, not the proxy.

In the example above, we declared `ChildItem.belongsTo('parent_item')`. That means that you can use the `"parent_item"` accessor to get the related record:

```coffeescript
  child.get('parent_item.name') # => "Parent 1"
  otherParent = new App.ParentItem(name: "Parent 2")
  child.set('parent_item', otherParent)
```

We also declared `ParentItem.hasMany('child_items')`, so we can use the `"child_items"` accessor to access those records:

```coffeescript
  parent.get('child_items') # => Batman.AssociationSet
  parent.get('child_items.length') # => 1
  # add an item:
  newChild = new App.ChildItem(parent_item: parent)
  parent.get('child_items').add(child)
  parent.get('child_items.length') # => 2
```

## Specifying Related Classes

By default, each association converts its `label` to the appropriate class name and looks it up on `Batman.currentApp`. However, you can also specify the class's `name` and `namespace` by passing them as options.

If your model is defined somewhere other than `MyApp`, you should use the `namespace` option to show batman.js where the model can be found. For example, if your `User` model was defined on a namespace called `Admin`, you would pass that object to any associations that looked for `User`:

```coffeescript
class MyApp.Admin.User extends Batman.Model
  @hasMany 'assignments'
# ...
class MyApp.Assignment extends Batman.Model
  @belongsTo 'user', namespace: MyApp.Admin
```

If you create an association whose name differs from the class name of the related model, you should pass the class name as `name`. For example, if an `Assignment` belongs to an `owner`, which is a `User` record, you can declare it like this:

```coffeescript
class MyApp.Assignment extends Batman.Model
  @belongsTo 'owner', name: "User"
```

Now, batman.js will use `MyApp.User` for the `owner` association.

## Polymorphic Associations

Batman.js also supports [Rails-inspired polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). In a polymorphic association, a record may belong to records of _different types_. Instead of specifying a related model, you specify an "interface" for the association.

For example, a `Superpower` may belong to a `Hero` or a `Villain`. The interface is `"superpowerable"`:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', saveInline: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', saveInline: true
```

By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

## Inverse Associations

You can declare `inverseOf` in you associations to tell batman.js which foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

## @hasMany(label : string [, options : Object])

`@hasMany` expresses a one-to-many relationship on a `Batman.Model`.

`get`ting a `@hasMany` accessor returns a `Batman.AssociationSet` (or a `Batman.PolymorphicAssociationSet` of the association is polymorphic).

It accepts options:

Option | Default | Description
-- | -- | --
`name` | singularized, camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("children")` will trigger a load operation with request param `parent_id`.
`url` |  model's collection URL | The URL where children can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` | `{}` | An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | underscored `@model.resourceName` + `"_id"`] | The key on child records which contains the parent's primary key value
`encodeWithIndexes` | `false` | If true, children will be encoded as an Object instead of an Array.
`replaceFromJSON` | `true` | If false, objects which aren't found when loading JSON will be _left in_ the association set. Use this option if you will paginate through child records.
`as` | | Denotes a polymorphic association with the given name
`foreignTypeKey` | `"#{as}_type"` | The field where polymorphic children's class names will be stored

`encodeWithIndexes` provides a second option for serializing children wtih `saveInline`. If `ecnodeWithIndexes: true`, `@hasMany` children will be encoded as a JSON object with index keys instead of arrays. For example:

```javascript
{ id: 1,
  name: "As Seen on TV Warehouse",
  products: {
    "0": {id: 1, name: "Orange Glo"},
    "1": {name: "Oxyclean"}
  }
}
```

## @belongsTo(label : string [, options : Object])

`@belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `@hasOne` instead.

`@belongsTo` often expresses inverse of a `@hasMany` or `@hasOne` association. You can declare this with the [`inverseOf` option](/docs/api/batman.model_associations.html#inverse_associations) so that both sides of the association are loaded from JSON.

`get`ting a `@belongsTo` accessor returns a `Batman.BelongsToProxy` (or a `Batman.PolymorphicBelongsToProxy` if the association is polymorphic).

It accepts options:

Option | Default | Description
-- | -- | --
`name` | singularized, camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("children")` will trigger a load operation with request param `parent_id`.
`nestUrl` | `false` | If true, the associated model will be passed to `@urlNestsUnder`
`url` |  associated model's URL, with the `foreignKey` value | The URL where the parent can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` | | An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | `"#{@label}_id"` | The key on child records which contains the parent's primary key value
`encodeForeignKey` | `true` | If false, the foreign key will be excluded from the record's JSON.
`polymorphic` | | Denotes the association as polymorphic

## @hasOne(label : string [, options : Object])

`@hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `@belongsTo` instead.

`get`ting a `@hasOne` accessor returns a `Batman.HasOneProxy`

It accepts options:

Option | Default | Description
-- | -- | --
`name` | camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("child")` will trigger a load operation with request param `parent_id`.
`url` |  associated model's URL, with the `primaryKey` value | The UR where the child can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` |  |  An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | underscored `@model.resourceName` + `"_id"` | The key on the child record which contains the parent's primary key value

# /api/App Components/Batman.Model/Batman.Model Associations

Batman.js associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`:

- [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany)
- [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto)
- [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone)

Batman.js also supports [polymorphic associations](/docs/api/batman.model_associations.html#polymorphic_associations).

## Declaring Associations

To declare associations, use class functions in your model definition. Each function accepts a `label` and an `options` object.

For example, to describe the relationship between `ParentItem` and `ChildItem`:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'child_items', inverseOf: 'parent_item', saveInline: true

class App.ChildItem extends Batman.Model
  @belongsTo 'parent_item', inverseOf: 'child_items', autoload: true
```

## Association Accessors

When you declare an association, you also create an accessor for the `label` you pass in the declaration. You can `get` and `set` that `label` to work with the association.

When you __`get`__ an association value, it returns a `Batman.AssociationSet` or a `Batman.AssociationProxy`. These objects help manage the association and provide transparent access to the actual records.

If you __`set`__ an association value, it will return the value which you assigned, not the proxy.

In the example above, we declared `ChildItem.belongsTo('parent_item')`. That means that you can use the `"parent_item"` accessor to get the related record:

```coffeescript
  child.get('parent_item.name') # => "Parent 1"
  otherParent = new App.ParentItem(name: "Parent 2")
  child.set('parent_item', otherParent)
```

We also declared `ParentItem.hasMany('child_items')`, so we can use the `"child_items"` accessor to access those records:

```coffeescript
  parent.get('child_items') # => Batman.AssociationSet
  parent.get('child_items.length') # => 1
  # add an item:
  newChild = new App.ChildItem(parent_item: parent)
  parent.get('child_items').add(child)
  parent.get('child_items.length') # => 2
```

## Specifying Related Classes

By default, each association converts its `label` to the appropriate class name and looks it up on `Batman.currentApp`. However, you can also specify the class's `name` and `namespace` by passing them as options.

If your model is defined somewhere other than `MyApp`, you should use the `namespace` option to show batman.js where the model can be found. For example, if your `User` model was defined on a namespace called `Admin`, you would pass that object to any associations that looked for `User`:

```coffeescript
class MyApp.Admin.User extends Batman.Model
  @hasMany 'assignments'
# ...
class MyApp.Assignment extends Batman.Model
  @belongsTo 'user', namespace: MyApp.Admin
```

If you create an association whose name differs from the class name of the related model, you should pass the class name as `name`. For example, if an `Assignment` belongs to an `owner`, which is a `User` record, you can declare it like this:

```coffeescript
class MyApp.Assignment extends Batman.Model
  @belongsTo 'owner', name: "User"
```

Now, batman.js will use `MyApp.User` for the `owner` association.

## Polymorphic Associations

Batman.js also supports [Rails-inspired polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). In a polymorphic association, a record may belong to records of _different types_.

For example, a `Superpower` may belong to a `Hero` or a `Villain`:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', saveInline: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', saveInline: true
```

By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

## Inverse Associations

You can declare `inverseOf` in you associations to tell batman.js which foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

## @hasMany(label : string [, options : Object])

`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

It accepts options:

Option | Default | Description
-- | -- | --
`name` | singularized, camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("children")` will trigger a load operation with request param `parent_id`.
`url` |  model's collection URL | The URL where children can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` | `{}` | An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | underscored `@model.resourceName` + `"_id"`] | The key on child records which contains the parent's primary key value
`encodeWithIndexes` | `false` | If true, children will be encoded as an Object instead of an Array.
`replaceFromJSON` | `true` | If false, objects which aren't found when loading JSON will be _left in_ the association set. Use this option if you will paginate through child records.
`as` | | Denotes a polymorphic association with the given name
`foreignTypeKey` | `"#{as}_type"` | The field where polymorphic children's class names will be stored

`encodeWithIndexes` provides a second option for serializing children wtih `saveInline`. If `ecnodeWithIndexes: true`, `@hasMany` children will be encoded as a JSON object with index keys instead of arrays. For example:

```javascript
{ id: 1,
  name: "As Seen on TV Warehouse",
  products: {
    "0": {id: 1, name: "Orange Glo"},
    "1": {name: "Oxyclean"}
  }
}
```

## @belongsTo(label : string [, options : Object])

`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead. It often expresses inverse of a `hasMany` or `hasOne` association. You can declare this with the [`inverseOf` option](/docs/api/batman.model_associations.html#inverse_associations) so that both sides of the association are loaded from JSON.

It accepts options:

Option | Default | Description
-- | -- | --
`name` | singularized, camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("children")` will trigger a load operation with request param `parent_id`.
`nestUrl` | `false` | If true, the associated model will be passed to `@urlNestsUnder`
`url` |  associated model's URL, with the `foreignKey` value | The URL where the parent can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` | | An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | `"#{@label}_id"` | The key on child records which contains the parent's primary key value
`encodeForeignKey` | `true` | If false, the foreign key will be excluded from the record's JSON.
`polymorphic` | | Denotes the association as polymorphic

## @hasOne(label : string [, options : Object])

`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

It accepts options:

Option | Default | Description
-- | -- | --
`name` | camelized `@label` | The class name for the associatiated model
`namespace` | `Batman.currentApp` | The object where the class is defined
`encoderKey` | `@label` | The JSON key for associated records' data
`saveInline` | `false` | If true, child records will be saved inline with their parent
`autoload` | `false` | If true, `parent.get("child")` will trigger a load operation with request param `parent_id`.
`url` |  associated model's URL, with the `primaryKey` value | The UR where the child can be loaded
`includeInTransaction` | `true` | If false, this association will be skipped when deep-copying the record.
`inverseOf` | | Names the corresponding relation on the associated model.
`extend` |  |  An object to be mixed into the `Batman.Association` object.
`primaryKey` | `"id"` | The primary key for the parent model
`foreignKey` | underscored `@model.resourceName` + `"_id"` | The key on the child record which contains the parent's primary key value


document options and reorganize a bit

document options and reorganize a bit

# Batman.Model Associations

There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). They're modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). Batman also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type,
such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns JSON for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, Whether or not the record has been loaded from storage.

## ::fetchFromLocal() : Model
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record. If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote() : Model
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record. `Batman.AssocationProxy` subclasses must implement this method.

## Association Options
All assocations have a common set of options, as well as specific options for each type of relationship.

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.

##### `autoload[= true] : boolean`
If `true`, Batman will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, Batman checks for a model with this singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model is different from that, use `name` (and/or `namespace` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key where attributes for associated records will be found.

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
Batman expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
Batman also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Whether the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Specifies whether the `foreignTypeKey` should be included in the JSON of the record.

# Batman.Model Associations

There are 3 types of assocations available on `Batman.Model`: `hasMany`, `belongsTo`, and `hasOne`. They're modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). To add associations to your models, declare the associations in your model definition:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type,
such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns JSON for the target record, if the [`target`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, Whether or not the record has been loaded from storage.

## ::fetchFromLocal() : Model
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_accessor_target) record. If this method returns a falsy value, then [`fetchFromRemote`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote() : Model
If [`fetchFromLocal`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](http://localhost:4000/docs/api/batman.model_associations.html#prototype_accessor_target) record. `Batman.AssocationProxy` subclasses must implement this method.

## Shared Options
All assocations have a common set of options, as well as specific options for each type of relationship.

##### `saveInline[= true] : boolean`
Whether we should save the child objects as part of the parent object's JSON

##### `autoload[= true] : boolean`
 Whether we should load the child objects when loading the parent object.

##### `nestUrl[= false] : boolean`
Whether the child models are persisted beneath the parent model's url structure.

##### `name : string`
The name of the child model for the association. (eg. App.Product)

##### `inverseOf : string`
The foreign association to set on load.

##### `encoderKey : string`
The key to encode and decode the assocation into/from JSON.

##### `namespace[= Batman.currentApp] : string`
The location of the model definition for the association.

##### `polymorphic[= false] : boolean`
Whether the association is polymorphic.

## @hasMany(label[, options])
`hasMany` assocations are used for expressing one-to-many relationships on a `Batman.Model`.

- `label : string`
- `options : Object`
  - `primaryKey : string`
  - `foreignKey : string`
  - `as : string`
    - the parent association name on child objects in a polymorphic association

## @hasOne(label[, options])
`hasOne` associations are used for expressing one-to-one relationships on a `Batman.Model`.

- `label : string`
- `options : Object`
  - `primaryKey : string`
  - `foreignKey : string`
  - `as : string`
    - the parent association name on child objects in a polymorphic association

## @belongsTo(label[, options])
`belongsTo` associatons are used for expressing one-to-one child relationships on a `Batman.Model`.

- `label : string`
- `options : Object`
  - `primaryKey : string`
  - `foreignKey : string`
  - `encodeForeignKey[= true] boolean`
    - whether to encode the foreignKey value when persisting the model


Added arguments for all Png rendering parameters

    module.exports = require 'yargs'
      .usage 'Usage: $0 [options] levelname anotherlevelname yetanotherlevelname ...'
      .example '$0',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -vvvvvvvv',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to verbosity level 8 (max)\n"
      .example '$0 -w 20 -h 20',
        "Creates a level with default row and column counts,
         the cells 20 units wide, 20 units high,
         expanded by the default multiplier,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -w 10 -h 10 -x 4',
        "Creates a level with default row and column counts,
         40 x 40 unit cells,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 lvl1 lvl2',
        "Creates two levels; named lvl1 and lvl2 -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 --levels one two three',
        "Creates three levels; named one, two, and three -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 -l10',
        "Creates ten auto-named levels -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .count 'verbosity'
      .alias 'v', 'verbosity'
      .describe 'v', 'Level of logging verbosity: 1 - 8'
      .alias 'r', 'rows'
      .describe 'r', 'Number of rows for map'
      .alias 'c', 'columns'
      .describe 'c', 'Number of columns for map'
      .alias 'w', 'width'
      .describe 'w', 'Width of a grid cell'
      .alias 'h', 'height'
      .describe 'h', 'Height of a grid cell'
      .alias 'x', 'multiplier'
      .describe 'x', 'Increase cell size by x times'
      .number 'l'
      .describe 'l', 'Number of auto-named levels to create'
      .array 'levels'
      .describe 'levels', 'Array of named levels to create'
      .array 'pipeline'
      .alias 'p', 'pipeline'
      .describe 'p', 'The steps of the render pipleline'
      .string 'conf'
      .describe 'conf', 'Absolute path to config file'
      .string 'block.fill_color'
      .describe 'block.fill_color', 'The color path blocks should be'
      .string 'step_count.text_align'
      .choices 'step_count.text_align', [ 'left', 'center', 'right' ]
      .string 'step_count.text_color'
      .describe 'step_count.text_color', 'Can be either html color names or hex values'
      .number 'wall.width'
      .string 'wall.color'
      .describe 'wall.color', 'Can be either html color names or hex values'
      .conflicts 'levels', 'l'
      .help 'help'
      .default
        verbosity:  3
        rows:       15
        columns:    50
        width:      8
        height:     7
        multiplier: 4
        pipeline:   [ 'png_blocks', 'png_walls', 'png_step_count' ]
        block:
          fill_color: 'white'
        step_count:
          text_align: 'center'
          text_color: 'black'
        wall:
          width: 1
          color: '#666'
      .epilogue '© Bryan Maynard 2016'
      .wrap 120
      .argv

    module.exports = require 'yargs'
      .usage 'Usage: $0 [options] levelname anotherlevelname yetanotherlevelname ...'
      .example '$0',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -vvvvvvvv',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to verbosity level 8 (max)\n"
      .example '$0 -w 20 -h 20',
        "Creates a level with default row and column counts,
         the cells 20 units wide, 20 units high,
         expanded by the default multiplier,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -w 10 -h 10 -x 4',
        "Creates a level with default row and column counts,
         40 x 40 unit cells,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 lvl1 lvl2',
        "Creates two levels; named lvl1 and lvl2 -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 --levels one two three',
        "Creates three levels; named one, two, and three -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 -l10',
        "Creates ten auto-named levels -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .count 'verbosity'
      .alias 'v', 'verbosity'
      .describe 'v', 'Level of logging verbosity: 1 - 8'
      .alias 'r', 'rows'
      .describe 'r', 'Number of rows for map'
      .alias 'c', 'columns'
      .describe 'c', 'Number of columns for map'
      .alias 'w', 'width'
      .describe 'w', 'Width of a grid cell'
      .alias 'h', 'height'
      .describe 'h', 'Height of a grid cell'
      .alias 'x', 'multiplier'
      .describe 'x', 'Increase cell size by x times'
      .number 'l'
      .describe 'l', 'Number of auto-named levels to create'
      .array 'levels'
      .describe 'levels', 'Array of named levels to create'
      .array 'pipeline'
      .alias 'p', 'pipeline'
      .describe 'p', 'The steps of the render pipleline'
      .conflicts 'levels', 'l'
      .help 'help'
      .default
        verbosity:  3
        rows:       15
        columns:    50
        width:      8
        height:     7
        multiplier: 4
        pipeline:   [ 'png_blocks', 'png_walls', 'png_step_count' ]
      .epilogue '© Bryan Maynard 2016'
      .wrap 120
      .argv


Initial work on the new view docs

Initial work on the new view docs

# Batman.View

For a general explanation of `Batman.View`s and how they work, see [the
guide](/docs/views.html).

## ::constructor(options = {})

A `View` is a `Batman.Object`, so any options you pass are mixed in. Use this
to set `html`, `node`, `superview`, `parentNode` and/or your custom data.

    test 'constructor can be called without arguments', ->
      set = new Batman.Set
      deepEqual set.toArray(), []

## ::lookupKeypath(keypath) : Object

Traverses up the view tree searching for the specified keypath, and returns the
result. This is equivalent to performing a `Batman.get` for each view above
`this` in the tree, until a defined result is returned. The path it takes is as
follows:

current view → chain of superviews → layout view → active controller → app →
window

If there is no match, `undefined` is returned. However if used in an accessor
or binding, the entire path to the root will be registered as a potential
source of the keypath. Consequently, if the keypath is later set on any part of
the chain, the data will be correctly bound.

`lookupKeypath` is the function invoked to locate data when evaluating a
binding.

    test 'lookupKeypath returns the value if defined on the view', ->
      view = new Batman.View(animal: 'cats')
      equal 'cats', view.lookupKeypath('animal')

    test 'lookupKeypath returns the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'cats')
      subview = new Batman.View(superview: superview)
      equal 'cats', subview.lookupKeypath('animal')

## ::setKeypath(keypath, value) : Object

Traverses the View tree searching for the specified keypath, and sets the value
on the nearest ancestor which defines it. If no ancestor view defines the given
keypath, it will be set on the nearest ancestor which is not a
backing view.

`setKeypath` is the function invoked to set data when using an input binding.

    test 'setKeypath sets the value if defined on the view', ->
      view = new Batman.View(animal: 'dogs')

      view.setKeypath('animal', cats)
      equal 'cats', view.get('animal')

    test 'setKeypath sets the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'dogs')
      subview = new Batman.View(superview: superview)

      subview.setKeypath('animal', cats)
      equal 'cats', superview.get('animal')

    test 'setKeypath sets the value on the nearest non-backing view when not defined anywhere', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)
      backingView = new Batman.BackingView(superview: view)

      backingView.setKeypath('animal', cats)
      equal 'cats', view.get('animal')

## ::%node : Node

A reference to the DOM node that this view encapsulates. The entire tree
beneath this node is also the responsibility of this view and/or its subviews.

Accessing `node` will load and parse the template on demand if it isn't already
loaded.

    test 'node parses the template', ->
      view = new Batman.View(html: '
cat
')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

    test 'node parses bindings too', ->
      view = new Batman.View(html: '

', animal: 'cat')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

## ::%html : String

The HTML source for the view's template. Setting this will parse the template
and build bindings automatically, but it will not be inserted into the DOM
until the view is added to a superview.

If you don't explicitly set `html` but you do set `source`, then getting `html`
will automatically fetch the template source from the local template store.

## ::.superview : Batman.View

A reference to the current superview (the direct ancestor in the tree). This is
used for traversing the tree when searching for data, as in
`View::lookupKeypath`.

## ::.subviews : Batman.Set

The set of direct children of a `View`. To manipulate the view tree, you should
operate directly on this set — batman.js will automatically keep the DOM in
sync with the logical tree.

## ::subviews.add(view)

Adding to a view's subview set will automatically update the tree, and parse
the template and bindings. If the superview is already in the DOM, this will
insert the current view's node into the DOM.

## ::subviews.remove(view)

Removing from a view's subview set will automatically remove the subview from
the DOM.

## ::removeFromSuperview()

Removes this view from its parent, without killing it.

## ::die()

Kills this view, which renders it to forever unusable. This has the
following implications:

- The view is removed from its superview
- The view's node is removed from the DOM
- The view's bindings are destroyed
- The view's current subviews are killed

    test 'die kills the view', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)

      view.die()
      equal true, view.isDead
      equal 0, superview.subviews.length

## ::.isDead : boolean

True if the view has been killed, false otherwise.

## ::destroySubviews()

Kills every subview of this view.

## ::propagateToSubviews(eventOrKey : string, value)

If value is defined, set `eventOrKey` to `value` on the entire subtree.
Otherwise, fire `eventOrKey` on the entire subtree.

## @viewForNode(node, climbTree = true) : Batman.View

Finds the view acting as the current context for a node — i.e. perform the
reverse mapping of the view tree to the DOM. If you pass `false` for
`climbTree`, it won't traverse up the DOM, and will return `undefined` unless
the node is the view's root.