jacopo beschi: yet another web guy

Coffeescript Model class with attr_accessor rails alike

Created at: Feb/21/2015 jacopo beschi

Nowadays I've been toying around with the fabolous coffeescript language and I've created a basic model class.
This class allow you to use attr_accessor method as you can do in Ruby. If you don't know what attr_accessor is you can take a look here: Ruby attr_accessor.
Briefly what attr_accessor does is to let you access object attributes in "object.attribute" form (which in javascript is built in) but more importantly let you add a constrain on read/write permission of that attribute! In fact if you want the attribute to be readonly you need to use the "attr_reader" method, in the opposite case you need to use the "attr_writer" method. If you don't want to add any constraint you can use the "attr_accessor".

Here is the code of the model:

# this creates a root namespace that works with browser or node.js
root = exports ? this
#uppercase the first letter 
root.namespace.ucFirst = (field) ->
    field.charAt(0).toUpperCase() + string.slice(1);

root.namespace.Model = class Model
  get: (field) ->
    # call getter if exists
    getter = "get#{root.namespace.ucFirst(field)}"
    return this[getter]() if (typeof this[getter] == "function")

  set: (field, value) ->
    # call setter if exists
    setter = "set#{root.namespace.ucFirst(field)}"
    return this[setter](value) if (typeof this[setter] == "function")

  defineAttribute: (field, type) ->
    @attributes ||= {}
    prop = {}
    prop[field] = {}
    prop[field].get = () -> @get(field, originalGetter) unless type == "writer"
    prop[field].set = (value) -> @set(field, value) unless type == "reader"
    Object.defineProperties(@ , prop)

  attr_accessor: (field) ->
    @defineAttribute(field, "all")

  attr_reader: (field) ->
    @defineAttribute(field, "reader")

  attr_writer: (field) ->
    @defineAttribute(field, "writer")

What this code does is to create the methods: "attr_writer, attr_reader, attr_accessor". In order to use this model you need to inherit from him in your class with "extends root.namespace.Model". Here is an example of usage:

class Test extends root.namespace.Model
    constructor: () ->
        @attr_reader "readonly"
        @attr_writer "writeonly"
        @attr_accessor "accessor"

    getTest: ->

test = new Test
# write the attribute but cannot read from him
test.writeonly = "write"
# can read from outside but cannot write    
console.log test.readonly   
# can read and write data
test.accessor = "writable and readable"
console.log test.accessor
#if you have a get"AttributeName" method or set"AttributeName" method it gets called instead of fetching the attribute
console.log test.test   # writes "test"

That's all forks. If you have any question or comment feel free to use the disquis form below. Enjoy.

comments powered by Disqus