包详细信息

ember-data-model-fragments

adopted-ember-addons56.5kMIT6.0.10

Ember Data addon to support nested JSON documents

ember-addon, ember, ember-data, ember-cli

自述文件

Ember Data Model Fragments

CI NPM Version Ember Observer Score

This package provides support for sub-models that can be treated much like belongsTo and hasMany relationships are, but whose persistence is managed completely through the parent object.

:warning: Deprecated APIs have been removed. See the changelog for more information on breaking changes.

Compatibility

This project makes extensive use of private Ember Data APIs and is therefore sensitive to minor changes in new Ember Data releases, regardless of semver guarantees. Every effort is made to maintain compatibility with the latest version, but updates always take time. See the contributing section if you'd like to help out :shipit:

Use the following table to decide which version of this project to use with your app:

Ember Data Model Fragments Node.JS
>= v3.5.x < v3.12.x v4.x 10+
>= v3.13.x < v3.27.x v5.x 12+
>= v3.28.x < v4.6.x v6.x 14+
>= v4.7.x Not Compatible

Installation

To install as an Ember CLI addon:

$ ember install ember-data-model-fragments

You may then start creating fragments with:

$ ember generate fragment foo someAttr:string anotherAttr:boolean

Which will create the module app/models/foo.js which exports a Fragment class with the given attributes.

Example

// app/models/person.js

import Model from "@ember-data/model";
import {
  fragment,
  fragmentArray,
  array,
} from "ember-data-model-fragments/attributes";

export default class PersonModel extends Model {
  @fragment("name") name;
  @fragmentArray("address") addresses;
  @array() titles;
}
// app/models/name.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class NameFragment extends Fragment {
  @attr("string") first;
  @attr("string") last;
}
// app/models/address.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class AddressFragment extends Fragment {
  @attr("string") street;
  @attr("string") city;
  @attr("string") region;
  @attr("string") country;
}

With a JSON payload of:

{
  "person": {
    "id": "1",
    "name": {
      "first": "Tyrion",
      "last": "Lannister"
    },
    "addresses": [
      {
        "street": "1 Sky Cell",
        "city": "Eyre",
        "region": "Vale of Arryn",
        "country": "Westeros"
      },
      {
        "street": "1 Tower of the Hand",
        "city": "King's Landing",
        "region": "Crownlands",
        "country": "Westeros"
      }
    ],
    "titles": ["Imp", "Hand of the King"]
  }
}

The name attribute can be treated similar to a belongsTo relationship:

const person = store.peekRecord("person", "1");
const name = person.get("name");

person.get("hasDirtyAttributes"); // false
name.get("first"); // 'Tyrion'

name.set("first", "Jamie");
person.get("hasDirtyAttributes"); // true

person.rollbackAttributes();
name.get("first"); // 'Tyrion'

// New fragments are created through the store and assigned directly
person.set(
  "name",
  store.createFragment("name", {
    first: "Hugor",
    last: "Hill",
  })
);
person.get("hasDirtyAttributes"); // true

// Fragments can also be set with hashes
person.set("name", {
  first: "Tyrion",
  last: "Lannister",
});
person.get("hasDirtyAttributes"); // false

The addresses attribute can be treated similar to a hasMany relationship:

const person = store.peekRecord("person", "1");
const addresses = person.get("addresses");
const address = addresses.get("lastObject");

person.get("hasDirtyAttributes"); // false
address.get("country"); // 'Westeros'

address.set("country", "Essos");
person.get("hasDirtyAttributes"); // true

person.rollbackAttributes();
address.get("country"); // 'Westeros'

// Fragments can be created and added directly through the fragment array
addresses.get("length"); // 2
addresses.createFragment({
  street: "1 Shy Maid",
  city: "Rhoyne River",
  region: "Free Cities",
  country: "Essos",
});
addresses.get("length"); // 3
person.get("hasDirtyAttributes"); // true

// Or with arrays of objects
person.set("addresses", [
  {
    street: "1 Great Pyramid",
    city: "Meereen",
    region: "Slaver's Bay",
    country: "Essos",
  },
]);

The titles attribute can be treated as an Ember.Array:

const person = store.peekRecord("person", "1");
const titles = person.get("titles");

person.get("hasDirtyAttributes"); // false
titles.get("length"); // 2

