carrot / roots-records

Parse JSON conveniently as roots locals to be used with any template engine.
Other
24 stars 10 forks source link

Generate list of records from object #24

Closed smth closed 9 years ago

smth commented 9 years ago

I don't know how much this is a Records question and how much it's a Coffeescript one (I'm new to both), but is something like this possible?

hash = 
  somelabel: '12345'
  anotherlabel: '67890'

module.exports =
  extensions: [
    records(
        for key, value of hash
            #{key}: { url: api_root + #{value} + api_key },
    )
  ]

(assuming that api_root and api_key are defined somewhere)

The desire here is mainly to avoid having to duplicate the api_root and api_key stuff, but also potentially have that hash generated from another API.

jescalan commented 9 years ago

Nope, unfortunately that will not work, although it would be pretty sweet if it did. The reason is because for loops used as comprehensions in coffeescript return arrays, not objects, and interpolated object keys aren't valid syntax. There's no way to do this smoothly in coffeescript proper, you'd have to just run a function above that does this transform, then pass that result into roots records. However, you can use lodash.reduce to do it pretty smoothly like you want to do here. This code is as slim as you'll get it:

hash =
  somelabel: '12345'
  anotherlabel: '67890'

module.exports =
  extensions: [
    records(_.reduce(hash, (m, k, v) -> m[k] = { url: api_root + v + api_key }; m, {}))
  ]

This is some pretty nasty compressed code, so let me break it down in a little more understandable of a fashion. First requirement is having a good understanding of how reduce works, which can be tricky. Reduce takes three arguments here, an object or array, a function used to transform values, and what's referred to as a "memo" -- a value that is passed through each transform function. The transform function takes thee args as well, the memo value, and they key and value of the object you are iterating (if you were to pass an array it would just be two values, the memo and array value).

So what we do here is start with an empty object as the memo value, and in each transform add the key and value from the hash as required by roots records' config to the memo object. We then return the memo from the transform function, which is essential to ensure we are passing on the modified version. So each pass we make, we are adding another config value, and in the end the memo is returned complete with all the values we want.

Hope this helps! I'm going to close this issue as it's not a problem with roots records, but happy to continue discussion here of course if there's anything I can clarify.

smth commented 9 years ago

Thanks for the detailed reply @jenius this is something I might return to, for now it's just a 'nice to have'.

I love the concept of this plugin by the way, it's what lead me to Roots.

jescalan commented 9 years ago

Awesome! Glad you are liking it, and of course let me know if you have any other questions :grinning: