ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
823 lines (790 loc) • 26.9 kB
JavaScript
import Ember from 'ember';
import { assert } from '@ember/debug';
import {
decoratedPropertyWithRequiredParams,
decoratedPropertyWithOptionalCallback
} from '../utils/decorator-macros';
import {
SUPPORTS_UNIQ_BY_COMPUTED
} from 'ember-compatibility-helpers';
/**
* Decorator that wraps [Ember.computed.alias](http://emberjs.com/api/classes/Ember.computed.html#method_alias)
*
* Creates a new property that is an alias for another property on an object.
* Calls to get or set this property behave as though they were called on
* the original property.
*
* ```javascript
* import Component from '@ember/component';
* import { alias } from 'ember-decorators/object/computed';
*
* export default class UserProfileComponent extends Component {
* person = {
* first: 'Joe'
* };
*
* @alias('person.first') firstName;
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the aliased property
*/
export const alias = decoratedPropertyWithRequiredParams(Ember.computed.alias);
/**
* Decorator that wraps [Ember.computed.and](http://emberjs.com/api/classes/Ember.computed.html#method_and)
*
* A computed property that performs a logical and on the original values
* for the provided dependent properties.
*
* ```javascript
* import Component from '@ember/component';
* import { and } from 'ember-decorators/object/computed';
*
* export default class UserProfileComponent extends Component {
* person = {
* first: 'Joe'
* };
*
* @and('person.{first,last}') hasFullName; // false
* }
* ```
*
* @function
* @param {...String} dependentKeys - Keys for properties to `and`
*/
export const and = decoratedPropertyWithRequiredParams(Ember.computed.and);
/**
* Decorator that wraps [Ember.computed.bool](http://emberjs.com/api/classes/Ember.computed.html#method_bool)
*
* A computed property that converts the provided dependent property into a
* boolean value.
*
* ```javascript
* import Component from '@ember/component';
* import { bool } from 'ember-decorators/object/computed';
*
* export default class MessagesNotificationComponent extends Component {
* messageCount = 1;
*
* @bool('messageCount') hasMessages; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to convert
*/
export const bool = decoratedPropertyWithRequiredParams(Ember.computed.bool);
/**
* Decorator that wraps [Ember.computed.collect](http://emberjs.com/api/classes/Ember.computed.html#method_collect)
*
* A computed property that returns the array of values for the provided
* dependent properties.
*
* ```javascript
* import Component from '@ember/component';
* import { collect } from 'ember-decorators/object/computed';
*
* export default class CameraEquipmentComponent extends Component {
* light = 'strobe';
* lens = '35mm prime';
*
* @collect('light', 'lens') equipment; // ['strobe', '35mm prime']
* }
* ```
*
* @function
* @param {...String} dependentKeys - Keys for the properties to collect
*/
export const collect = decoratedPropertyWithRequiredParams(Ember.computed.collect);
/**
* Decorator that wraps [Ember.computed.deprecatingAlias](http://emberjs.com/api/classes/Ember.computed.html#method_deprecatingAlias)
*
* Creates a new property that is an alias for another property on an object.
* Calls to get or set this property behave as though they were called on
* the original property, but will also trigger a deprecation warning.
*
* ```javascript
* import Component from '@ember/component';
* import { deprecatingAlias } from 'ember-decorators/object/computed';
*
* export default class UserProfileComponent extends {
* person = {
* first: 'Joe'
* };
*
* @deprecatingAlias('person.first', {
* id: 'user-profile.firstName',
* until: '3.0.0',
* url: 'https://example.com/deprecations/user-profile.firstName'
* }) firstName;
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to alias
* @param {Object} options
*/
export const deprecatingAlias = decoratedPropertyWithRequiredParams(Ember.computed.deprecatingAlias);
/**
* Decorator that wraps [Ember.computed.empty](http://emberjs.com/api/classes/Ember.computed.html#method_empty)
*
* A computed property that returns `true` if the value of the dependent
* property is null, an empty string, empty array, or empty function.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { empty } from 'ember-decorators/object/computed';
*
* export default class FoodItemsComponent extends Component {
* items = A(['taco', 'burrito']);
*
* @empty('items') isEmpty; // false
* }
* ```
*
* @function
* @param {String} dependentKey - Key of the property to check emptiness of
*/
export const empty = decoratedPropertyWithRequiredParams(Ember.computed.empty);
/**
* Decorator that wraps [Ember.computed.equal](http://emberjs.com/api/classes/Ember.computed.html#method_equal)
*
* A computed property that returns true if the dependent properties are equal.
*
* ```javascript
* import Component from '@ember/component';
* import { equal } from 'ember-decorators/object/computed';
*
* export default class NapTimeComponent extends Component {
* state = 'sleepy';
*
* @equal('state', 'sleepy') napTime; // true
* }
*
* @function
* @param {String} dependentKey - Key for the property to check
* @param {Any} value - Value to compare the dependent property to
*/
export const equal = decoratedPropertyWithRequiredParams(Ember.computed.equal);
/**
* Decorator that wraps [Ember.computed.filter](http://emberjs.com/api/classes/Ember.computed.html#method_filter)
*
* Filters the items in the array by the provided callback.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { filter } from 'ember-decorators/object/computed';
*
* export default class ChoresListComponent extends Component {
* chores = A([
* { name: 'cook', done: true },
* { name: 'clean', done: true },
* { name: 'write more unit tests', done: false }
* ]);
*
* @filter('chores')
* remainingChores(chore, index, array) {
* return !chore.done;
* } // [{name: 'write more unit tests', done: false}]
*
* // alternative syntax:
*
* @filter('chores', function(chore, index, array) {
* return !chore.done;
* }) remainingChores; // [{name: 'write more unit tests', done: false}]
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to filter
* @param {Function(item: Any, index: Number, array: Array<Any>): Boolean} callback - The function to filter with
*/
export const filter = decoratedPropertyWithOptionalCallback(Ember.computed.filter);
/**
* Decorator that wraps [Ember.computed.filterBy](http://emberjs.com/api/classes/Ember.computed.html#method_filterBy)
*
* Filters the array by the property and value.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { filterBy } from 'ember-decorators/object/computed';
*
* export default class ChoresListComponent extends Component {
* chores = A([
* { name: 'cook', done: true },
* { name: 'clean', done: true },
* { name: 'write more unit tests', done: false }
* ]);
*
* @filterBy('chores', 'done', false) remainingChores; // [{name: 'write more unit tests', done: false}]
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to filter
* @param {String} propertyKey - Property of the array items to filter by
* @param {Any} value - Value to filter by
*/
export const filterBy = decoratedPropertyWithRequiredParams(Ember.computed.filterBy);
/**
* Decorator that wraps [Ember.computed.gt](http://emberjs.com/api/classes/Ember.computed.html#method_gt)
*
* A computed property that returns `true` if the provided dependent property
* is greater than the provided value.
*
* ```javascript
* import Component from '@ember/component';
* import { gt } from 'ember-decorators/object/computed';
*
* export default class CatPartyComponent extends Component {
* totalCats = 11;
*
* @gt('totalCats', 10) isCatParty; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to compare
* @param {Number} value - Value to compare against
*/
export const gt = decoratedPropertyWithRequiredParams(Ember.computed.gt);
/**
* Decorator that wraps [Ember.computed.gte](http://emberjs.com/api/classes/Ember.computed.html#method_gte)
*
* A computed property that returns `true` if the provided dependent property
* is greater than or equal to the provided value.
*
* ```javascript
* import Component from '@ember/component';
* import { gte } from 'ember-decorators/object/computed';
*
* export default class PlayerListComponent extends Component {
* totalPlayers = 14;
*
* @gte('totalPlayers', 14) hasEnoughPlayers; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to compare
* @param {Number} value - Value to compare against
*/
export const gte = decoratedPropertyWithRequiredParams(Ember.computed.gte);
/**
* Decorator that wraps [Ember.computed.intersect](http://emberjs.com/api/classes/Ember.computed.html#method_intersect)
*
* A computed property which returns a new array with all the duplicated
* elements from two or more dependent arrays.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { intersect } from 'ember-decorators/object/computed';
*
* export default class FoodListComponent extends Component {
* likes = A([ 'tacos', 'puppies', 'pizza' ]);
* foods = A(['tacos', 'pizza']);
*
* @intersect('likes', 'foods') favoriteFoods; // ['tacos', 'pizza']
* }
* ```
*
* @function
* @param {...String} dependentKeys - Keys of the arrays to intersect
*/
export const intersect = decoratedPropertyWithRequiredParams(Ember.computed.intersect);
/**
* Decorator that wraps [Ember.computed.lt](http://emberjs.com/api/classes/Ember.computed.html#method_lt)
*
* A computed property that returns `true` if the provided dependent property
* is less than the provided value.
*
* ```javascript
* import Component from '@ember/component';
* import { lt } from 'ember-decorators/object/computed';
*
* export default class DogPartyComponent extends Component {
* totalDogs = 3;
*
* @lt('totalDogs', 10) isDogParty; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to compare
* @param {Number} value - Value to compare against
*/
export const lt = decoratedPropertyWithRequiredParams(Ember.computed.lt);
/**
* Decorator that wraps [Ember.computed.lte](http://emberjs.com/api/classes/Ember.computed.html#method_lte)
*
* A computed property that returns `true` if the provided dependent property
* is less than or equal to the provided value.
*
* ```javascript
* import Component from '@ember/component';
* import { lte } from 'ember-decorators/object/computed';
*
* export default class PlayerListComponent extends Component {
* totalPlayers = 14;
*
* @lte('totalPlayers', 14) hasEnoughPlayers; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to compare
* @param {Number} value - Value to compare against
*/
export const lte = decoratedPropertyWithRequiredParams(Ember.computed.lte);
/**
* Decorator that wraps [Ember.computed.map](http://emberjs.com/api/classes/Ember.computed.html#method_map)
*
* Returns an array mapped via the callback
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { map } from 'ember-decorators/object/computed';
*
* export default class ChoresListComponent extends Component {
* chores = A(['clean', 'write more unit tests']);
*
* @map('chores')
* loudChores(chore, index) {
* return chore.toUpperCase() + '!';
* } // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
*
* // alternative syntax:
*
* @map('chores', function(chore, index) {
* return chore.toUpperCase() + '!';
* }) loudChores; // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to map over
* @param {Function(item: Any, index: Number): Any} callback - Function to map over the array
*/
export const map = decoratedPropertyWithOptionalCallback(Ember.computed.map);
/**
* Decorator that wraps [Ember.computed.mapBy](http://emberjs.com/api/classes/Ember.computed.html#method_mapBy)
*
* Returns an array mapped to the specified key.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { mapBy } from 'ember-decorators/object/computed';
*
* export default class PeopleListComponent extends Component {
* people = A([
* {name: "George", age: 5},
* {name: "Stella", age: 10},
* {name: "Violet", age: 7}
* ]);
*
* @mapBy('people', 'age') ages; // [5, 10, 7]
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to map over
* @param {String} propertyKey - Property of the array items to map by
*/
export const mapBy = decoratedPropertyWithRequiredParams(Ember.computed.mapBy);
/**
* Decorator that wraps [Ember.computed.match](http://emberjs.com/api/classes/Ember.computed.html#method_match)
*
* A computed property which matches the original value for the dependent
* property against a given RegExp, returning `true` if they values matches
* the RegExp and `false` if it does not.
*
* ```javascript
* import Component from '@ember/component';
* import { match } from 'ember-decorators/object/computed';
*
* export default class IsEmailValidComponent extends Component {
* email = 'tomster@emberjs.com';
*
* @match('email', /^.+@.+\..+$/) validEmail;
* }
* ```
*
* @function
* @param {String} dependentKey - The property to match
* @param {RegExp} pattern - The pattern to match against
*/
export const match = decoratedPropertyWithRequiredParams(Ember.computed.match);
/**
* Decorator that wraps [Ember.computed.max](http://emberjs.com/api/classes/Ember.computed.html#method_max)
*
* A computed property that calculates the maximum value in the dependent
* array. This will return `-Infinity` when the dependent array is empty.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { max } from 'ember-decorators/object/computed';
*
* export default class MaxValueComponent extends Component {
* values = A([1, 2, 5, 10]);
*
* @max('values') maxValue; // 10
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to find the max value of
*/
export const max = decoratedPropertyWithRequiredParams(Ember.computed.max);
/**
* Decorator that wraps [Ember.computed.min](http://emberjs.com/api/classes/Ember.computed.html#method_min)
*
* A computed property that calculates the minimum value in the dependent
* array. This will return `Infinity` when the dependent array is empty.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { min } from 'ember-decorators/object/computed';
*
* export default class MinValueComponent extends Component {
* values = A([1, 2, 5, 10]);
*
* @min('values') minValue; // 1
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the array to find the max value of
*/
export const min = decoratedPropertyWithRequiredParams(Ember.computed.min);
/**
* Decorator that wraps [Ember.computed.none](http://emberjs.com/api/classes/Ember.computed.html#method_none)
*
* A computed property that returns true if the value of the dependent property
* is null or undefined. This avoids errors from JSLint complaining about use
* of `==`, which can be technically confusing.
*
* ```javascript
* import Component from '@ember/component';
* import { none } from 'ember-decorators/object/computed';
*
* export default class NameDisplayComponent extends Component {
* firstName = null;
*
* @none('firstName') isNameless; // true unless firstName is defined
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to check
*/
export const none = decoratedPropertyWithRequiredParams(Ember.computed.none);
/**
* Decorator that wraps [Ember.computed.not](http://emberjs.com/api/classes/Ember.computed.html#method_not)
*
* A computed property that returns the inverse boolean value of the original
* value for the dependent property.
*
* ```javascript
* import Component from '@ember/component';
* import { not } from 'ember-decorators/object/computed';
*
* export default class UserInfoComponent extends Component {
* loggedIn = false;
*
* @not('loggedIn') isAnonymous; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to `not`
*/
export const not = decoratedPropertyWithRequiredParams(Ember.computed.not);
/**
* Decorator that wraps [Ember.computed.notEmpty](http://emberjs.com/api/classes/Ember.computed.html#method_notEmpty)
*
* A computed property that returns `true` if the value of the dependent
* property is NOT null, an empty string, empty array, or empty function.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { notEmpty } from 'ember-decorators/object/computed';
*
* export default class GroceryBagComponent extends Component {
* groceryBag = A(['milk', 'eggs', 'apples']);
*
* @notEmpty('groceryBag') hasGroceriesToPutAway; // true
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to check
*/
export const notEmpty = decoratedPropertyWithRequiredParams(Ember.computed.notEmpty);
/**
* Decorator that wraps [Ember.computed.oneWay](http://emberjs.com/api/classes/Ember.computed.html#method_oneWay)
*
* Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
* data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
* not mutate the upstream property, rather causes the current property to
* become the value set. This causes the downstream property to permanently
* diverge from the upstream property.
*
* ```javascript
* import Component from '@ember/component';
* import { oneWay } from 'ember-decorators/object/computed';
*
* export default class UserProfileComponent extends Component {
* firstName = 'Joe';
*
* @oneWay('firstName') originalName; // will always be 'Joe'
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to alias
*/
export const oneWay = decoratedPropertyWithRequiredParams(Ember.computed.oneWay);
/**
* Decorator that wraps [Ember.computed.or](http://emberjs.com/api/classes/Ember.computed.html#method_or)
*
* A computed property which performs a logical or on the original values for
* the provided dependent properties.
*
* ```javascript
* import Component from '@ember/component';
* import { or } from 'ember-decorators/object/computed';
*
* export default class OutfitFeaturesComponent extends Component {
* hasJacket = true;
* hasUmbrella = false;
*
* @or('hasJacket', 'hasUmbrella') isReadyForRain; // true
* }
* ```
*
* @function
* @param {...String} dependentKey - Key for the properties to `or`
*/
export const or = decoratedPropertyWithRequiredParams(Ember.computed.or);
/**
* Decorator that wraps [Ember.computed.reads](http://emberjs.com/api/classes/Ember.computed.html#method_reads)
*
* This is a more semantically meaningful alias of `computed.oneWay`, whose
* name is somewhat ambiguous as to which direction the data flows.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { reads } from 'ember-decorators/object/computed';
*
* export default class UserProfileComponent extends Component {
* first = 'Tomster';
*
* @reads('first') firstName;
* }
* ```
*
* @function
* @param {String} dependentKey - Key for the property to read
*/
export const reads = decoratedPropertyWithRequiredParams(Ember.computed.reads);
/**
* Decorator that wraps [Ember.computed.setDiff](http://emberjs.com/api/classes/Ember.computed.html#method_setDiff)
*
* A computed property which returns a new array with all the properties from
* the first dependent array that are not in the second dependent array.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { setDiff } from 'ember-decorators/object/computed';
*
* export default class FavoriteThingsComponent extends Component {
* likes = A([ 'tacos', 'puppies', 'pizza' ]);
* foods = A(['tacos', 'pizza']);
*
* @setDiff('likes', 'foods') favoriteThingsThatArentFood; // ['puppies']
* }
* ```
*
* @function
* @param {String} setAProperty - Keys for the first set
* @param {String} setBProperty - Keys for the first set
*/
export const setDiff = decoratedPropertyWithRequiredParams(Ember.computed.setDiff);
/**
* Decorator that wraps [Ember.computed.sort](http://emberjs.com/api/classes/Ember.computed.html#method_sort)
*
* A computed property which returns a new array with all the properties from
* the first dependent array sorted based on a property or sort function.
*
*
* The callback method you provide should have the following signature:
*
* ```javascript
* function(itemA, itemB);
* ```
* - `itemA` the first item to compare.
* - `itemB` the second item to compare.
*
* This function should return negative number (e.g. `-1`) when `itemA` should
* come before `itemB`. It should return positive number (e.g. `1`) when
* `itemA` should come after `itemB`. If the `itemA` and `itemB` are equal this
* function should return `0`.
*
* Therefore, if this function is comparing some numeric values, simple
* `itemA - itemB` or `itemA.get( 'foo' ) - itemB.get( 'foo' )` can be used
* instead of series of `if`.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { sort } from 'ember-decorators/object/computed';
*
* export default class SortNamesComponent extends Component {
* names = A([{name:'Link'},{name:'Zelda'},{name:'Ganon'},{name:'Navi'}]);
*
* @sort('names')
* sortedNames(a, b){
* if (a.name > b.name) {
* return 1;
* } else if (a.name < b.name) {
* return -1;
* }
*
* return 0;
* } // [{name:'Ganon'},{name:'Link'},{name:'Navi'},{name:'Zelda'}]
*
* // alternative syntax:
*
* @sort('names', function(a, b){
* if (a.name > b.name) {
* return 1;
* } else if (a.name < b.name) {
* return -1;
* }
*
* return 0;
* }) sortedNames; // [{name:'Ganon'},{name:'Link'},{name:'Navi'},{name:'Zelda'}]
* }
* ```
*
* @function
* @param {String} dependentKey - The key for the array that should be sorted
* @param {Array<String>|Function(Any, Any): Number} sortDefinition - Sorting function or sort descriptor
*/
export const sort = decoratedPropertyWithOptionalCallback(Ember.computed.sort);
/**
* Decorator that wraps [Ember.computed.sum](http://emberjs.com/api/classes/Ember.computed.html#method_sum)
*
* A computed property that returns the sum of the value in the dependent
* array.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { sum } from 'ember-decorators/object/computed';
*
* export default class SumValuesComponent extends Component {
* values = A([1, 2, 3]);
*
* @sum('values') total; // 6
* }
* ```
*
* @function
* @param {String} dependentKey - Key of the array to sum up
*/
export const sum = decoratedPropertyWithRequiredParams(Ember.computed.sum);
/**
* Decorator that wraps [Ember.computed.union](http://emberjs.com/api/classes/Ember.computed.html#method_union)
*
* Alias for [union](http://emberjs.com/api/classes/Ember.computed.html#method_uniq).
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { union } from 'ember-decorators/object/computed';
*
* export default class LikesAndFoodsComponent extends Component {
* likes = A([ 'tacos', 'puppies', 'pizza' ]);
* foods = A(['tacos', 'pizza', 'ramen']);
*
* @union('likes', 'foods') favorites; // ['tacos', 'puppies', 'pizza', 'ramen']
* }
* ```
*
* @function
* @param {...String} dependentKeys - Keys of the arrays to union
*/
export const union = decoratedPropertyWithRequiredParams(Ember.computed.union);
/**
* Decorator that wraps [Ember.computed.uniq](http://emberjs.com/api/classes/Ember.computed.html#method_uniq)
*
* A computed property which returns a new array with all the unique elements from one or more dependent arrays.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { uniq } from 'ember-decorators/object/computed';
*
* export default class FavoriteThingsComponent extends Component {
* likes = A([ 'tacos', 'puppies', 'pizza' ]);
* foods = A(['tacos', 'pizza', 'ramen']);
*
* @uniq('likes', 'foods') favorites; // ['tacos', 'puppies', 'pizza', 'ramen']
* }
* ```
*
* @function
* @param {String} dependentKey - Key of the array to uniq
*/
export const uniq = decoratedPropertyWithRequiredParams(Ember.computed.uniq);
/**
* Decorator that wraps [Ember.computed.uniqBy](http://emberjs.com/api/classes/Ember.computed.html#method_uniqBy)
*
* A computed property which returns a new array with all the unique elements
* from an array, with uniqueness determined by a specific key.
*
* ```javascript
* import Component from '@ember/component';
* import { A } from '@ember/array';
* import { uniqBy } from 'ember-decorators/object/computed';
*
* export default class FruitBowlComponent extends Component {
* fruits = A([
* { name: 'banana', color: 'yellow' },
* { name: 'apple', color: 'red' },
* { name: 'kiwi', color: 'brown' },
* { name: 'cherry', color: 'red' },
* { name: 'lemon', color: 'yellow' }
* ]);
*
* @uniqBy('fruits', 'color') oneOfEachColor;
* // [
* // { name: 'banana', color: 'yellow'},
* // { name: 'apple', color: 'red'},
* // { name: 'kiwi', color: 'brown'}
* // ]
* }
* ```
*
* @function
* @param {String} dependentKey - Key of the array to uniq
* @param {String} propertyKey - Key of the property on the objects of the array to determine uniqueness by
*/
export const uniqBy = SUPPORTS_UNIQ_BY_COMPUTED ?
decoratedPropertyWithRequiredParams(Ember.computed.uniqBy) :
() => {
assert('uniqBy is only available from Ember.js v2.7 onwards.', false);
};