Batman.js is no longer in production at Shopify and is not actively maintained.

This website is left for reference (and for old times' sake).


Model associations define relationships between models.

Defining Associations

Associations are defined inside the model definition using @belongsTo, @hasMany, and @hasOne. Each association function takes:

  • A label (string), which is used for the accessor name & encoder name
  • An options object, for configuring the association.

For example, a deck of playing cards might be modeled like this:

class MyApp.Deck extends Batman.Model
  @resourceName: 'deck'
  @encode 'brand'
  @hasMany 'cards', inverseOf: 'deck' # will look for `deck_id` on cards

class MyApp.Card extends Batman.Model
  @resourceName: 'card'
  @encode 'suit', 'rank', 'deck_id'
  @belongsTo 'deck', inverseOf: 'cards' # will match its `deck_id` to a deck's `id`

  @accessor 'fullName', -> "#{@get('rank')} of #{@get('suit')}"
  @delegate 'brand', to: 'deck'

Now, you can access the cards from their Deck:

deck.get('cards')        # => Batman.AssocationSet containing `Card`s
deck.get('cards.length') # => 52
# => ["Ace of Spades", "Queen of Hearts", ...]

Similarly, you can access a Deck from a Card:

aceOfSpades.get('deck')         # => a Deck instance (actually a BelongsToProxy)
aceOfSpades.get('deck.brand')   # => "Bicycle"
aceOfSpades.get('brand')        # => "Bicycle"

Associations are very configurable: see the Model Associations API docs for more detail about association options.

Asynchronicity and Association Values

In fact, association accessors return special objects:

Using these special objects allows batman.js to account for asynchronous loading. For example, a Batman.AssociationSet may be rendered in a Batman.View even before its records are loaded. When the records are loaded, the view will be updated automatically. Batman.BelongsToProxy provides the same functionality.

To avoid asynchronous loading, use the saveInline option on your association.

Help us improve our documentation!

Contributions to this page are welcome on Github. If you find a problem but you cannot fix it, please open an issue.

Discussion regarding batman.js documentation is also welcome on our mailing list.