2013-12-21 3 views
30

Я пишу свой первый генератор Yeoman, который запрашивает у пользователя различные входы и условно создает файлы на основе их ответов. Мне нужно иметь возможность вызвать подпрограмму (может быть подгенератором Yeoman) на основе ввода пользователя и передать ей аргументы.Yeoman: Call Sub-Generator с пользовательскими аргументами

Причина, по которой я хочу использовать именованные функции (которые не запускаются автоматически), заключается в том, что иногда ответ пользователя должен вызывать множество функций, а иногда функцию следует запускать в одиночку.

То, что я пробовал:

я понял суб-генераторы были путь, так как я создаю наборы файлов, только если пользователь запрашивает их. Но мне не удается называть их условно и передавать им пользовательский ввод. Я пробовал использовать hookFor, но я получаю ошибку утверждения: hookFor must be used within the constructor only. (Потому что я не хочу, чтобы он запускался по умолчанию, я вызываю подгенератор из моего this.prompt(prompts, function (props)).

Вопрос:

Как назвать рутинным, только если пользователь запрашивает его (через приглашение), и передать, что рутинное некоторые предоставленный пользователем информацию?

Если вы достаточно любезны ответить, пожалуйста, не предполагайте, что я пробовал что-то очевидное ;-).

ответ

32

Рассмотрим у вас есть генератор generator-blog (BlogGenerator) с двумя суб-генераторов (блог-сервера и блог-клиент):

app\index.js 
client\index.js 
server\index.js 

Так что, когда вы запускаете yo blog вы что спросить пользователя для некоторых вариантов и (необязательно) подгенераторы, правильно?

Для запуска подкаталога необходимо набрать this.invoke("generator_namespace", {options: {}}). Второй аргумент, который мы передали, может иметь поле options - это объект объектов, который будет передан генератору.

В App \ index.js:

BlogGenerator.prototype.askFor = function askFor() { 
    var cb = this.async(); 

    // have Yeoman greet the user. 
    console.log(this.yeoman); 

    var prompts = [{ 
    name: 'appName', 
    message: 'Enter your app name', 
    default: 'MyBlog' 
    }, { 
    type: 'confirm', 
    name: 'createServer', 
    message: 'Would you like to create server project?', 
    default: true 
    }, { 
    type: 'confirm', 
    name: 'createClient', 
    message: 'Whould you like to create client project?', 
    default: true 
    }]; 

    this.prompt(prompts, function (props) { 
    this.appName = props.appName; 
    this.createServer = props.createServer; 
    this.createClient = props.createClient; 

    cb(); 
    }.bind(this)); 
} 

BlogGenerator.prototype.main = function app() { 
    if (this.createClient) { 
    // Here: we'are calling the nested generator (via 'invoke' with options) 
    this.invoke("blog:client", {options: {nested: true, appName: this.appName}}); 
    } 
    if (this.createServer) { 
    this.invoke("blog:server", {options: {nested: true, appName: this.appName}}); 
    } 
}; 

В клиентском \ index.js:

var BlogGenerator = module.exports = function BlogGenerator(args, options, config) { 
    var that = this; 
    yeoman.Base.apply(this, arguments); 
    // in this.options we have the object passed to 'invoke' in app/index.js: 
    this.appName = that.options.appName; 
    this.nested = that.options.nested; 
}; 

BlogGenerator .prototype.askFor = function askFor() { 
    var cb = this.async(); 

    if (!this.options.nested) { 
    console.log(this.yeoman); 
    } 
} 

UPDATE 2015-12-21:
Использования invoke осуждается сейчас и должен заменить на composeWith. Но это не так просто, как могло бы быть. Основное различие между invoke и composeWith заключается в том, что теперь у вас нет возможности контролировать подгенераторы. Вы можете только объявить их использование.
Вот как main метод сверху должен выглядеть следующим образом:

BlogGenerator.prototype.main = function app() { 
    if (this.createClient) { 
    this.composeWith("blog:client", { 
     options: { 
      nested: true, 
      appName: this.appName 
     } 
     }, { 
     local: require.resolve("./../client") 
     }); 
    } 
    if (this.createServer) { 
    this.composeWith("blog:server", { 
     options: { 
      nested: true, 
      appName: this.appName 
     } 
     }, { 
     local: require.resolve("./../server") 
     }); 
    } 
}; 

Также я извлекал заменил yeoman.generators.Base с yeoman.Base.

+0

** Точно, что я искал. Благодарю. – Fiona

+0

Я знаю, что это старо, но это близко к тому, что я ищу. Моя проблема в том, что мой подгенератор расширяет «yeoman.generators.NamedBase». Когда я запускаю этот код, я получаю «Ошибка: не предоставлял требуемое имя аргумента!» Я пытаюсь выяснить, как передать имя (т. Е. «Тест» в «yo make: controller test») на подгенераторы, вызываемые .invoke(). Любая помощь? – ItJustWerks

+1

Получил это: this.invoke ("make: controller", {options: {nested: true, ...}, args: [this.name]}); – ItJustWerks

2

Вы можете покрыть все возможные сценарии выполнения, проверку состояния, побуждая при создании генераторов вместе, если вы отвязать генераторы и использовать «главный-генератор» цикл контекст запуска поможет вам. Используйте options.composeWith('my-genertor', { 'options' : options }) для передачи конфигураций в сгенерированные генераторы.

При использовании .composeWith функция приоритетных групп (например: prompting, writing ...) будет выполнена для всех генераторов, а затем следующей группы приоритетов. Если вы звоните .composeWith в generatorB изнутри generatorA, то выполнение будет, например:

generatorA.prompting => generatorB.prompting => generatorA.writing => generatorB.writing

Если вы хотите, чтобы контролировать выполнение между различными генераторами, я советую вам создать «главный» генератор, который составляет их, как написано на http://yeoman.io/authoring/composability.html#order:

// In my-generator/generators/turbo/index.js 
module.exports = require('yeoman-generator').Base.extend({ 
    'prompting' : function() { 
    console.log('prompting - turbo'); 
    }, 

    'writing' : function() { 
    console.log('prompting - turbo'); 
    } 
}); 

// In my-generator/generators/electric/index.js 
module.exports = require('yeoman-generator').Base.extend({ 
    'prompting' : function() { 
    console.log('prompting - zap'); 
    }, 

    'writing' : function() { 
    console.log('writing - zap'); 
    } 
}); 

// In my-generator/generators/app/index.js 
module.exports = require('yeoman-generator').Base.extend({ 
    'initializing' : function() { 
    this.composeWith('my-generator:turbo'); 
    this.composeWith('my-generator:electric'); 
    } 
}); 
Смежные вопросы