titles.pushObject("Halfman");
titles.get("length"); // 3
person.get("hasDirtyAttributes"); // true

person.rollbackAttributes();
titles.get("length"); // 2

Default Values

Ember Data attributes support a defaultValue config option that provides a default value when a model is created through store#createRecord(). Similarly, fragment and fragmentArray properties support a defaultValue option:

// app/models/person.js

import Model from "@ember-data/model";
import {
  fragment,
  fragmentArray,
  array,
} from "ember-data-model-fragments/attributes";

export default class PersonModel extends Model {
  @fragment("name", { defaultValue: { first: "Faceless", last: "Man" } }) name;
  @fragmentArray("address") addresses;
  @array("string") titles;
}

Since JavaScript objects and arrays are passed by reference, the value of defaultValue is copied using Ember.copy in order to prevent all instances sharing the same value. If a defaultValue option is not specified, fragment properties default to null and fragmentArray properties default to an empty array. Note that this may cause confusion when creating a record with a fragmentArray property:

const person = store.createRecord('person');
const addresses = person.get('addresses'); // null

// Fails with "Cannot read property 'createFragment' of null"
addresses.createFragment({
  ...
});

Like attr, the defaultValue option can be a function that is invoked to generate the default value:

// app/models/person.js

import Model from "@ember-data/model";
import { fragment } from "ember-data-model-fragments/attributes";

export default class PersonModel extends Model {
  @fragment("name", {
    defaultValue() {
      return {
        first: "Unsullied",
        last: new Date().toString(),
      };
    },
  })
  name;
}

Serializing

Serializing records with fragment attributes works using a special Transform that serializes each fragment or fragment array. This results in fragments being nested in JSON as expected, and avoids the need for any custom serialization logic for most cases. This also means that model fragments can have their own custom serializers, just as normal models can:

// app/models/name.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class NameFragment extends Fragment {
  @attr("string") given;
  @attr("string") family;
}
// apps/serializers/name.js
// Serializers for fragments work just as with models

import JSONSerializer from "@ember-data/serializer/json";

export default class NameSerializer extends JSONSerializer {
  attrs = {
    given: "first",
    family: "last",
  };
}

Since fragment deserialization uses the value of a single attribute in the parent model, the normalizeResponse method of the serializer is never used. And since the attribute value is not a full-fledged JSON API response, JSONAPISerializer cannot be used with fragments. Because of this, auto-generated fragment serializers do not use the application serializer and instead use JSONSerializer.

If common logic must be added to auto-generated fragment serializers, apps can register a custom serializer:-fragment with the application in an initializer.

// app/serializers/fragment.js

import JSONSerializer from "@ember-data/serializer/json";

export default class FragmentSerializer extends JSONSerializer {}
// app/initializers/fragment-serializer.js

import FragmentSerializer from "../serializers/fragment";

export function initialize(application) {
  application.register("serializer:-fragment", FragmentSerializer);
}

export default {
  name: "fragment-serializer",
  initialize: initialize,
};

If custom serialization of the owner record is needed, fragment snapshots can be accessed using the Snapshot#attr method. Note that this differs from how relationships are accessed on snapshots (using belongsTo/hasMany methods):

// apps/serializers/person.js
// Fragment snapshots are accessed using `snapshot.attr()`

import JSONSerializer from "@ember-data/serializer/json";

export default JSONSerializer.extend({
  serialize(snapshot, options) {
    const json = super.serialize(...arguments);

    // Returns a `Snapshot` instance of the fragment
    const nameSnapshot = snapshot.attr("name");

    json.full_name =
      nameSnapshot.attr("given") + " " + nameSnapshot.attr("family");

    // Returns a plain array of `Snapshot` instances
    const addressSnapshots = snapshot.attr("addresses");

    json.countries = addressSnapshots.map(function (addressSnapshot) {
      return addressSnapshot.attr("country");
    });

    // Returns a plain array of primitives
    const titlesSnapshot = snapshot.attr("titles");

    json.title_count = titlesSnapshot.length;

    return json;
  },
});

Nesting

Nesting of fragments is fully supported:

// app/models/user.js

import Model, { attr } from "@ember-data/model";
import { fragmentArray } from "ember-data-model-fragments/attributes";

export default class UserModel extends Model {
  @attr("string") name;
  @fragmentArray("order") orders;
}
// app/models/order.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";
import { fragmentArray } from "ember-data-model-fragments/attributes";

export default class OrderFragment extends Fragment {
  @attr("string") amount;
  @fragmentArray("product") products;
}
// app/models/product.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class ProductFragment extends Fragment {
  @attr("string") name;
  @attr("string") sku;
  @attr("string") price;
}

With a JSON payload of:

{
  "id": "1",
  "name": "Tyrion Lannister",
  "orders": [
    {
      "amount": "799.98",
      "products": [
        {
          "name": "Tears of Lys",
          "sku": "poison-bd-32",
          "price": "499.99"
        },
        {
          "name": "The Strangler",
          "sku": "poison-md-24",
          "price": "299.99"
        }
      ]
    },
    {
      "amount": "10999.99",
      "products": [
        {
          "name": "Lives of Four Kings",
          "sku": "old-book-32",
          "price": "10999.99"
        }
      ]
    }
  ]
}

Dirty state propagates up to the parent record, rollback cascades down:

const user = store.peekRecord("user", "1");
const product = user.get("orders.firstObject.products.lastObject");

user.get("hasDirtyAttributes"); // false
product.get("price"); // '299.99'

product.set("price", "1.99");
user.get("hasDirtyAttributes"); // true

user.rollbackAttributes();
user.get("hasDirtyAttributes"); // false
product.get("price"); // '299.99'

However, note that fragments do not currently support belongsTo or hasMany properties. See the Limitations section below.

Polymorphism

Ember Data: Model Fragments has support for reading polymorphic fragments. To use this feature, pass an options object to fragment or fragmentArray with polymorphic set to true. In addition the typeKey can be set, which defaults to 'type'.

The typeKey option might be a String or a Function returning a String. If you use a function, the data and the owner will be passed as parameter.

The typeKey's value must be the lowercase name of a class that is assignment-compatible to the declared type of the fragment attribute. That is, it must be the declared type itself or a subclass. Additionally, the typeKey's value must be a field on the parent class.

In the following example the declared type of animals is animal, which corresponds to the class Animal. Animal has two subclasses: Elephant and Lion, so to typeKey's value can be 'animal', 'elephant' or 'lion'.

// app/models/zoo.js

import Model, { attr } from "@ember-data/model";
import { fragment, fragmentArray } from "ember-data-model-fragments/attributes";

export default class ZooModel extends Model {
  @attr("string") name;
  @attr("string") city;
  @fragmentArray("animal", { polymorphic: true, typeKey: "$type" }) animals;
  @fragment("animal", {
    polymorphic: true,
    typeKey: (data) => `my-model-prefix-${data.name}`,
  })
  bestAnimal;
}
// app/models/animal.js

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class AnimalFragment extends Fragment {
  @attr("string") $type;
  @attr("string") name;
}
// app/models/elephant.js

import AnimalFragment from "./animal";
import { attr } from "@ember-data/model";

export default class ElephantFragment extends AnimalFragment {
  @attr("number") trunkLength;
}
// app/models/lion.js

import AnimalFragment from "./animal";
import { attr } from "@ember-data/model";

export default class LionFragment extends AnimalFragment {
  @attr("boolean") hasManes;
}

The expected JSON payload is as follows:

{
  "Zoo": {
    "id": "1",
    "name": "Winterfell Zoo",
    "city": "Winterfell",
    "animals": [
      {
        "$type": "lion",
        "name": "Simba",
        "hasManes": false
      },
      {
        "$type": "lion",
        "name": "Leonard",
        "hasManes": true
      },
      {
        "$type": "elephant",
        "name": "Trunky",
        "trunkLength": 10
      },
      {
        "$type": "elephant",
        "name": "Snuffles",
        "trunkLength": 9
      }
    ]
  }
}

Serializing the fragment type back to JSON is not currently supported out of the box. To serialize the polymorphic type, create a custom serializer to perform manual introspection:

// app/serializers/animal.js

import JSONSerializer from "@ember-data/serializer/json";
import ElephantFragment from "app/models/elephant";
import LionFragment from "app/models/elephant";

