Search code examples
ember.jsember-dataember-cli

Confusing behavior from computed properties with async Ember models


I ran into some strange behavior trying to build computed properties into my Ember Data model. Here's what my .coffee file looks like:

LineItemModel = DS.Model.extend
  quantity: attr 'number'
  length: attr 'number'
  product: DS.belongsTo 'product', async: true
  priceAdjust: attr 'number', defaultValue: 0

  weight: (->
    return this.get('product.weight') * length
  ).property('product')

  # Get MLF price
  price: (->
    # Adjust if percentage is specified
    adjust = (mlf, adjustment) ->
      return mlf unless adjustment
      mlf += Math.ceil(mlf * adjustment / 100)

    prices = this.get('product').get 'prices'
    level = this.get('quote').get 'level'
    price = prices.filterBy 'level', level
    return if price[0] then adjust( price[0], this.get('priceAdjust') ) else 0
  ).property('product', 'product.@each.prices', 'quote.level', 'priceAdjust')

My problem is that in my weight method this.get('product.weight') always returns undefined. I've done some testing and anything other than this.get('product.id') returns undefined. To make thing even more confusing, this works

Ember.computed.alias('product.weight')

and this from with the price method

  # Get MLF price
  price: (->
     console.log this.get('product.weight')
     ...

This is the product model for reference:

ProductModel = DS.Model.extend
  ...
  weight: attr 'number'
  prices: DS.hasMany 'price', async: true

I'm not sure if I did something wrong or if this is a bug. This is a cli app v0.1.15


Solution

  • So as far as I can tell, the problem is related to promises as whether or not they're resolved. Here's what I came up with so far:

    weight: Ember.computed.alias 'product.weight'

    Computed property easily takes care of handling the promise relationship business

    # Lbs / Ft
    lbs: (->
      return this.get('weight') * this.get('length')    
    ).property('weight', 'length')
    

    Now I know I have some value for weight and I can do my calculation with it. I'm still not sure why I didn't seem to need this in the price method but this seems like the "Ember" way to do things. I'd love some feedback if this can be improved.