DS.attr / DS.Transform


#1

I’m attempting to write some DS.Transform classes, but I’m confused about the application of DS.attr. Values do not seem to get converted to boolean or number when using DS.attr(‘boolean’), DS.attr(‘number’).

export default DS.Model.extend({
  foo: DS.attr('boolean')
});

 var bar = this.store.createRecord('foomodel');
 bar.set('foo', 'hello');

Calling .get or checking using the Ember inspector, the value of foo is “hello”. No boolean conversion seems to be happening.

 Ember      : 2.3.0-beta.1
 Ember Data : v2.3.0-beta.1

#2

DS.attr('boolean') tells ember-data that you want to use DS.BooleanTransform when converting your model to/from JSON. Transforms don’t validate or modify the properties directly, instead they are run when your model is saved/loaded from the adapter. That’s why you can still set ‘foo’ to ‘hello’ or any other value. When you call bar.save(), the transform’s serialize fx will be called. In this case it will return Boolean('hello') and produce {foo: true} since hello is truthy. Have a look at https://github.com/emberjs/data/blob/v2.3.0-beta.1/addon/transforms/boolean.js to see how it works…


#3

For a boolean transform:

  • The strings “true” or “t” in any casing, or “1” will coerce to true, and false otherwise
  • The number 1 will coerce to true, and false otherwise
  • Anything other than boolean, string, or number will coerce to false

I wrote about it on my blog not too long ago: http://thejsguy.com/2015/11/23/a-look-into-ember-data-transforms.html


#4

Thanks guys! Great blog post skaterdav. I will do some more testing. Deserialize doesn’t seem to be executed on incoming data right now. I debugged the source code for BooleanTransform. I wonder if it is because I have a model serializer extending DS.RESTSerializer with a cusotm ‘normalizeArrayResponse’ function.


#5

Figured out what the issue was. Not sure if this had anything to do with it, but i wasn’t using the new JSONAPISerializer. Also wasn’t calling this.super() in normalizeArrayResponse, just returning the payload.


#6

I have it working. The only exception is that only models in payload.data are deserialized but not models in payload.included. Do you think this is a bug?


#7

What does your payload look like? Something like this?

{
  "data": {
    "type": "users",
    "id": "8",
    "attributes": {
      "first": "David",
      "last": "Tang"
    },
    "relationships": {
      "pets": {
        "data": [
          { "id": 1, "type": "pets" },
          { "id": 3, "type": "pets" }
        ]
      }
    }
  },
  "included": [
    {
      "type": "pets",
      "id": "1",
      "attributes": {
        "name": "Fiona"
      }
    },
    {
      "type": "pets",
      "id": "3",
      "attributes": {
        "name": "Biscuit"
      }
    }
  ]
}