keithwhor / nodal

API Services Made Easy With Node.js

Home Page:http://www.nodaljs.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nodal Server Crashes if Joined Table Field Name Matches Model Name

nsipplswezey opened this issue · comments

commented

TL;DR
If your model is called Tweet, and your endpoint is called tweets and one of your model fields is called tweets and you join Tweet to another model, like User, Nodal will crash on any requests to your tweet endpoint.

Simplest solution is to tell users not to do this.
Simple solution 1 is to validate field names in nodal g:model name1:type name2:type against endpoints and model names.
Simple solution 2 is to add feedback to the error handling block in __setJoined__ which handles this error:

nodal/core/required/model.js:706:17

Simple solution 3 is to figure out why this naming/reference conflict between model field names and API endpoints happens exactly, and address that. My intuition suggests that it has something to do with how URLs are parsed, or how the parsed output is consumed. But honestly that's just a guess.

Practical Use Case: I had a Todo model, with a json field named todos, which was used to store an array of client todo objects.
todos was a natural name for a field containing a json array of todos

To recreate:

nodal g:model Tweet user_id:int tweets:string
nodal g:model --user
nodal g:controller --for Tweet
nodal g:controller --for User

Go to your tweet model, import your User model and Tweet.joinsTo(User,{multiple:true})

Try POST to /tweets with something like user_id=1 and tweets=hello
Try GET to /tweets

Nodal server will throw the following error on a POST to /tweets/with user_id=1 and tweets=hello

{
  "meta": {
    "total": 0,
    "count": 0,
    "offset": 0,
    "error": {
      "message": "Internal Server Error",
      "details": [
        "Error: hello is not an instance of User",
        "    at Tweet.setJoined (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:706:17)",
        "    at Tweet.__safeSet__ (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:507:21)",
        "    at /Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:456:14",
        "    at Array.forEach (native)",
        "    at Tweet.__load__ (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:455:12)",
        "    at Tweet.Model (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:34:12)",
        "    at Tweet (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/app/models/tweet.js:8:3)",
        "    at Function.create (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:77:19)",
        "    at V1TweetsController.create (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/app/controllers/v1/tweets_controller.js:34:13)",
        "    at /Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/controller.js:59:63"
      ]
    }
  },
  "data": []
}  

And the following on a GET

{
  "meta": {
    "total": 0,
    "count": 0,
    "offset": 0,
    "error": {
      "message": "Internal Server Error",
      "details": [
        "Error: hello is not an instance of User",
        "    at Tweet.setJoined (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:706:17)",
        "    at Tweet.__safeSet__ (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:507:21)",
        "    at /Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:456:14",
        "    at Array.forEach (native)",
        "    at Tweet.__load__ (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:455:12)",
        "    at Tweet.Model (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/model.js:34:12)",
        "    at Tweet (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/app/models/tweet.js:8:3)",
        "    at /Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/composer.js:108:39",
        "    at Array.forEach (native)",
        "    at Composer.__parseModelsFromRows__ (/Users/nsipplsw/nodal-doc-release/nodal/examples/model-matches-field-name-bug/node_modules/nodal/core/required/composer.js:102:12)"
      ]
    }
  },
  "data": []
}

Going to close this right now. Just don't name field names the same as the model. It generally doesn't make sense to do, anyway.