export default class AnimalSerializer extends JSONSerializer {
  serialize(record, options) {
    const json = super.serialize(...arguments);

    if (record instanceof ElephantFragment) {
      json.$type = "elephant";
    } else if (record instanceof LionFragment) {
      json.$type = "lion";
    } else {
      json.$type = "animal";
    }

    return json;
  }
}
// app/serializers/elephant.js

import AnimalSerializer from "./animal";

export default AnimalSerializer;
// app/serializers/lion.js

import AnimalSerializer from "./animal";

export default AnimalSerializer;

TypeScript

TypeScript declarations are included out of the box. For additional type safety for createFragment, push, etc. you can index your fragment classes in the FragmentRegistry:

// app/models/address.ts

import Fragment from "ember-data-model-fragments/fragment";
import { attr } from "@ember-data/model";

export default class AddressFragment extends Fragment {
  @attr("string")
  declare street: string;

  @attr("string")
  declare city: string;

  @attr("string")
  declare region: string;

  @attr("string")
  declare country: string;
}

declare module "ember-data-model-fragments/types/registries/fragment" {
  export default interface FragmentRegistry {
    address: AddressFragment;
  }
}

Limitations

Conflict Resolution

There is a very good reason that support for id-less embedded records has not been added to Ember Data: merging conflicts is very difficult. Imagine a scenario where your app requests a record with an array of simple embedded objects, and then a minute later makes the same request again. If the array of objects has changed – for instance an object is added to the beginning – without unique identifiers there is no reliable way to map those objects onto the array of records in memory.

This plugin handles merging fragment arrays by swapping out the data of existing fragments. For example, when a record is fetched with a fragment array property, a fragment model is created for each object in the array. Then, after the record is reloaded via reload or save, the data received is mapped directly onto those existing fragment instances, adding or removing from the end when necessary. This means that reordering the array will cause fragment objects' data to swap, rather than simply reordering the array of fragments in memory. The biggest implication of this behavior is when a fragment in a fragment array is dirty and the parent model gets reloaded. If the record is then saved, the change will likely affect the wrong object, causing data loss. Additionally, any time a reference to a model fragment is held onto, reloading can give it a completely different semantic meaning. If your app does not persist models with fragment arrays, this is of no concern (and indeed you may wish to use the EmbeddedRecordMixin instead).

Filtered Record Arrays

Another consequence of id-less records is that an ID map of all fragment instances of a given type is not possible. This means no store.all('<fragment_type>'), and no ability to display all known fragments (e.g. names or addresses) without iterating over all owner records and manually building a list.

Relationships to Models

Currently, fragments cannot have normal belongsTo or hasMany relationships. This is not a technical limitation, but rather due to the fact that relationship management in Ember Data is in a state of flux and would require accessing private (and changing) APIs.

Testing

Building requires Ember CLI and running tests requires Test 'Em, which can all be installed globally with:

$ yarn global add ember-cli

Then install NPM packages and start the development test server:

$ yarn
$ ember test --server

It is also possible to run the tests in a headless fashion. This requires PhantomJS 2 to be installed.

$ ember test

# Using `yarn test` will invoke `ember try:testall`.
# This will test each version of ember supported by this addon.
$ yarn test

Contributing

When reporting an issue, follow the Ember guidelines. When contributing features, follow Github guidelines for forking and creating a new pull request. All existing tests must pass (or be suitably modified), and all new features must be accompanied by tests to be considered.

更新日志

Changelog

v5.0.0-beta.3 (December 22, 2021)

v6.0.10 (2024-05-22)

:bug: Bug Fix

  • #488 Preserve fragment array state after the record is unloaded (@dwickern)

Committers: 1

v6.0.9 (2024-05-06)

:bug: Bug Fix

  • #487 Fix updating fragment arrays multiple times in the same runloop (@dwickern)

Committers: 1

v6.0.8 (2024-03-20)

:bug: Bug Fix

  • #486 fix passing arbitrary props to fragmentArray.createFragment (@dwickern)

Committers: 1

v6.0.7 (2024-02-13)

:bug: Bug Fix

:house: Internal

Committers: 1

v6.0.6 (2023-12-13)

v6.0.5 (2023-09-30)

:bug: Bug Fix

  • #480 fix(changedAttributes): initial value of property which are supposed to be null return a value when the record is in flight (@VincentMolinie)

Committers: 1

v6.0.4 (2023-09-01)

