web-dev-qa-db-ja.com

Yeoman:ユーザー指定の引数を使用してサブジェネレーターを呼び出す

私は最初のYeomanジェネレーターを作成しています。これは、ユーザーにさまざまな入力を求め、その応答に基づいて条件付きでファイルを作成します。ユーザー入力に基づいてサブルーチン(Yeomanサブジェネレーターの場合もあります)を呼び出し、それに引数を渡すことができる必要があります。

名前付き関数(自動的には実行されない)を使用する理由は、ユーザーの応答によって複数の関数を組み合わせて呼び出す場合と、関数を単独で実行する場合があるためです。

私が試したこと:

ユーザーが要求した場合にのみファイルのセットを作成するので、サブジェネレーターが最適な方法であると考えました。しかし、条件付きで呼び出して、ユーザーが入力したものを渡すのに問題があります。 hookForを使用しようとしましたが、アサーションエラーが発生します:_hookFor must be used within the constructor only_。 (デフォルトで実行したくないので、this.Prompt(prompts, function (props)からサブジェネレーターを呼び出しています)。

質問:

ユーザーが(プロンプトを介して)要求した場合にのみルーチンを呼び出し、そのルーチンにユーザーが指定した情報を渡すにはどうすればよいですか?

あなたが親切に答えてくれるなら、私が何か明白なことを試みたと思い込まないでください;-)。

30
Fiona

2つのサブジェネレーター(blog-serverとblog-client)を持つジェネレーター_generator-blog_(BlogGenerator)があるとしましょう。

_app\index.js
client\index.js
server\index.js
_

したがって、_yo blog_を実行するとき、ユーザーにいくつかのオプションを要求し、(オプションで)サブジェネレーターを実行する必要がありますか?

サブジェネレーターを実行するには、this.invoke("generator_namespace", {options: {}})を呼び出す必要があります。渡した2番目の引数には、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}});
  }
};
_

Client\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);
  }
}
_

PDATE 2015-12-21
invokeの使用は非推奨になり、composeWithに置き換える必要があります。しかし、それはそれほど簡単ではありません。 invokecomposeWithの主な違いは、サブジェネレーターを制御する機能がなくなったことです。それらを使用して宣言することしかできませんでした。
上記の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_に削除しました。

32
Shrike

2015-04アップデート:yeoman apiには、ジェネレーターをリンクするための推奨メソッドとしてthis.composeWithが含まれるようになりました。

ドキュメント: http://yeoman.io/authoring/composability.html

7
TomFuertes

ジェネレーターを分離し、「メインジェネレーター」を使用する場合、ジェネレーターを一緒に構成するときに、考えられるすべての実行シナリオ、条件チェック、プロンプトをカバーできます。実行コンテキストループが役立ちます。構成されたジェネレーターに構成を渡すには、.composeWith('my-genertor', { 'options' : options })optionsを使用します。

.composeWithを使用すると、優先グループ関数(例:promptingwriting...)がすべてのジェネレーターに対して実行され、次に次の優先グループが実行されます。 generatorAの内部から.composeWithgeneratorBに呼び出す場合、実行は次のようになります。例:

ジェネレーターA.prompting =>ジェネレーターB.prompting =>ジェネレーターA.writing =>ジェネレーターB.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');
  }
});
2
p1100i