Brendan Long
Brendan Long

Reputation: 54242

Validating arguments in CoffeeScript?

I have a function with a bunch of arguments, and I just want to check if any of them are falsy (empty, undefined, null, etc.).

One option is obvious to just check every argument individually, but it's pretty repetitive:

if not arg1
  response.send 400, 'Missing argument arg1'
if not arg2
  response.send 400, 'Missing argument arg2'

I can simplify that a bit with this, but I still have to list out every every argument and argument name:

for key, value of { 'arg1': arg1, 'arg2': arg2 }
  if not value
    response.send 400, "Missing argument #{key}"

I was hoping to do something like this:

for key, value of arguments
  if not value
    response.send 400, "Missing argument #{key}"

But arguments is more like an array. Is there a way to get the arguments as an object, or get the argument names as an array? Am I going about this this wrong way?

What is a good way of validating a bunch of arguments without repeating myself?

Upvotes: 0

Views: 341

Answers (2)

mutil
mutil

Reputation: 3305

I believe there is no clear way of achieving what you want, but a nasty way of doing this (based on similar threads for javascript, like this and this), which may be error prone, is to parse the function itself, get the names of the arguments and make them an array:

fn = (a,b,c,d,e,f) ->
  fns = fn.toString()
  args = fns.slice(fns.indexOf('(')+1, fns.indexOf(')')).split(', ')
  for idx in [0...args.length]
    console.log 400, "Missing argument #{args[idx]}" unless arguments[idx]

fn('', null, 'arg1', undefined, 'arg2')

#Output:
#400 'Missing argument a'
#400 'Missing argument b'
#400 'Missing argument d'
#400 'Missing argument f'

Upvotes: 1

robkuz
robkuz

Reputation: 9934

You could write an check function that parses the parameter names from the string representation of your function (there is really no other way)

check = ()->
    f = "" + arguments.callee.caller
    r = /function \((.*)\)/
    regres = r.exec(f)
    pnames = regres[1].split(",")
    params = (pn.trim() for pn in pnames)
    for index in [0...arguments.length]
        if arguments[index] == null || arguments[index] == undefined
            console.log "argument: #{params[index]} is null"

handleRequest = (x, y, z)->
    #give all your params in the correct order to the check function
    check(x, y, z)

handleRequest(1, 2, "lala")
handleRequest(1, 2)

Now the fact that this is somehow possible shouldn't mean that you should do it. This solution is at best brittle and will create confusion if you change parameter position. Some would probably claim its evil - me included ;-)

I'd rather advise you that you change your API design.

From your response.send I would assume that you are in an web environment? Why dont you simply use the params hash that the framework you are using is handling to you? Most frameworks will do exactly this.

Another possibility would be to define default values for your parameter so that received parameters are always well defined?

handleRequest = (x, y = "somevalue", z = "anothervalue")->

Upvotes: 2

Related Questions