:bug: Bug Fix

Committers: 1

v6.0.3 (2023-07-20)

:bug: Bug Fix

  • #476 changedAttributes still return the dirty attributes until the record has been fully committed (@VincentMolinie)

Committers: 1

v6.0.2 (2023-07-15)

:bug: Bug Fix

  • #474 fix(polymorphism): fix regression introduced with ember-data-model-fragments 6.0.0 where owner is not passed to typeKey function (@VincentMolinie)
  • #472 Ensure changing arrays are notified. (@deanmarano)
  • #469 Fix issue with reloading array records. (@deanmarano)

:house: Internal

Committers: 2

v6.0.1 (2023-05-30)

:bug: Bug Fix

  • #466 Fix glimmer render error when creating fragment arrays (@dwickern)

:house: Internal

Committers: 1

v6.0.0 (2023-05-26)

:boom: Breaking Change

:rocket: Enhancement

:bug: Bug Fix

:memo: Documentation

:house: Internal

Committers: 5

v5.0.0 (2023-02-02)

:bug: Bug Fix

Committers: 1

v5.0.0-beta.9 (2023-01-16)

:rocket: Enhancement

:bug: Bug Fix

  • #447 Handle null record in isStateInitializing (@richgt)

:house: Internal

Committers: 3

v5.0.0-beta.8 (2022-06-07)

:bug: Bug Fix

:house: Internal

Committers: 2

v5.0.0-beta.7 (2022-04-21)

v5.0.0-beta.6 (2022-04-14)

:bug: Bug Fix

  • #432 fix(serializer): fix the deserialization when using a typeKey as a function (@VincentMolinie)

:house: Internal

Committers: 2

v5.0.0-beta.5 (2022-03-17)

:bug: Bug Fix

  • #431 fix(dirty state): prevent record from being tagged as dirty when not changed (@VincentMolinie)

Committers: 1

v5.0.0-beta.4 (2022-03-16)

:rocket: Enhancement

  • #430 feat(polymorphism): add the possibility to compute the type based on owner and data (@VincentMolinie)

:bug: Bug Fix

:house: Internal

Committers: 2

What's Changed

Breaking change

Before v5.0.0-beta.3, when setting a fragment array property to null from a server response, it wouldn't nullify the attribute. Instead, the fragment array instance just became empty with no items inside. Now updating the fragment array to null works correctly and is consistent with fragments behaviour. For more details see https://github.com/adopted-ember-addons/ember-data-model-fragments/pull/415.

v5.0.0-beta.2 (April 20, 2021)

  • 🐛 Bugfix: #397 Use send('loadedData') instead of loadedData method (@runspired)

v5.0.0-beta.1 (November 12, 2020)

  • #381 Fix hasDirtyAttributes when resetting a property (@VincentMolinie)
  • #385 Upgrade to Ember 3.20 LTS (@patocallaghan)

v5.0.0-beta.0 (May 28, 2020)

  • #360 Upgrade to work with Ember Data 3.16 (@richgt, @igorT)

v4.0.0 (January 25, 2019)

  • Ember 3.5.0 compatibility with breaking changes related to RecordData. (@cohitre)
  • Fixed changedAtributes with fragments (@Gorzas)

v3.3.0 (August 2nd, 2018)

  • Update Ember to 3.3.0 (@jakesjews)
  • Fixed ember-data compatibility the fields property on ember-data model class (@rondale-sc)
  • Fixed bug with setting array fragment attr to null (@Techn1x)
  • Use ember-copy instead of Ember.copy/Ember.Copyable (@pauln)
  • Removed deprecated exports (@jakesjews)
  • Replace exists-sync package with fs.existsSync (@jakesjews)
  • Fix ember-data compatibility with type.modelName and _internalModel.modelName (@JosephHalter)
  • Prevent infinite recursion on save with fragmentArray (@JosephHalter)
  • When defaultValue is a function, don't copy (@Techn1x)

v3.0.0 (April 4th, 2018)

  • Upgrade to Ember 3.0 (@jakesjews)

v3.0.0-beta.1 (February 7th, 2018)

  • Added support for Ember-Data 3.0 (@rondale-sc, @jakesjews)
  • Upgraded to Ember 2.15, 2.16, 2.17 (@jakesjews)
  • Switched from NPM to Yarn (@jakesjews)
  • Added cacheKeyForTree to the build pipeline (@thec0keman)

