Create a model named Pokemon and then try to generate the scaffold for it:
yarn rw g scaffold pokemon
yarn run v1.22.4
$ /Users/price/Repos/xx-delete/node_modules/.bin/rw g scaffold pokemon
✖ Generating scaffold files...
→ 15 | })
Adding scaffold routes...
Adding scaffold asset imports...
/Users/price/Repos/xx-delete/api/src/services/pokemon/pokemon.ts: Identifier 'pokemon' has already been declared (12:13)
10 | }
11 |
> 12 | export const pokemon = ({ id }: PokemonWhereUniqueInput) => {
| ^
13 | return db.pokemon.findOne({
14 | where: { id },
15 | })
✨ Done in 4.19s.
It turns out this is because the plural and singular forms of "pokemon" are the same. :( The JS generators don't actually care, but if you try to generate TS (which the scaffold, service and SDL generators all do by default) it will complain that an identifier already exists and refuse to continue. But even with the JS generators, some files aren't created because some of the filenames are identical.
Run a check at the start of any generator that depends on generating things specifically with singular/plural name differences that will blow up with a message letting the user know before generating anything:
[ERROR] Singular and plural are returning the same string! You should add a rule
to disambiguate:
pluralize.addPluralRule(/pokemon$/i, 'pokemonii')
I'm not sure where this custom rule can go so that it actually gets picked up by the scaffold generators. In Rails, a brand new app will include a file config/initializers/inflections.rb where you can add custom pluralization rules and they are picked up for use by the generators:
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
inflect.irregular 'human', 'humans'
end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end
Maybe we can include some kind of web/src/lib/pluralizationRules.js file and the generators will include that file if it exists before starting.
@cannikin Would redwood.toml be a good place for this?
[generators]
pluralRules = [/pokemon$/i, 'pokemonii']
Ooooo interesting....what do you think @peterp?
I think it would be easier to put it in a specific place - I like your suggestion of placing it in web, but maybe we could put it in web/config/pluralizationRules.js
Right now the only place it's biting us in the scaffold generators which are the CLI, not the user's web or api side. I don't think we have any other pluralization in the web or api side after your app is created. Maybe this just needs to be a flag you can set when generating:
yarn rw g scaffold pokemon --plural=pokemons
And then we'll use that as the plural form, rather than generating it from the name of the model. We probably also need a singular flag if your model name is plural:
yarn rw g scaffold pokemons --singular=pokemon
I think this is helpful, but should be prioritized as step 2. Step 1 would be to modify the generators so they fail gracefully, e.g. don't blow up on a word like "pokemon" and give a readable message with suggestion to use a different word for the model.
yarn rw g scaffold pokemon --plural=pokemons
^^ As for handling specifics words (which will also be awesome for multi-language support), this makes the most sense to me. I think config is a bit overkill for something a developer will likely do once or twice. (i.e. run the generator.)
We probably also need a singular flag if your model name is plural
^^ I thought the "rule" was for model names to _only_ be singular?
Step 1 would be to modify the generators so they fail gracefully, e.g. don't blow up on a word like "pokemon" and give a readable message with suggestion to use a different word for the model.
Makes sense, although if we're only releasing once a week we can probably get both the warning and the --plural flag done to ship together...
I think config is a bit overkill for something a developer will likely do once or twice. (i.e. run the generator.)
Yeah, I was thinking for some reason that we use the pluralization rules in the app itself (web and/or api) side but I don't think we do at this point. Again I'm used to Rails where those rules are used EVERYWHERE and so you need them configured app-wide.
^^ I thought the "rule" was for model names to only be singular?
That's the syntax that Prisma shows in their schema-from-scratch examples, but there's nothing stopping someone from putting whatever they want for the model name. I haven't checked the docs for this in a while, but one of their other big examples is introspecting an existing DB and converting to Prisma, and in that example the table names are all lowercase and plural.
@cannikin Ah, makes sense across the board. Especially the "introspecting" case.
I agree with the two part approach, the problem has bit me again today.
I don't know if this is possible, but what if the pluralized version didn't rely on hard-to-generalize rules of English, but instead just appended some string to the model name? I'm not sure where all the pluralized version is used, but instead of trying to go from pokemon --> pokemans, could it just be pokemon --> pokemonList?
A very similar issue came up in the CRUD function generators for nexus-plugin-prisma where they are trying to use the pluralize package. There is an issue open to address it, and one recommendation is to do what Prisma apparently decided to do, which was to switch from trying to explicitly pluralize the model names to instead using e.g. pokemon.findOne() and pokemon.findMany().
A quick fix could be to just compare the output of pluralize with the input. If they're the same (in the case of pokemon) then just append an "s" and continue with life as usual. We could add a warning in the console output letting the user know we did that if it happens.