dchester / epilogue

Create flexible REST endpoints and controllers from Sequelize models in your Express app
846 stars 116 forks source link

"undefined is not a function" - on create controller #132

Closed richmarr closed 8 years ago

richmarr commented 8 years ago

Hi,

Thanks for sharing epilogue; it's really handy. Hit a confusing situation and thought someone might know where I'm going wrong. Having set up a few endpoints and started to consume them, I'm getting an error when I use create:

TypeError: undefined is not a function
    at Object.module.exports.mapOptionFieldNames (/Users/rich/Projects/bit-jobs/node_modules/sequelize/lib/utils.js:82:47)
    at null.<anonymous> (/Users/rich/Projects/bit-jobs/node_modules/sequelize/lib/model.js:1313:11)
    at tryCatcher (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/util.js:24:31)
    at Promise._settlePromiseFromHandler (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/promise.js:489:31)
    at Promise._settlePromiseAt (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/promise.js:565:18)
    at Async._drainQueue (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/async.js:128:12)
    at Async._drainQueues (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/async.js:133:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/rich/Projects/bit-jobs/node_modules/bluebird/js/main/async.js:15:14)
    at processImmediate [as _immediateCallback] (timers.js:358:17)

As far as I can see, sequelize's Utils.mapOptionFieldNames is expecting options.attributes to be an array, but epilogue's Create.prototype.write is setting options.attributes to { exclude: self.resource.excludeAttributes }.

The excludeAttributes condition is being triggered by if (!!self.resource.excludeAttributes) evaluating true, even though self.resource.excludeAttributes in my case is an empty array which makes me feel like I've got an API version conflict somewhere.

I assume I'm doing something daft, but have been staring at it and must be missing something. I'm on epilogue@0.6.5 and sequelize@3.5.1. Anyone got any ideas?

mbroadst commented 8 years ago

@richmarr I just ran the full test suite with sequelize@3.19.2, epilogue@0.6.5, and everything ran just fine. Could you possibly provide some of your code, maybe we can identify something wrong there. As far as the excludeAttributes, that seems to be working just fine.

richmarr commented 8 years ago

Thanks @mbroadst. It's an existing app & data model. Unpicking everything into a test case is do-able but time-consuming, so I'm keen to try understanding the code before resorting to that.

mbroadst commented 8 years ago

@richmarr if you see sequelize's instance docs, you'll note that reload supports all the options of Model.find. That's where the exclude is being added (and it appears perhaps as double duty, since below it iterates through the excludes and deletes properties again).

It's true that the check itself for excludes is incomplete, it appears that using the !! to check was at a time where we were checking if it was specified at all. A more complete check would be something like !!excludeAttributes && Array.isArray(excludeAttributes) && excludeAttributes.length > 0. That might help you out.

It also occurs to me that you may be using a version of sequelize that simply does not support adding exclude to the reload method, in which case you would just need to update sequelize and this will work. Another way to get around this is to specify reloadInstances: false in your resource definition, this will bypass this code completely.

Unfortunately this is a one-man operation over here, and I don't even use this module anymore, so supporting multiple versions of sequelize is out of the question, unless you'd like to contribute the work (and tests).

richmarr commented 8 years ago

@mbroadst no worries, totally understand, and thanks for the tips. Much appreciated. I'll follow up once I've tried some things.

richmarr commented 8 years ago

@mbroadst I upgraded Sequelize from sequelize@3.5.1 to sequelize@3.19.2 and that did the trick.

Just to note; I originally upgraded from sequelize@3.2.0to sequelize@3.5.1 because 3.5.1 was the one listed in epilogue's devDependencies. Might be worth figuring out which is the lowest sequelize version and listing it as a peer dependency. I'd have to check that, not used it before.

If I get time I'll put a pull request together... and thanks for your help, much appreciated!