Yes, you're right. Usually, polymorphism is for a case like this:
class App.Product extends Batman.Model
@belongsTo 'productable', polymorphic: true
class App.Store extends Batman.Model
@hasMany 'products', as: 'productable', polymorphic: true
class App.VendingMachine extends Batman.Model
@hasMany 'products', as: 'productable', polymorphic: true
Now, a Product
will store both productable_id
and productable_type
. productable_type
will be either Store
or VendingMachine
.
But... you want to have children of different types available from a single accessor? I don't know that batman.js supports this out of the box, but here's a way you might be able to get it done:
class App.Store extends Batman.Model
@hasMany 'products' # setup the relationships individually
@hasMany 'books'
@hasMany 'dvds'
@accessor 'allProducts', -> # then create a custom accessor for all of them
products = @get('products')
books = @get('books')
dvds = @get('dvds')
products.merge(books, dvds) # returns a new Batman.Set
Actually, the docs say not to use Set::merge
inside accessors, but rather to use Batman.SetUnion
. If this approach seems like it would work, you might want to look into that!
Then, if you need to send class names back in JSON, you can use @encode
on your child models, for example:
class App.Product extends Batman.Model
@resourceName: 'product'
@encode 'product_type',
encode: (value, key, builtJSON, record) ->
builtJSON.product_type = Batman.helpers.camelize(record.constructor.resourceName)
Hope that helps!
Edit:
you could shorthand the relation and accessor, if you think you'll have a lot of them:
class App.Store extends Batman.Model
@productTypes: [
'products'
'books'
'dvds'
]
for productType in @productTypes
@hasMany productType
@accessor 'allProducts', ->
allProducts = new Batman.Set
productSets = (@get(pt) for pt in @constructor.productTypes)
allProducts.merge(productSets...)
Might be worth a shot anyways!