Robert Mosolgo

To my knowledge, batman.js is not maintained. For that reason, I don't suggest that you use it for a new project!

Batman.Model Lifecycle Callbacks

A Batman.Model has a lifecycle object that fires events on the record when it’s being dirtied, cleaned, loaded, saved or destroyed.

Hooking up callbacks

Love ‘em or hate ‘em, Active Record callbacks can be just the thing for certain problems. Batman.Model provides similar functionality for records.

You can hook into lifecycle events by creating listeners on the prototype:

class App.AddressBook extends Batman.Model
  @::on 'before save', ->
    # remove contacts with no email:
    contacts = @get('contacts')
    contacts.forEach (contact) ->
      if !@contact.get('email')

One caveat: Unlike ActiveRecord’s before_validation, you can’t abort a storage operation from a batman.js lifecycle callback. You can throw/catch, though:

class App.AddressBook extends Batman.Model
  @::on 'before save', -> throw "Stop saving!"

addressBook = new App.AddressBook
catch err
  # => err is "Stop saving!"
  addressBook.isNew() # => true

Available callbacks

These keys can be observed like this:

class App.AddressBook extends Batman.Model
  @::on "#{someEventName}", -> someCallback()

Saving Records

For records where isNew is true, create callbacks are fired. Otherwise, save callbacks are fired.

  1. enter dirty
  2. set
  3. enter creating OR enter saving
  4. create OR save
  5. exit creating OR exit saving
  6. enter clean
  7. created OR saved
  8. Callback passed to Model::save
  9. enter destroying
  10. destroy
  11. exit destroying
  12. enter destroyed
  13. destroyed
  14. Callback passed to Model::destroy

Loading a Record From Memory

  1. enter loading
  2. load
  3. exit loading
  4. enter clean
  5. loaded
  6. Callback passed to Model.load


There are others… Check out Batman.StateMachine to see specific transition events and see InstanceLifecycleStateMachine for other events and transitions not listed here. There are tons of combinations, but I tried to hit the main ones!

How it works

Every Batman.Model instance has a InstanceLifecycleStateMachine at lifecycle. That state machine extends Batman.DelegatingStateMachine, which means it fires all of its own events on its base – in this case, a Batman.Model instance. The batman.js source for Model shows the different state and transition names, and Batman.StateMachine shows how these names translate to events.