-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathattr.js
164 lines (142 loc) · 4.44 KB
/
attr.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import Ember from 'ember';
import { deprecate } from 'ember-data/-private/debug';
/**
@module ember-data
*/
function getDefaultValue(record, options, key) {
if (typeof options.defaultValue === 'function') {
return options.defaultValue.apply(null, arguments);
} else {
let defaultValue = options.defaultValue;
deprecate(`Non primitive defaultValues are deprecated because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`,
typeof defaultValue !== 'object' || defaultValue === null, {
id: 'ds.defaultValue.complex-object',
until: '3.0.0'
});
return defaultValue;
}
}
function hasValue(record, key) {
return key in record._attributes ||
key in record._inFlightAttributes ||
key in record._data;
}
function getValue(record, key) {
if (key in record._attributes) {
return record._attributes[key];
} else if (key in record._inFlightAttributes) {
return record._inFlightAttributes[key];
} else {
return record._data[key];
}
}
/**
`DS.attr` defines an attribute on a [DS.Model](/api/data/classes/DS.Model.html).
By default, attributes are passed through as-is, however you can specify an
optional type to have the value automatically transformed.
Ember Data ships with four basic transform types: `string`, `number`,
`boolean` and `date`. You can define your own transforms by subclassing
[DS.Transform](/api/data/classes/DS.Transform.html).
Note that you cannot use `attr` to define an attribute of `id`.
`DS.attr` takes an optional hash as a second parameter, currently
supported options are:
- `defaultValue`: Pass a string or a function to be called to set the attribute
to a default value if none is supplied.
Example
```app/models/user.js
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr('string'),
email: DS.attr('string'),
verified: DS.attr('boolean', { defaultValue: false })
});
```
Default value can also be a function. This is useful it you want to return
a new object for each attribute.
```app/models/user.js
import DS from 'ember-data';
export default DS.Model.extend({
username: attr('string'),
email: attr('string'),
settings: attr({defaultValue: function() {
return {};
}})
});
```
@namespace
@method attr
@for DS
@param {String} type the attribute type
@param {Object} options a hash of options
@return {Attribute}
*/
export default function attr(type, options) {
if (typeof type === 'object') {
options = type;
type = undefined;
} else {
options = options || {};
}
var meta = {
type: type,
isAttribute: true,
options: options
};
return Ember.computed({
get(key) {
var internalModel = this._internalModel;
if (hasValue(internalModel, key)) {
return getValue(internalModel, key);
} else {
return getDefaultValue(this, options, key);
}
},
set(key, value) {
var internalModel = this._internalModel;
var oldValue = getValue(internalModel, key);
if (value !== oldValue) {
// Add the new value to the changed attributes hash; it will get deleted by
// the 'didSetProperty' handler if it is no different from the original value
internalModel._attributes[key] = value;
this._internalModel.send('didSetProperty', {
name: key,
oldValue: oldValue,
originalValue: internalModel._data[key],
value: value
});
}
return value;
}
}).meta(meta);
}
// TODO add to documentation of `attr` function above, once this feature is added
// /**
// * The `options` hash is passed as second argument to a transforms'
// * `serialize` and `deserialize` method. This allows to configure a
// * transformation and adapt the corresponding value, based on the config:
// *
// * ```app/models/post.js
// * export default DS.Model.extend({
// * text: DS.attr('text', {
// * uppercase: true
// * })
// * });
// * ```
// *
// * ```app/transforms/text.js
// * export default DS.Transform.extend({
// * serialize: function(value, options) {
// * if (options.uppercase) {
// * return value.toUpperCase();
// * }
// *
// * return value;
// * },
// *
// * deserialize: function(value) {
// * return value;
// * }
// * })
// * ```
// *
// */