Skip to content

Commit

Permalink
- added 'slot' attribute to Joose.Managed.Property.Attribute
Browse files Browse the repository at this point in the history
this should allow to have the accessor with the same name as attribute
  • Loading branch information
canonic-epicure committed Feb 19, 2010
1 parent 116d61e commit af8cd12
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 90 deletions.
70 changes: 56 additions & 14 deletions lib/Joose/Managed/Attribute.js
Expand Up @@ -5,7 +5,7 @@ Joose.Managed.Attribute = new Joose.Managed.Class('Joose.Managed.Attribute', {
have : {
is : null,

isPrivate : null,
isPrivate : false,

role : null,

Expand All @@ -17,21 +17,24 @@ Joose.Managed.Attribute = new Joose.Managed.Class('Joose.Managed.Attribute', {
},


override : {

computeValue : function () {
if (typeof this.init != 'function') this.SUPER()

var isPrivate = /^_/.test(this.name)

after : {
initialize : function () {
this.publicName = this.name.replace(/^_+/, '')

this.isPrivate = this.isPrivate || isPrivate
this.isPrivate = this.isPrivate || /^_/.test(this.name)

if (this.isPrivate && !isPrivate) this.name = '__' + this.name
this.slot = this.isPrivate ? '_$' + this.name : this.name

this.setterName = this.setterName || this.getSetterName()
this.getterName = this.getterName || this.getGetterName()
}
},


override : {

computeValue : function () {
if (typeof this.init != 'function') this.SUPER()
},


Expand Down Expand Up @@ -84,6 +87,45 @@ Joose.Managed.Attribute = new Joose.Managed.Class('Joose.Managed.Attribute', {
targetMeta.extend({
removeMethods : removeMethods
})
},


getValueFrom : function (instance) {
var getterName = this.getterName

if (/^r/i.test(this.is) && instance.meta.hasMethod(getterName)) return instance[getterName]()

return instance[this.slot]
},


setValueTo : function (instance, value) {
var setterName = this.setterName

if (/^rw/i.test(this.is) && instance.meta.hasMethod(setterName)) instance[setterName](value)

instance[this.slot] = value
},


initFromConfig : function (instance, config) {
var name = this.name

var value, isSet = false

if (config.hasOwnProperty(name)) {
value = config[name]
isSet = true
} else
if (typeof this.init == 'function') {
value = this.init.call(instance, name, config)
isSet = true
}

if (isSet)
this.setValueTo(instance, value)
else
if (this.required) throw "Required attribute [" + name + "] is missed during initialization of " + instance
}

},
Expand All @@ -92,20 +134,20 @@ Joose.Managed.Attribute = new Joose.Managed.Class('Joose.Managed.Attribute', {
methods : {

getSetter : function () {
var name = this.name
var slot = this.slot

return function (value) {
this[name] = value
this[slot] = value
return this
}
},


getGetter : function () {
var name = this.name
var slot = this.slot

return function () {
return this[name]
return this[slot]
}

}
Expand Down
21 changes: 19 additions & 2 deletions lib/Joose/Managed/Property/Attribute.js
Expand Up @@ -2,13 +2,30 @@ Joose.Managed.Property.Attribute = new Joose.Proto.Class('Joose.Managed.Property

isa : Joose.Managed.Property,

slot : null,


initialize : function () {
Joose.Managed.Property.Attribute.superClass.initialize.apply(this, arguments)

this.slot = this.name
},


apply : function (target) {
Joose.Managed.Property.Attribute.superClass.apply.call(this, target.prototype)
target.prototype[this.slot] = this.value
},


isAppliedTo : function (target) {
return target.prototype[this.slot] == this.value
},


unapply : function (from) {
Joose.Managed.Property.Attribute.superClass.unapply.call(this, from.prototype)
if (!this.isAppliedTo(from)) throw "Unapply of property [" + this.name + "] from [" + from + "] failed"

delete from.prototype[this.slot]
}

}).c
15 changes: 9 additions & 6 deletions lib/Joose/Manual/Attributes.js
Expand Up @@ -24,22 +24,22 @@ In this document we'll cover only the base capabilities of attributes, which are
BASIC ATTRIBUTE - `have` builder
=======================
================================
The simplest attribute in Joose can be constructed with *have* builder:
Class('Person', {
have : {
firstName : 'JohnDoe'
firstName : 'John'
}
})
This says that all Person objects have an "first_name" attribute, which has a default value 'JohnDoe'. Default value will be installed directly to the class's prototype without any modifications.
This says that all Person objects have an "first_name" attribute, which has a default value 'John'. Default value will be installed directly to the class's prototype without any modifications.
Thats all, no other features. This type of attribute is used primarily in the Joose internals and low-level extensions.
ADVANCED ATTRIBUTE - `has` builder
==========================
==================================
The advanced attribute in Joose can be constructed with *has* builder:
Expand All @@ -63,7 +63,7 @@ Each attribute has one or more accessor methods. An accessors lets you read or w
By default, the read accessor method has the name 'getAttributeName', where the 'AttributeName' is the name of attribute with uppercased first letter.
Write accessor has the name 'setAttributeName'. If you declared your attribute as 'ro' then it will have only read accessor. If you declared it read-write, you get both read-write accessors. Simple.
Given our User example above, we now have a 'getUsername/setUsername' accessors that can read/write User object's username attribute's value:
Given our `User` example above, we now have a `getUsername/setUsername` accessors that can read/write User object's username attribute's value:
var user = new User()
Expand All @@ -75,7 +75,7 @@ Class can provide custom implementation of the accessor methods, they will not b
Default value
----------------------------------
-------------
To specify the default value for the attribute use `init` property. In the example above attribute `username` will be initialized with default value 'root'.
Expand All @@ -90,6 +90,9 @@ To specify the default value for the attribute use `init` property. In the examp
If you'll provide a function as the value for `init`, it will be called during initialization with the following signature:
`func(attributeName, config)`, where `config` is the 1st argument passed to constructor. Function will be called as class's method (in the instance's scope).
Value, returned from function, will be used for initialization. **Note**, that if the attribute is `rw` it will be passed further to the setter method, and not applied directly to instance.
Any other values, provided as `init` value, will be applied to prototype of the class directly.
Simplified form. Attribute helpers
Expand Down
30 changes: 4 additions & 26 deletions lib/Joose/Meta/Object.js
Expand Up @@ -9,32 +9,10 @@ Joose.Meta.Object = new Joose.Proto.Class('Joose.Meta.Object', {

Joose.O.each(this.meta.attributes, function (attribute, name) {

var haveInitValue = config.hasOwnProperty(name)

if (attribute instanceof Joose.Managed.Attribute) {
var setValue, isSet = false

if (haveInitValue) {
setValue = config[name]
isSet = true
} else
if (typeof attribute.init == 'function') {
setValue = attribute.init.call(this, name, config)
isSet = true
}


if (isSet)
if (this.meta.hasMethod(attribute.setterName))
this[attribute.setterName](setValue)
else
this[name] = setValue
else
if (attribute.required) throw "Required attribute [" + name + "] is missed during initialization of " + this

} else
if (haveInitValue) this[name] = config[name]

if (attribute instanceof Joose.Managed.Attribute)
attribute.initFromConfig(this, config)
else
if (config.hasOwnProperty(name)) this[name] = config[name]

}, this)
}
Expand Down

0 comments on commit af8cd12

Please sign in to comment.