v2.14.0 (June 27th, 2017)

  • Added support for Ember-Data 2.14 (@workmanw)

v2.11.5 (June 19th, 2017)

  • Fixed bug with fragments invoking ready callback (@danielspaniel)

v2.11.4 (June 10th, 2017)

  • Reverting prior bugfix. Unfortunately the fix resulted in infinite loop in for some users. (@jakesjews)

v2.11.3 (May 5th, 2017)

  • Upgrade to Ember 2.13 (@workmanw)
  • Fixed Ember-Data 2.13.0 issue related to internalModel caching change. (@workmanw)
  • Upgrade to Ember 2.12 (@jakesjews)

v2.11.2 (March 1st, 2017)

  • Fixed Ember-Data 2.11.2 issue caused by modelFactoryFor change (@workmanw)

v2.11.1 (February 19th, 2017)

  • Fixed max call stack error aka Alias Loop (@kobsy, Rob Riebau <github handle unknown>)
  • Replaced JSHint with ESLint (@workmanw)
  • Renamed the ES6 module from model-fragments to ember-data-model-fragments (@workmanw)
  • ES6-ified the addon. Utilized ES6 conveniences more throughout the codebase (@workmanw)
  • Fixed an Ember-Data 2.12 compatibility issue (@workmanw)
  • Removed deprecation from upcoming Ember 2.12 release (@workmanw)
  • Updated to ember-cli 2.11.0 (@jakesjews)

v2.11.0 (January 19th, 2017)

  • Fixed infinite loop issue caused by deprecation of store.lookupSerializer (@runspired, @workmanw)
  • Added store.isFragment for easier detection (@gavinjoyce)
  • Removed usage of deprecated Ember.K (@cibernox)

v2.3.3 (December 12, 2016)

  • Updated to ember-cli 2.10.0 (@jakesjews)
  • Use the ember-data initializer as a target instead of the soon to be deprecated store initializer (@bmac)
  • Fixed issue that caused internalModel is null exception (@cesarizu)

v2.3.2 (June 18, 2016)

  • Fixed ember-cli deprecation warning (@jakesjews)

v2.3.1 (April 20, 2016)

  • Fixed issue with deprecated use of Ember.get (@jakesjews)

v2.3.0 (March 31, 2016)

  • Fully converted to ember-cli addon (@jakesjews, @workmanw)

v2.1.2 (March 21, 2016)

  • Fixed memory leak caused by fragments not being destroyed (@dwickern)
  • Fixed issue with rolling back fragments after adapter error (@workmanw)
  • Fixed isNew not reporting correct state

v1.13.3 (March 21, 2016)

  • Backported fix for memory leak caused by fragments not being destroyed (@dwickern)
  • Backported fix for issue with rolling back fragments after adapter error (@workmanw)
  • Backported fix for isNew not reporting correct state

v2.1.1 (December 23, 2015)

  • Fixed issue with store.push leaving records dirty

v2.0.2 (December 23, 2015)

  • Backported fix for issue with store.push leaving records dirty

v1.13.2 (December 23, 2015)

  • Backported fix for issue with store.push leaving records dirty

v2.1.0 (November 15, 2015)

  • Updated Ember/ED > v2.1.x
  • Fixed initializer argument deprecation

v2.0.1 (November 15, 2015)

  • Fixed issue with looking up application/default serializers with store#serializerFor (@thec0keman)

v1.13.1 (November 15, 2015)

  • Backported fix for application/default serializer lookup

v2.0.0 (October 28, 2015)

  • Removed Deprecated APIs
  • Fixed breaking changes in Ember 2.0
  • Fixed deserialization issue when isNewSerializerAPI is not specified
Breaking Changes

The isDirty and rollback methods on fragments and fragment arrays have been removed (use hasDirtyAttributes and rollbackAttributes instead).

v1.13.0 (October 25, 2015)

  • Removed deprecated APIs
  • Changed default value of fragment array properties to an empty array
  • Changed repository name
Breaking Changes

Deprecated APIs have been removed:

  • DS.ModelFragmentMF.Fragment
  • DS.hasOneFragmentMF.fragment
  • DS.hasManyFragmentsMF.fragmentArray
  • DS.fragmentOwnerMF.fragmentOwner

