Skip to content

Instantly share code, notes, and snippets.

@naartjie
Last active July 8, 2022 21:20
Show Gist options
  • Select an option

  • Save naartjie/9005e81811c4df6a595b to your computer and use it in GitHub Desktop.

Select an option

Save naartjie/9005e81811c4df6a595b to your computer and use it in GitHub Desktop.
Moonscript Object accessors extension
getters = (cls, getters) ->
cls.__base.__index = (key) =>
if getter = getters[key]
getter @
else
cls.__base[key]
setters = (cls, setters) ->
cls.__base.__newindex = (key, val) =>
if setter = setters[key]
setter @, val
else
rawset @, key, val
{ :getters, :setters }
{ :getters, :setters } = require('object_ext')
describe 'object accessors', ->
object1, object2, spy, spies = nil
class MyObject
getters @,
field1: =>
spy 'get', key
@_field1
setters @,
field1: (val) =>
spy 'set', 'field1', val
@_field1 = val
before_each ->
object1 = MyObject!
object2 = MyObject!
spies = {}
spy = (fun, key, val) ->
table.insert(spies, {:fun, :key, :val})
it 'should set and get simple properties', ->
assert.Same #spies, 0
assert.Nil object1.field1
assert.Same #spies, 1
assert.Same spies[1], {fun: 'get'}
object1.field1 = 'two'
assert.Same #spies, 2
assert.Same spies[2], {fun: 'set', key: 'field1', val: 'two'}
it 'should keep properties separate for separate objects', ->
assert.Same #spies, 0
assert.Nil object1.field1
assert.Nil object2.field1
assert.Same 2, #spies
assert.Same 'get', spies[1].fun
assert.Same 'get', spies[2].fun
object1.field1 = 'boo'
assert.Same 3, #spies
assert.Same 'set', spies[3].fun
assert.Nil object2.field1
assert.Same 4, #spies
assert.Same 'get', spies[4].fun
assert.Same 'boo', object1.field1
assert.Same 5, #spies
assert.Same 'get', spies[5].fun
it 'should still allow vanilla properties without accessors', ->
assert.Same 0, #spies
object1.field1 = 'object1.field1'
object2.field1 = 'object2.field1'
object1.some_vanilla_prop = 'object1.some_vanilla_prop'
object2.some_vanilla_prop = 'object2.some_vanilla_prop'
assert.Same 2, #spies
assert.Same 'set', spies[1].fun
assert.Same 'set', spies[2].fun
assert.Same 'object1.some_vanilla_prop', object1.some_vanilla_prop
assert.Same 'object2.some_vanilla_prop', object2.some_vanilla_prop
assert.Same 2, #spies
assert.Same 'object1.field1', object1.field1
assert.Same 'object2.field1', object2.field1
it 'should have the same metatable', ->
assert.equal getmetatable(object1), getmetatable(object2)
it 'should allow for 2 or more setters', ->
ops = {}
class MyObj
getters @,
field1: =>
ops[#ops+1] = 'get:field1'
@_field1
field2: =>
ops[#ops+1] = 'get:field2'
@_field2
setters @,
field1: (val) =>
ops[#ops+1] = 'set:field1'
@_field1 = val
field2: (val) =>
ops[#ops+1] = 'set:field2'
@_field2 = val
obj1 = MyObj!
obj2 = MyObj!
obj1.field1 = 'obj1.field1'
obj1.field2 = 'obj1.field2'
obj2.field1 = 'obj2.field1'
obj2.field2 = 'obj2.field2'
assert.Same ops, {
'set:field1', 'set:field2', 'set:field1', 'set:field2'
}
ops = {}
assert.Same 'obj1.field1', obj1.field1
assert.Same 'obj1.field2', obj1.field2
assert.Same 'obj2.field1', obj2.field1
assert.Same 'obj2.field2', obj2.field2
assert.Same ops, {
'get:field1', 'get:field2', 'get:field1', 'get:field2'
}
@naartjie
Copy link
Author

An extension which allows you to use getters and setters with your Moonscript objects.

Caveat: it does not use getters and setters from the super class, only base class is supported for now. Please see here for a discussion.

@SleebyRhea
Copy link

SleebyRhea commented Jun 7, 2022

Is the source in this gist free-use? I imagine, considering the age, that you don't much care but I figured I'd ask just in case as I've been toying around with moonscript and have found it useful to build off of.

@naartjie
Copy link
Author

naartjie commented Jul 8, 2022

@SleepyFugu yeah ditto (the age part).

This is forked from https://gist.github.com/kress95/13bc1001f817a42590fa.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment