Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scaffold Generator File Organization #2613

Merged
merged 22 commits into from
Jun 10, 2021

Conversation

cjreimer
Copy link
Contributor

@cjreimer cjreimer commented May 23, 2021

This is a PR that addresses #2543 regarding scaffold file generation, but I believe it also addresses #340.

Summary of status:

  • Code changes
  • Cypress e2e tests
  • Documentation Changes
  • Tutorial Changes

EDIT ==> please see post starting at Jun 9, 2021 for the latest. There were significant changes in the plan on this one.

What it does is (using a Post model as an example):

  1. Renames the component EditPostCell.js to PostEditCell.js
  2. Renames the component NewPost.js to PostNew.js
  3. Renames the component EditPostPage.js to PostEditPage.js
  4. Renames the component NewPostPage.js to PostNewPage.js
  5. Reorganizes the components into a single folder by default (with an option to retain the existing behavior). See below for details.
  6. Adjusts the imports to the full format to address the new format and get rid of typescript import warnings (DX). See below for details.

Not included in this PR at this time:

  • Restructure of the page folders (other than renaming as described above)
    • There appears to be existing logic regarding folder names having to match page names in the router or other areas of the codebase. More thought would be required if we would want to change this, which I'm not sure if we would want to after briefly looking at it.
  • Optimization of layouts, as suggested by @cannikin is deferred, possibly implementing a future set context to pass in props.

Detail for 5. Reorganizes the components into a single folder by default (with an option to retain the existing behavior):

For example, for a model named Post, it would create the following structure:

in /components/

  • Post/
    • PostEditCell.js
    • PostNew.js
    • Post.js
    • PostCell.js
    • PostForm.js
    • Posts.js
    • PostsCell.js

For tests and story files (not currently available), I envision them to be in subdirectories.

If you want to retain the current individual folder structure, then set the following in the redwood.toml file.

[generate]
  scaffoldIndividualComponentFolders= true

Detail for 6. Adjusts the imports to the full format to address new format and get rid of typescript import warnings (DX)

The imports in the scaffolded files are now fully expressed:

For example:
import PostCell from 'src/components/PostCell'
is now
import PostCell from 'src/components/Post/PostCell'

@cjreimer cjreimer changed the title Cjr generator scaffold org Scaffold Generator File Organization May 23, 2021
@jtoar
Copy link
Contributor

jtoar commented May 24, 2021

@cjreimer Thanks for this, it's looking great! Just tried it out locally and things definitely feel a lot more organized from the get go. It even works with the nested syntax for major organizational wins!

A bit of a warning: you might have to deal with some merge conflicts. There's a few scaffolds/generator-related PRs out there right now. If it should happen, let me know if you need help with that, more than happy to do those for you!

One point of feedback, the name of this toml key:

scaffoldIndividualComponentFolders

Setting this to true means I get the Post/ directory right? I think the "Individual" part is confusing me a little. What do you think of something along these lines instead?

[generate]
  nestScaffoldComponents = true

@cjreimer
Copy link
Contributor Author

@jtoar

Thanks for the feedback. I can help with the merge conflicts. It looks like #2609 might have some things to reconcile with. Do you want that one into the main branch first, or this one?

As for the operation of the toml key:
scaffoldIndividualComponentFolders

Currently, if you leave the key out or set it to false you get the new default behavior as described in the initial post for this pr. If you set it to true, you get something that looks like the previous behavior other than the renaming of the components. You would get:

in /components/

  • PostEditCell/
    • PostEditCell.js
  • PostNew/
    • PostNew.js
  • Post/
    • Post.js
  • PostCell/
    • PostCell.js
  • PostForm/
    • PostForm.js
  • Posts/
    • Posts.js
  • PostsCell/
    • PostsCell.js

I know I kind of argued against this behavior in issue #2543; however, as writing the code, I remembered that the rest of redwood by default has one folder per component, so I thought we should at least have this as an option. We could rename this toml option to: scaffoldOneFolderPerComponent

I'm not opposed to modifying the option, or even adding another option. Could you clarify what you envision nestScaffoldComponents = true would do relative to what the default option does?

@jtoar
Copy link
Contributor

jtoar commented May 25, 2021

Do you want that one into the main branch first, or this one?

If we can get this one in today then let's do it! But no rush. I really only have on point of feedback below about the toml key's name.

Could you clarify what you envision nestScaffoldComponents = true would do relative to what the default option does?

My bad! I just wanted to rename the option scaffoldIndividualComponentFolders, not introduce a new one or anything. nestScaffoldComponents was my suggestion; what do you think of that one? scaffoldOneFolderPerComponent makes it sound like each component will be in it's own folder.

Having this option is great by the way! Thanks for going above and beyond to include it.

@cjreimer
Copy link
Contributor Author

Thanks for the active and great feedback @jtoar !

