3

I'm pretty new to the world of JavaScript and even newer to CoffeeScript. I have a problem and I'm not sure if it's even possible.

Say I have a CoffeeScript class like this

class @Model
  constructor: (@name) ->

how could I pass the names of models to be created to a function to instantiate these objects whilst appending the name of the variable [in this case] with _model? Something like:

makeModel = (name) ->
  "#{name}_model" = new Model(name)

My rails app tells me that:

unexpected =
      "#{name}_model" = new Model(
                ^

I'm assuming that this is because of the string. Is there some sort of method to convert a string to a variable name? I took a quick look at the .eval() method but the little book of CoffeeScript warns against it's use.

Thanks

6
  • 2
    instead of a named variable, use an array or object to collect instances... Commented Apr 8, 2014 at 16:24
  • That did not occur to me. As a last resort this would be possible but as these elements are all stored in a database it would be far more convenient being able to interact with them by name than by maintaining an array Commented Apr 8, 2014 at 16:28
  • how is all.fred_model any eaiser to use than window.fred_model or even just fred_model? plus, if they are in an object, you8 can iterate all instances, which is messy with variables. i would also consider attaching them to the constructor itself as a static object property. Commented Apr 8, 2014 at 16:29
  • Again, new to JS and CS, would you mind expanding with some sort of code examples? the point is that I probably wouldn't need to iterate through all models but I would likely need to directly target say current_model = fred_model Sorry, complete noob here! Commented Apr 8, 2014 at 16:40
  • i don't know how it would look in CoffeeScript, but thanks to leaky assignments, you can just prepend an additional assignment after "var xxx=" in normal JS. something like "var xxx= self[name]= ... " Commented Apr 8, 2014 at 16:43

1 Answer 1

2

You could do something like this:

ModelFactory = do -> 
  class @Model
    constructor: (@name) ->

  models = {}

  makeModel = (name) ->
    model = new Model(name)
    models["#{name}Model"] = model
    model

  getModel = (name) ->
    models["#{name}Model"] or makeModel(name)

  { getModel }

Secret Magic:

do -> - The do keyword creates an IIFE, a function that is called as soon as it is created. It can be used for creating modules like the following:

var myModule = (function () {
    var privateFunc = function () {};
    var publicFunc = function () { privateFunc(); };
    return {
        publicFunc: publicFunc
    }
})();

accessing properties with strings - In JavaScript, you can access a property of an object as a string, by using the square-bracket ([]) notation, plus a string, or a variable containing a string. Here we are combining this with the CoffeeScript string interpolation sugar ("#{}") to dynamically create property names and assign them.

var object = {
    prop: 'value',
    otherProp: 'otherValue'
};

var propertyName = 'prop';
var value = object[propertyName]; // 'value';

var something = 'Something'
object['my' + something] = 'a new property';
object.mySomething === 'a new property'; // true
Sign up to request clarification or add additional context in comments.

2 Comments

This looks like a very good solution, thanks. two little things though , I really don't like using solutions without knowing what the code is doing. I don't suppose you know where I could read up on the ModelFactory = do -> business and this whole using strings as indices in arrays (models["#{name}Model"])
Thanks, this is great! Nothing like being schooled before breakfast

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.