codeactual / grunt-horde

Packageable, composable grunt configuration modules
http://codeactual.github.io/06/02/2013/introducing-grunt-horde.html
MIT License
4 stars 1 forks source link

Unable to learn a registerTask property #6

Open cameroncan opened 9 years ago

cameroncan commented 9 years ago

Something like the following always returns undefined:

var defaultTask = horde.learn('registerTask.default');

I looked inside of the function: GruntHorde.prototype.learn(key) and added logging. The "this.config" object always has empty properties:

inside learn, config with key: registerTask.default { initConfig: {}, loadNpmTasks: {}, loadTasks: {}, registerMultiTask: {}, registerTask: {} }

Is this a known issue? It looks as though only properties in initConfig will be accurately learned, however in the comments it gives an example with 'registerTask.default'.

I am using version 0.3.5

codeactual commented 9 years ago

I'm not aware of that issue but I'd like to reproduce it.

What are the preceding horde.* function calls?

cameroncan commented 9 years ago

Here is an excerpt from my Gruntfile.js.

module.exports = function(grunt) {
    ...
    //Bring in the shared grunt configuration
    var horde = require('grunt-horde').create(grunt);
    horde.loot('shared-grunt-config');

    //jshint
    horde.demand('initConfig.pkg', grunt.file.readJSON('package.json'));
    horde.demand('initConfig.jshint.options.camelcase', false);
    horde.demand('initConfig.jshint.options.globals._angularAppManager', false);

    //tasks
    var defaultTask = horde.learn('registerTask.default');
    ...
    horde.attack();
};

Moving the learn call around doesn't change the result. Perhaps I'm missing something more major? I can learn the initConfig properties just fine. Inside the learn function it uses "grunt.config.getRaw()", whereas when a non-initConfig property is used, the learn function uses "this.config"

codeactual commented 9 years ago

Thanks. I think this might be it:

To be honest I don't recall why so much is delayed until attack. My best guess is that I assumed there would be a mostly one-way data relationship: Gruntfile.js would mostly demand values while loot-ed modules would learn them, not the reverse. But it sounds like it may be more useful for your use case if registerTask is read earlier like in create, or through a separate method, etc? Let me know your thoughts -- whether or not it will help with how you're consuming defaultTask.

Also, you're right about how getRaw and this.config are both used. I'm looking into an issue I noticed related to those and hopefully can find a way to simplify.

cameroncan commented 9 years ago

Thanks for the response. I see now that I can learn the registerTask properties after the attack. In my case I'm hoping to add a task to a previously existing task list (not sure I have the nomenclature right). It would be helpful to have registerTask be read in earlier like you suggest, before the attack call. That way I can modify the task list.

Here's an example of the reverse case (after the attack) where I can learn, but not demand.

    horde.attack();
    var defaultTask = horde.learn('registerTask.default');
    console.log('******************');
    console.log(defaultTask);
    horde.demand('registerTask.test', defaultTask.concat(['another:task']));
codeactual commented 9 years ago

I'm thinking about a new peek method but not exactly sure how it would work.

Any property like registerTask.default might be defined in multiple loot-ed modules, so peek either needs a 2nd arg to disambiguate or it would need perform a merge itself and only inspect the result. But then loot could get called again prior to attack, so peek might see a value that isn't "final".

One alternative/workaround for your use-case might be an approach I've been using:

https://github.com/codeactual/sinon-doublist-fs/blob/master/Gruntfile.js https://github.com/codeactual/sinon-doublist-fs/blob/master/config/grunt/registerTask.js

That project inherits defaults via the 1st loot and then customizes via the 2nd. Calling learn from the 2nd registerTask module should work because it will happen in the middle of attack as long as loot('shared-grunt-config') was called first. It's not great -- more basically empty files -- but it may work for your purposes.

cameroncan commented 9 years ago

After reading your different suggestions I couldn't help but think I was not quite using grunt-horde correctly. I took a new approach to it and I have it working now. Previously I was trying to do all my config overrides with the horde api. However, I now have a separate registerTask.js config file in my project which I loot as well as the shared grunt config. This enabled me to read and set config how I needed to.

As for this functionality, I think it sounds great to make it flexible in this way, to allow the user to make all sorts of config changes through the horde-api, however, I'm not sure that it is necessary. So this in my eyes is now more of an enhancement rather than a bug.