Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion features.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"ember-metal-injected-properties": null,
"mandatory-setter": "development-only",
"ember-routing-fire-activate-deactivate-events": null,
"ember-testing-pause-test": null
"ember-testing-pause-test": null,
"improved-cp-syntax": null
},
"debugStatements": [
"Ember.warn",
Expand Down
34 changes: 27 additions & 7 deletions packages/ember-metal/lib/computed.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ ComputedPropertyPrototype.teardown = function(obj, keyName) {
The function should accept two parameters, key and value. If value is not
undefined you should set the value first. In either case return the
current value of the property.

A computed property defined in this way might look like this:

```js
Expand All @@ -516,7 +516,7 @@ ComputedPropertyPrototype.teardown = function(obj, keyName) {
var client = Person.create();

client.get('fullName'); // 'Betty Jones'

client.set('lastName', 'Fuller');
client.get('fullName'); // 'Betty Fuller'
```
Expand All @@ -539,21 +539,41 @@ ComputedPropertyPrototype.teardown = function(obj, keyName) {
@method computed
@for Ember
@param {String} [dependentKeys*] Optional dependent keys that trigger this computed property.
@param {Function} func The computed property function.
@param {Function} opts The computed property function.
@return {Ember.ComputedProperty} property descriptor instance
*/
function computed(func) {
var args;
function computed(opts) {
var args, func;

if (arguments.length > 1) {
args = a_slice.call(arguments);
func = args.pop();
opts = args.pop();
}

if (Ember.FEATURES.isEnabled('improved-cp-syntax')){
if (typeof opts === "object"){
if (opts.set){
func = function(keyName, value, oldValue){
if (arguments.length > 1){
return opts.set.call(this, keyName, value, oldValue);
} else {
return opts.get.call(this, keyName);
}
};
} else {
func = opts.get;
}
} else if (typeof opts === "function"){
func = opts;
Ember.deprecate("Using the same function as getter and setter is deprecated. Pass an object containing `get` and `set` properties instead", func.length < 2);
}
}

func = func || opts;

if (typeof func !== "function") {
throw new EmberError("Computed Property declared without a property function");
}

var cp = new ComputedProperty(func);

if (args) {
Expand Down
60 changes: 60 additions & 0 deletions packages/ember-metal/tests/computed_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,66 @@ testBoth('chained dependent keys should evaluate computed properties lazily', fu
});


// ..........................................................
// FEATURE 'improved-cp-syntax'
//

if (Ember.FEATURES.isEnabled('ember-metal-injected-properties')){
QUnit.module('computed - improved cp syntax');

test('setter and getters are passed using an object', function() {
var testObj = Ember.Object.extend({
a: '1',
b: '2',
aInt: computed('a', {
get: function(keyName){
equal(keyName, 'aInt', 'getter receives the keyName');
return parseInt(this.get('a'));
},
set: function(keyName, value, oldValue){
equal(keyName, 'aInt', 'setter receives the keyName');
equal(value, 123, 'setter receives the new value');
equal(oldValue, 1, 'setter receives the old value');
this.set('a', ""+value); // side effect
return parseInt(this.get('a'));
}
})
}).create();

ok(testObj.get('aInt') === 1, 'getter works');
testObj.set('aInt', 123);
ok(testObj.get('a') === '123', 'setter works');
ok(testObj.get('aInt') === 123, 'cp has been updated too');
});

test('setter can be omited', function() {
var testObj = Ember.Object.extend({
a: '1',
b: '2',
aInt: computed('a', {
get: function(keyName){
equal(keyName, 'aInt', 'getter receives the keyName');
return parseInt(this.get('a'));
}
})
}).create();

ok(testObj.get('aInt') === 1, 'getter works');
ok(testObj.get('a') === '1');
testObj.set('aInt', '123');
ok(testObj.get('aInt') === '123', 'cp has been updated too');
});

test('Passing a function that acts both as getter and setter is deprecated', function() {
var regex = /Using the same function as getter and setter is deprecated/;
expectDeprecation(function(){
Ember.Object.extend({
aInt: computed('a', function(keyName, value, oldValue){})
});
}, regex);
});
}

// ..........................................................
// BUGS
//
Expand Down