Questions about ember-data 0.13->1.0beta upgrade


#1

I’m trying to upgrade to the ember-data beta but I’m running into some issues. The relevant code is pasted here and I’ve listed the issue and questions below, any help would be greatly appreciated!

# store

App.ApplicationSerializer = DS.ActiveModelSerializer.extend
  serializeAttribute: (record, json, key, attribute) ->
    if !attribute.options.readOnly
      return @_super(record, json, key, attribute)

App.ApplicationAdapter = DS.ActiveModelAdapter.extend
  namespace: 'api/v1'
  pathForType: (type) ->
    underscored = Ember.String.underscore(type)
    return Ember.String.pluralize(underscored)


# models

App.Trackable = Ember.Model.extend()

App.Notifiable = App.Trackable.extend
  notifications: DS.hasMany('notificationActivity', { async: true })

App.Attachable = App.Notifiable.extend
  attachments: DS.hasMany('attachment', { async: true })

App.Commentable = App.Attachable.extend
  comments: DS.hasMany('comment', { async: true })

App.Attachment = App.Commentable.extend
  user: DS.belongsTo('user', { async: true, readOnly: true })
  attachable: DS.belongsTo('attachable', { polymorphic: true, async: true })

App.Profile = App.Attachable.extend
  user: DS.belongsTo('user', { async: true, readOnly: true })
  photo: DS.belongsTo('attachment', { async: true })

App.Activity = App.Trackable.extend
  owner: DS.belongsTo('user', { async: true })
  recipient: DS.belongsTo('user', { async: true })
  trackable: DS.belongsTo('trackable', { polymorphic: true, async: true })

App.NotificationActivity = App.Activity.extend()

App.User = App.Model.extend
  profile:        DS.belongsTo('profile', { async: true })
  posts:          DS.hasMany('post', { async: true })
  attachments:    DS.hasMany('attachment', { async: true })
  friends:        DS.hasMany('user', { async: true })
  friendships:    DS.hasMany('friendship', { async: true })
  events:         DS.hasMany('event', { async: true })
  notifications:  DS.hasMany('notificationActivity', { async: true })

# edit controller

App.UserEditController = App.OverlayController.extend
  actions:
    save: ->
      profile = @get('model')
      profile.get('photo').then (photo) =>
        if photo.get('isDirty')
          photo.save().then (photo) =>
            profile.save().then =>
              @send 'close'
            , (error) ->
              profile.get('photo').deleteRecord()
              profile.get('photo').save()
              console.log error
          , (error) ->
            alert "Uh-oh, we couldn't save your new photo"
            console.log error

        else if profile.get('isDirty')
          profile.save().then =>
            @send 'close'
          , (error) ->
            alert "Uh-oh, something went wrong :("
            console.log error

        else
          @send 'close'

      , (error) ->
        alert "Uh-oh, couldn't load photo"
        console.log error

Main issue: When saving the photo, the serialiser fails because the belongsTo relationship is null meaning it can’t access the constructor.

I’m not sure if this is because a) I don’t have my relationships defined properly, or b) ember-data doesn’t keep track of the relationship graph.

If I try setting up the relationship explicitly before saving with photo.set('attachable', profile) then the serialiser still fails because belongsTo.constructor.typeKey is undefined.

** Queries**

  1. Before ember-data 1.0 this save method was much simpler as it used embedded relationships to save the profile and photo together in one API call. However, 1.0 seems to have phased out that type of API access which has resulted in much more complex code - is there a simpler way than constantly checking the success of saves in a chain and manual cleanup of already created relationships if latter saves fail?

  2. Is there anyway to retrieve an actual model from a .get('relationship' call rather than a promise object? I’m finding I’m having to work around this a lot throughout my app.

  3. I’ve found I need to create all of my polymorphic relationship models (attachable, commentable, etc) by extending the previous one in the chain otherwise I end up with errors such as You can only add a 'attachable' record to this relationship. This means every one of my models that uses a polymorphic relationship must include the entire chain even if it only uses one type of polymorphic association. Is there a way to do this with mixins or similar instead so there isn’t such a dependency problem?


#2

Hi :slight_smile: I’m curious about this because I don’t see your defintiions for the association targets (Attachment and NotificationActivity). Also, did you read the Ember Data transitioning document?

Sorry if I’m asking a question to which the answer is obvious.


#3

I’ve updated the code above to include the other model definitions, maybe it’s clearer to see the extend chain now.

I have read through the transitioning document many times but it appears I’m running into a bug somewhere with the polymorphic support.

It would be really useful to have a cookbook that shows the correct way to handle saving relationships asynchronously where you need to clean up previously created objects if the other side of the relationship fails to save.


#4

Cool thanks.

For what it’s worth, in my use of Ember Data 1.0 beta 2, I’ve found it absolutely necessary to specify the inverse relationships to get them to work. I don’t use polymorphic joins at all, so it might not be terribly helpful, but that was a major sticking point for me.


DS.Model, polymorphism, and multiple polymorphic associations
#5

I was wondering - does your JSON use the new polymorphic type format specified in transition.md? sorry for checking your basics…:

{
  "message": 12,
  "messageType": "post"
}

#6

I’m using the ActiveModelAdapter/Serializer so the JSON format hasn’t changed.

Manually querying all the relationships works but it’s saving that’s causing issues. I’ll have a look into specifying inverse relationships. Thanks.


#8

It really bothers me a lot that you have to “inherit” from the other “classes” in a chain like that. Hm…


#9

@lookingsideways did you ever find a solution to this? I’m having the same issue.

var key = relationship.key;
var belongsTo = get(record, key);
var jsonKey = underscore(key + "_type");

if (Ember.isNone(belongsTo)) {
  json[jsonKey] = null;
} else {
  json[jsonKey] = capitalize(camelize(belongsTo.constructor.typeKey));
}

by the last line, belongsTo.constructor is undefined as belongsTo is still not resolved.


#10

I’ve solved this issue, but I’m now seeing ‘Error: Assertion Failed: You can only add a ‘user’ record to this relationship’

user is the base class, but i’m adding a subclass to the record.