Skip to content

Commit

Permalink
fix(model sub-generator): add automatic prompt pruning for command li…
Browse files Browse the repository at this point in the history
…ne option equivalents, this removes the need for the '--nested' command line kludge when used as a compositing sub-generator.
  • Loading branch information
cueedee committed May 7, 2015
1 parent 68b90d7 commit 0096e01
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 52 deletions.
3 changes: 1 addition & 2 deletions generators/collection/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,7 @@ var CollectionGenerator = generators.Base.extend(

, options:
{
nested: true
, description: 'Model for the ' + data.collectionName + ' collection.'
description: 'Model for the ' + data.collectionName + ' collection.'
, singleton: false
}
}
Expand Down
114 changes: 64 additions & 50 deletions generators/model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,37 @@ var ModelGenerator = generators.Base.extend(
, desc: 'The name of the model to create.'
}
);

// Also add 'modelName' as a - hidden - option, defaulting to the positional argument's value.
// This way `_promptsPruneByOptions()` can filter away prompting for the model name too.
//
this.option(
'modelName'
, {
type: String
, desc: 'The name of the model to create.'
, defaults: this.modelName
, hide: true
}
);

// Normal options.
//
this.option(
'description'
, {
type: String
, desc: 'The purpose (description) of the model to create.'
}
);

this.option(
'singleton'
, {
type: Boolean
, desc: 'Specify wether this model should be a singleton (instance).'
}
);
}

, initializing: function ()
Expand All @@ -34,68 +65,55 @@ var ModelGenerator = generators.Base.extend(

// Container for template expansion data.
//
var data = this.templateData =
this.templateData =
{
modelName: this.modelName
}
;

// Check if any options are passed. Collection generator might be
// calling this generator for example

var options = this.options;

if ( options )
{
if ( options.description )
{
data.description = options.description;
}

if ( typeof( options.singleton) === 'boolean' )
{
data.singleton = options.singleton;
}
}
}

, prompting:
{
askSomeQuestions: function ()
{
var done = this.async();
var prompts = this._promptsPruneByOptions(
[
{
name: 'modelName'
, message: 'What is the name of this model you so desire?'
, default: this.options.modelName
, validate: youtil.isIdentifier
, filter: function ( value )
{
return decapitalize( _.trim( value ).replace( /model$/i, '' ));
}
}
, {
name: 'description'
, message: 'What is the purpose (description) of this model?'
, default: this.options.description
, validate: youtil.isNonBlank
, filter: youtil.sentencify
}
, {
type: 'confirm'
, name: 'singleton'
, message: 'Should this model be a singleton?'
, default: false
, validate: _.isBoolean
}
]
)
;

if ( !this.options.nested )
if ( prompts.length )
{
var done = this.async();

// Have Yeoman greet the user.
//
this.log( yosay( 'So you want a BAT model?' ) );

var prompts = [
{
name: 'modelName'
, message: 'What is the name of this model you so desire?'
, default: this.modelName
, validate: youtil.isIdentifier
, filter: function ( value )
{
return decapitalize( _.trim( value ).replace( /model$/i, '' ));
}
}
, {
name: 'description'
, message: 'What is the purpose (description) of this model?'
, validate: youtil.isNonBlank
, filter: youtil.sentencify
}
, {
type: 'confirm'
, name: 'singleton'
, message: 'Should this model be a singleton?'
, default: false
}
];

this.prompt(
prompts
, function ( answers )
Expand All @@ -106,10 +124,6 @@ var ModelGenerator = generators.Base.extend(

}.bind( this )
);

} else {

done();
}
}
}
Expand Down
55 changes: 55 additions & 0 deletions lib/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,61 @@ var _ = require( 'lodash' );

module.exports =
{
/**
* Takes an array of prompt definitions, as would be passed to `this.prompt()`, filters away those for which valid values have been supplied via the
* identically named command line options, fills the `this.templateData` object with those values and returns the pruned list.
* @method _promptPruneByOptions
*
* @param {Array} prompts An array of prompt definitions as would be passed to `this.prompt()`.
*
* @return {Array} The prompts for which no valid value has been supplied through a command line option.
*
*/

_promptsPruneByOptions: function ( prompts )
{
var options = this.options
, data = this.templateData
, remaining = []
, prompt
, name
, value
, final
, index
, validate
, filter
;

for ( index = prompts.length; index--; )
{
prompt = prompts[ index ];
name = prompt.name;
value = options[ name ];
final = null;

if ( value != null )
{
if ( !(( validate = prompt.validate )) || validate( value ))
{
final = (( filter = prompt.filter )) ? filter( value ) : value;
}
}

if ( final != null )
{
data[ name ] = final;
}
else
{
remaining.unshift( prompt );
}
}

return remaining;
}

,
/**
* Process template files; either copying them as-is from `#sourceRoot()` to `#destinationRoot()`, or expanding them with #templateData first.
*
Expand Down

0 comments on commit 0096e01

Please sign in to comment.