Support for non-fragment array properties has been added with the new property MF.array, which supports transforms:

export default DS.Model.extend({
  things: MF.array('string'),
  stuff: MF.array('my-custom-transform')
});

The default value of fragment array properties is now an empty array (previously null):

export default DS.Model.extend({
  things: MF.fragmentArray('some-fragment'), // { defaultValue: [] } option is no longer necessary
  stuff: MF.array('string') // Defaults to an empty array as well
});

The repository name has changed from ember-data.model-fragments to ember-data-model-fragments. This does not affect the NPM package name, but does affect the Bower package. Consequently, when upgrading from v0.4.x to v1.13.x, in addition to making sure the addon blueprint runs, the old Bower package must be removed manually:

$ bower uninstall --save ember-data.model-fragments

v0.4.4 (October 25, 2015)

  • Reverted clearing fragment owner to maintain rollback support
  • Fixed issue with record dirtiness when setting with object literal

v0.4.3 (October 14, 2015)

  • Updated API and added deprecation warnings to all outdated APIs
  • Fixed issue with initializer arguments in Ember 2.1 (@jakesjews)

v0.4.2 (October 11, 2015)

  • Added support for setting fragment properties with object literals
  • Fixed issue with fragment properties not being notified on create
  • Fixed falsy default values being clobbered (@christophersansone)
  • Fixed bad registry property reference in Ember v2.1 (@abuiles)
  • Updated fragment properties to clear owner when releasing fragments

v0.4.1 (August 19, 2015)

  • Added warning about changing default value for array fragment properties
  • Added support for copying nested fragments (@louy)
  • Fixed broken fragment copying (@jakesjews)

v0.4.0 (August 14, 2015)

  • Updated to support Ember Data v1.13

v0.3.3 (May 20, 2015)

  • Removed deprecations in test suite
  • Removed computed property deprecations (@jakesjews)
  • Added fragment transform module for unit testing ember-cli apps (@rwjblue)

v0.3.2 (April 20, 2015)

  • Removed duplicate addon definition

v0.3.1 (March 30, 2015)

  • Fixed "properly formatted package" ember-cli warning
  • Fixed bad file name in 'fragment' blueprint using pod structure

v0.3.0 (February 27, 2015)

  • Added support for Snapshots to support Ember Data v1.0.0-beta.15
  • Added explicit ordering to ember-cli addon

v0.2.8 (February 2, 2015)

  • Fixed infinite loops when reloading observed fragments (@igort)

v0.2.7 (January 16, 2015)

  • Fixed issue with multiple rollbacks failing
  • Fixed issue with changed properties not being notified on reload

v0.2.6 (January 8, 2015)

  • Fixed infinite recursion issue after save when observing fragment array props
  • Fixed issue with ember install:addon not invoking correct blueprint
  • Fixed issue with Ember CLI including addon dir in JS tree

v0.2.5 (January 6, 2015)

  • Support type checks with Ember.MODEL_FACTORY_INJECTIONS set to true
  • Fixed issue with broken ember-cli install:addon

v0.2.4 (January 5, 2015)

  • Updated to support Ember Data v1.0.0-beta.14 (@igort)

v0.2.3 (January 5, 2015)

  • Added Ember CLI addon
  • Updated Ember Data version dependency in Bower package

v0.2.2 (November 3, 2014)

  • Added support for polymorphic fragments (@marcus-nl)

v0.2.1 (October 2, 2014)

  • Fixed infinite recursion issue with nested hasManyFragments
  • Fragment array reloads now notify array observers,
  • Fix bower runtime dependencies to include Ember Data

v0.2.0 (May 22, 2014)

  • Reformatted/added comments to conform to YUIDoc
  • Fixed issue with saving a record with null fragments
  • Fixed issue with rollback when fragment is set to null
  • Fixed issue with fragment array methods bypassing replaceContent
  • Added support for empty adapter response
  • Fixed issue with owner-less fragments on new records
  • Added limited support for fragments in DS.Model#changedAttributes
  • Fixed issue with setting a hasOneFragment property to null
  • Fixed issue with hasOneFragment default values

v0.1.0 (May 20, 2014)

  • Initial release compatible with original gist