scaffoldOneFolderPerComponent makes it sound like each component will be in its own folder.

Yes! That's what it does!

@jtoar
Copy link
Contributor

jtoar commented May 25, 2021

Anytime! And ah maybe I'm confused then--doesn't it put all the components (Post, Posts, PostCell, PostCells, etc.) into one folder (Post)? scaffoldOneFolderPerComponent sounds like each component (Post, Posts, etc.) gets its own folder, which is already the case. oneComponentFolderPerScaffold sounds clearer but more verbose.

@cjreimer
Copy link
Contributor Author

No problem ... I think we're just thinking the inverse case of what the flag should do. I can change the function of the flag to the inverse case, as I believe you are proposing. So, then we would have:

toml flag either missing [ default behavior ] or set as follows:
[oneComponentFolderPerScaffold] = true

==> Puts in new behavior and has all components in one folder by model For example:
Post/

  • PostEditCell.js
  • PostNew.js
  • Post.js
  • PostCell.js
  • PostForm.js
  • Posts.js
  • PostsCell.js

If the toml flag is set as follows:
[oneComponentFolderPerScaffold] = false

==> Retains previous behavior and has one folder per component

@cannikin
Copy link
Member

Hmm, when we talked about the components going into a Post directory I assumed they would still be in their own subdirectories: Posts, NewPost, etc. While we don’t currently include tests and stories with the scaffold, we definitely should keep that folder structure so that they have a home when we’re ready.

Unless @mojombo disagrees, but this structure of a directory for each component was kind of one of the pillars of Redwood when we started. You could maybe argue that scaffolds are a special case but I’d have him weigh in on that if we plan on adding an option to let users do something different.

@jtoar
Copy link
Contributor

jtoar commented May 25, 2021

Hmm, when we talked about the components going into a Post directory I assumed they would still be in their own subdirectories: Posts, NewPost, etc

Ah I didn't catch that; that's probably why I was confused about the name. As Rob said, we definitely want to keep them in subdirectories regardless, sorry we didn't make that clear!

@jtoar
Copy link
Contributor

jtoar commented May 25, 2021

And @cannikin this example is probably why we all got confused:

image

I also okayed the changes that were clearly-spelled out in #2543 (comment), so totally on me!

@cannikin
Copy link
Member

cannikin commented May 25, 2021 via email

@jtoar
Copy link
Contributor

jtoar commented May 25, 2021

@cjreimer Don't make any changes to this just yet, I'll get feedback from Tom and Peter tomorrow. I'm pretty sure they'll want to stick to the component-directory structure, but I'll ask them to be sure. Even if we do, we still like the change introduced in this PR of putting all those components in a Post/ directory. Thanks for working on this, and I owe you one!

@cjreimer
Copy link
Contributor Author

No problem, @jtoar and @cannikin! Always pleased to help and give back.

I totally understand the desire to stick with the one component per folder structure, which has been consistently applied in Redwood to date. I can absolutely tweak the code to that behavior!

While I will defer to the core team on this, my personal preference is for tightly coupled components to be grouped into a single folder for that model/domain, with tests and stories in subdirectories (actually more similar to how the redwood framework is structured). With the above as the default case, would there be any support for having this structure as a non-default option requiring a manually set flag? I would see this non-default option getting expanded to the cells and component generators as well, where we specify a path (which could be an existing path), and the tests and stories get created in subfolders.

Either way, I'll get the code cleaned up once we have some direction.

@Tobbe
Copy link
Member

Tobbe commented May 25, 2021

This might not be the place, but FWIW I also think it might be time to take another look at how we organize/structure a RW project. It's getting kind of hard navigating my project by looking at the file tree with just a components and pages directory.

image

I think I'd like to see Cells and Components that are only used by one page to be nested with that page. And I guess nothing is stopping me from doing that, but maybe RW can do something about better supporting other ways to organize the code, or even change the way it currently does it by default.

Maybe this is a discussion better had in the forums...
I posted there as well. Feel free to add any more input anyone might have https://community.redwoodjs.com/t/perfect-file-structure-for-redwood-web/1575/9

@cjreimer
Copy link
Contributor Author

@Tobbe, the changes have been made. Let me know if anything else is needed.

Copy link
Contributor

@jtoar jtoar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjreimer was going to tell you the same thing as @Tobbe; glad you guys got that one already. Huge thanks for this! Besides just organizing our scaffolds, there's a lot of changes you made to the organization of the code here that's for the better (that us maintainers especially appreciate). Super glad we can get this one in!

@cjreimer
Copy link
Contributor Author

Thanks, Dominic!

@jtoar jtoar merged commit e561fe4 into redwoodjs:main Jun 10, 2021
@Tobbe
Copy link
Member

Tobbe commented Jun 10, 2021

Any tutorial docs, tutorial project code or anything else that needs to be updated now?

@thedavidprice
Copy link
Contributor

thedavidprice commented Jun 10, 2021

@Tobbe I had the same docs questions. On my list as well if not addressed here.

@jtoar @cjreimer curious if we tested this compatibility with yarn rw destroy scaffold .... Without looking, I believe there are unit tests that would have needed to be updated in this PR. But will destroy be backwards compatible?

update: it doesn't look like it is backwards compatible — not necessarily an issue but should be discussed
Screen Shot 2021-06-10 at 3 59 17 PM

update 2: ah, I think I'm getting it now. You'd need to use the toml config appropriate to your setup. Confirmed it's working correctly for both create and destroy. Very nice. And I can handle in Release Notes. I like this a lot, btw.

[generate]
  nestScaffoldByModel= false

@thedavidprice
Copy link
Contributor

@jtoar could you help update the current description and help output for yarn rw g scaffold --help:

rw g scaffold <model>

Generate Pages, SDL, and Services files based on a given DB schema Model. Also
accepts <path/model>

Positionals:
  model  Model to scaffold. You can also use <path/model> to nest files by type
         at the given path directory (or directories). For example, 'rw g
         scaffold admin/post'                                         [required]

Options:
      --help              Show help                                    [boolean]
      --version           Show version number                          [boolean]
      --tests             Generate test files                          [boolean]
  -f, --force             Overwrite existing files    [boolean] [default: false]
      --typescript, --ts  Generate TypeScript files   [boolean] [default: false]

@cjreimer
Copy link
Contributor Author

@Tobbe Yes, we should probably update the tutorial. Some of the code extracts presented will need updating.

@thedavidprice I did test the destroy scaffold command reasonably extensively in my test project, and I believe it's working. I admit the automated tests aren't as thorough as the generate command.

As for backward compatible on the destroy command, you would need to add the following to redwood.toml.

[generate]
  nestScaffoldByModel= false

Is it confusing that the option says [generate] but would also apply to the [destroy]?

Alternatively we could look at adding an option into the command line option .. wouldn't be hard with how it's set up.

@thedavidprice
Copy link
Contributor

@cjreimer Nice! I just figured that out locally as well and confirmed in an update to my original comment above. Super slick and I can communicate appropriately in the Release Notes. Thanks again 🚀

@cjreimer
Copy link
Contributor Author

Docs updated in:
https://github.com/redwoodjs/redwoodjs.com/pull/715

@Tobbe
Copy link
Member

Tobbe commented Jun 11, 2021

@cjreimer Do you want to do the tutorial as well? If so, it's here https://github.com/redwoodjs/learn.redwoodjs.com
And the code lives here: https://github.com/redwoodjs/redwood-tutorial

@cjreimer
Copy link
Contributor Author

@Tobbe, I can gladly tackle it, but please know that I have quite a backlog at the moment in my "real" work, so it might take me a couple of weeks to complete. Feel free to assign it to someone else if they have time. Otherwise, I'll gladly put it on my plate.

Do you have a best practice for making sure the code snippets and results presented are exactly as a new user would see? Do you run through the tutorial yourself or make the spot changes as per what you expect? I took a look, and already some of the existing routes stuff in the tutorial looks questionable as to whether it's the latest.

@thedavidprice
Copy link
Contributor

@cjreimer @Tobbe I'll tackle the Tutorial changes. Rob is planning an overhaul once we have a stable v1-rc, so I might just go for "good enough" changes this time around. Regardless, it's on my list to handle.

Thanks, all!

@cjreimer
Copy link
Contributor Author

Thanks @thedavidprice! I appreciate it!

@callingmedic911
Copy link
Member

Hi @cjreimer! I see couple of log when generating and deleting scaffold. I was wondering whether this is intentional or left from development? I will mark it the review page. Should we remove these or maybe rephrase if we have to keep it?

@@ -64,6 +64,9 @@ const removeLayoutImport = ({ model: name, path: scaffoldPath = '' }) => {
new RegExp(`\\s*${importLayout}`),
''
)
console.log('regex:', new RegExp(`\\s*${importLayout}`))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see #2613 (comment)

@@ -64,6 +64,9 @@ const removeLayoutImport = ({ model: name, path: scaffoldPath = '' }) => {
new RegExp(`\\s*${importLayout}`),
''
)
console.log('regex:', new RegExp(`\\s*${importLayout}`))
console.log(newRoutesContent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see #2613 (comment)

}) => {
if (typeof nestScaffoldByModel === 'undefined') {
nestScaffoldByModel = getConfig().generate.nestScaffoldByModel
console.log('nestScaffoldByModel from config: ', nestScaffoldByModel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see #2613 (comment)

@cjreimer
Copy link
Contributor Author

Hey thanks @callingmedic911. Yes, those should be removed. Thanks for catching that!
I'll get that cleaned up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggestion - Redwood scaffold generator - file naming
6 participants