The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
The case for Ext.applyOnly

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Edward Spencer

Posts: 148
Nickname: edspencer
Registered: Aug, 2008

Edward Spencer is a Ruby/Rails developer and the creator of the ExtJS MVC framework
The case for Ext.applyOnly Posted: Apr 23, 2009 5:45 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Edward Spencer.
Original Post: The case for Ext.applyOnly
Feed Title: Ed's Elite blog
Feed URL: http://feeds2.feedburner.com/EdSpencer
Feed Description: Ruby on Rails development, Git issues and ExtJS/JavaScript
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Edward Spencer
Latest Posts From Ed's Elite blog

Advertisement
We should have something like this:

Ext.applyOnly(this, config, ['width', 'height']);

You could use this every time you write a method or class that requires a config Object as one of it's parameters. These methods ought to only apply those properties of the config object they actually need, but usually this will just be done with an Ext.apply(this, config). This means anything in your object could be overwritten by this config object. Sometimes that's a good thing, but sometimes it's definitely not.

Ext.applyOnly() applies only a whitelist of the properties in the config object. These are specified by an optional third argument, which is an array of property names. Here's how you might write applyOnly:


/**
* Applies only a pre-specified set of properties from one object to another
* @param {Object} receiver The object to copy the properties to
* @param {Object} sender The object to copy the properties from
* @param {Array} whitelist The whitelist of properties to copy (e.g. ['width', 'height'])
* @return {Object} The receiver object, with any of the whitelisted properties overwritten if they exist in sender
*/
Ext.applyOnly = function(receiver, sender, whitelist) {
if (receiver && sender) {
Ext.each(whitelist || [], function(item) {
if (typeof sender[item] != 'undefined') receiver[item] = sender[item];
}, this);
};

return receiver;
};

While you can't stop code maliciously overwriting properties this way, it would stop people from unknowingly overwriting your object's properties. They could overwrite them manually, but they'll do this knowing that this wasn't an intended use for the class. Let's have a look at an extension that would do a great job opening popups telling people they've won lots of money:


/**
* Pops up windows telling lucky visitor she's won big money!!!!
*/
Ext.ux.WinnerEarnings = Ext.extend(Ext.util.Observable, {
/**
* @property accessibleProperties
* @type Array
* All properties intended to be mass-updatable
*/
accessibleProperties: ['height', 'width'],

/**
* Message to show lucky winners!! You can't change this!!!!!
*/
message: "You're the 1000000000000th visitor!!!!!!!1 Click here to claim money. Now!!!",

constructor: function(config) {
//apply only the fields that are deemed writable
Ext.applyOnly(this, config, this.accessibleProperties);

Ext.ux.WinnerEarnings.superclass.constructor.apply(this, arguments);

Ext.applyIf(this, {
version: 2.9,
coolFeature: Ext.util.TaskRunner({
interval: 1000,
scope: this,
run: function() {
//version, coolFeature, updateDetails, closable and close won't be sent to Ext.Window
new Ext.Window(Ext.applyOnly({}, this, ['height', 'weight', 'message'])).show();
}
}).start()
}
},

/**
* Updates this WinnerEarnings opportunity with options from the supplied object
* @param {Object} updates An object containing updates to make to this precious opportunity
* @return {Ext.ux.WinnerEarnings} The WinnerEarnings object
*/
updateDetails: function(updates) {
return Ext.applyOnly(this, updates, this.accessibleProperties)
},

//secret tricks to let the user stop the popups
closable: false,
close: function() {
this.coolFeature.stop();
}
})

How it works:


var myObj = new Ext.ux.WinnerEarnings({height: 200, width: 150});

myObj.updateDetails({width: 300, message: "My Message"})
myObj.width: // => 300
myObj.message; // => "You're the 1000000000000th visitor!!!!!!!1 Click here to claim money. Now!!!"

//updating message didn't work, but we can still do it manually
myObj.message = "My message";
myObj.message; // => "My message"

In my example class I've added the whitelist as an accessibleProperties property on the class, which makes it easy for others to see what they should and should not be updating.

In this example we're also sanitizing output with applyOnly. WinnerEarnings lightly wraps around a series of Ext.Windows and we'd like to be able to pass our WinnerEarnings object as config. We want to make sure we're not passing our 'closable' property, 'close()' function and others to the Ext.Window constructor, so we pass that in via a whitelist too, inside the run() function in our constructor.

Check out the unit tests
for the function to see a couple more use cases. Here's one final example - sanitizing output from a function:


myFunction = function(input) {
//do some stuff to make input useful

//guarantee our returned object only has relevant properties
return Ext.applyOnly({}, input, ['important-thing-1', 'important-thing-2']);
}

Read: The case for Ext.applyOnly

Topic: Truly Open Source Previous Topic   Next Topic Topic: I'll be speaking at RailsConf

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use