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

Run rails generate commands automatically when Super Scaffolding #547

Merged
merged 20 commits into from
Oct 4, 2023

Conversation

gazayas
Copy link
Contributor

@gazayas gazayas commented Sep 13, 2023

@gazayas
Copy link
Contributor Author

gazayas commented Sep 13, 2023

The plan from here is to run rails generate for the crud scaffolder first and try to go through each model in the test setup script step by step.

@gazayas
Copy link
Contributor Author

gazayas commented Sep 22, 2023

cc/ @jagthedrummer @pascallaliberte @kaspth

Hey everyone, I decided to tag you guys because I think this PR could go one of two ways, one of which would have a big impact on our Super Scaffolding flow.

Our two options

  1. Running something like bin/super-scaffold crud Project Team title:text_field will automatically run the rails g model command before scaffolding all of our templates, etc.
  2. Instead, we can just add a flag like this: bin/super-scaffold crud Project Team title:text_field -—run-migration.

The current state of this PR

This PR currently works with commands like the following (option 2):

bin/super-scaffold crud Project Team title:text_field --run-migration
bin/super-scaffold crud-field Project test_number:number_field test_boolean:boolean --run-migration

My thoughts

I think 1 is closer to vanilla Rails scaffolding, but I'm afraid there will be situations in which we WON'T want to Super Scaffold all of the attributes to the new views. In this scenario, we could add a flag to say --skip-migration instead.

If we go with option 2, Bullet Train developers can still do things the old way, and if they're certain they want to run the migration on the spot then they can just add the --run-migration flag.

What seems most intuitive to you all? I personally like 1 the most, but I think developers will get thrown off if they are too used to the original workflow.

@jagthedrummer
Copy link
Contributor

@gazayas, do we need to automatically run migrations before we can super scaffold things? (I don't know a lot about the internals of how super scaffolding works.)

In general I think we should try to stick as closely as possible to the "normal Rails way", mainly so that things feel familiar and intuitive for devs that are already familiar with those patterns. So I'm kind of inclined to just tell people to run the migration themselves the normal way.

For example, if I were scaffolding a project in vanilla rails I'd do something like:

rails g scaffold Project team:references title:string
rails db:migrate

And so, (possibly naively) I'd expect the same general pattern for super scaffolding:

bin/super-scaffold crud Project Team title:text_field
rails db:migrate

Using a --run-migrations flag feels like a nice "quality of life" improvement that would allow me to combine everything into a single step if I know that's what I want.

Conversely requiring a --skip-migrations flag in order to make things work closer to The Rails Way seems like it assumes people will already posses some knowledge about The Bullet Train Way. (Not that that's necessarily bad. There's certainly a story we could tell about how we're saving you a step.)

As far as how to handle fields that shouldn't be on the form, I think that if we don't run the migration for people that they'd be able to handle it "the normal Rails way". That is they could either:

  1. Generate a scaffold for the things that should show up in the form, and then edit the migration to add additional columns that shouldn't be on the form.
  2. Generate a scaffold for the things that should show up in the form and also generate a second migration to add some additional non-form fields.
  3. Generate the scaffold with all of the fields, and then edit the form and controller to remove attributes that shouldn't be user-facing.

And if we do run migrations for people then it's pretty easy to follow up with a second vanilla migration to add whatever extra fields are needed.

Aside

Not suggesting we tackle it in this PR, but it would be nice if we could get our super scaffolding commands to be closer to vanilla rails commands. I'd love to be able to do:

rails g super-scaffold Project Team title:text_field
rails db:migrate

@gazayas
Copy link
Contributor Author

gazayas commented Sep 22, 2023

@jagthedrummer Thank you for the feedback! I realized there's a portion that I didn't explain, so I'll write that here and maybe that will clear things up.

--run-migrations

I had trouble naming this flag because crud and crud-field accomplish two different things. This flag doesn't run rails db:migrate, but does the following:

  1. For the crud scaffolder, it runs rails g model ModelName
  2. For the crud-field scaffolder, it runs rails g migration migration_name

I originally wanted to name this --generate-model to cover both of the scaffolders, but crud-field doesn't actually generate a model. I also didn't want to name it --generate-migration because I felt it would be too long. So yes, I'm not 100% sure what to call the flag name right now, but I can see how --run-migration implies rails db:migrate, which is not what we want. After reading your comment though, I feel more confident that we can just do away with the flag.

Defining separate attributes in a different migration

  1. Generate a scaffold for the things that should show up in the form, and then edit the migration to add additional columns that shouldn't be on the form.
  2. Generate a scaffold for the things that should show up in the form and also generate a second migration to add some additional non-form fields.

Yes, I like these either one of these (mostly the second option). I think we can mention it shortly in the Super Scaffolding documentation and that that would suffice.

@gazayas
Copy link
Contributor Author

gazayas commented Sep 22, 2023

@jagthedrummer
Copy link
Contributor

@gazayas, thanks for the additional info. With that new info I agree with your initial assessment that the first option you presented is the best. (But if we want to go with the second option for some reason I think the flag should be named --generate-migration instead of --run-migration. Even though it's a bit longer I think it's clearer as to what it does.)

@kaspth
Copy link
Contributor

kaspth commented Sep 25, 2023

Would it be clearer if we added this as separate commands like crud-migration and crud-field-migration? I know that could be a problem if we added more options in the future, but it feels tough to name the migration option without having it be ambiguous.

@gazayas gazayas marked this pull request as ready for review September 26, 2023 12:13
@gazayas
Copy link
Contributor Author

gazayas commented Sep 26, 2023

@kaspth I personally like just bin/super-scaffold crud and automatically creating the migrations that way, but I'm open to crud-migration and crud-field-migration too!

Until we decide, I've added the --skip-migration-generation flag in the meantime:

rails g model Project team:references title:string
bin/super-scaffold crud Project Team title:text_field --skip-migration-generation

@gazayas
Copy link
Contributor Author

gazayas commented Sep 26, 2023

This PR is ready for review, I'm still working on updating the documentation though and I'll have to think through delegated types because I don't think we have a test in place for this.

@kaspth
Copy link
Contributor

kaspth commented Sep 26, 2023

@gazayas ok, that sounds good to me!

@gazayas
Copy link
Contributor Author

gazayas commented Sep 27, 2023

Looking at the documentation for delegated types, you can see that we generate a polymorphic model:

rails g model Entry team:references entryable:references{polymorphic}:index

I currently don't have a solution in mind that would automatically run this Rails command, but I've at least added the --skip-migration-generation flag in the documentation so developers can still run the code properly.

@pascallaliberte
Copy link
Member

I like this a lot. Classy.

@jagthedrummer
Copy link
Contributor

I've been a little thin on time this week and haven't been able to do a thorough review yet, but I'm really looking forward to getting this merged. It'll be a very nice quality of life improvement. 🎉

Copy link
Contributor

@jagthedrummer jagthedrummer left a comment

Choose a reason for hiding this comment

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

I just pulled this down and played around with it and I love it! It feels much more like it's an enhancement to the Rails scaffolding procedure that I already know vs being a whole new procedure that has different types of steps than I'm used to.

Since this will change scaffolding behavior on people, but will not break existing code, I'm thinking we should do a minor version bump when we release this one. What do y'all think @gazayas, @kaspth, @pascallaliberte?

email_field: "string",
emoji_field: "string",
file_field: "attachment",
image: "attachment",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be active_storage_image? Or should we remove cloudinary_image above and then have image be a special case where we don't do a direct lookup, but instead check whether Cloudinary is active?

@@ -53,6 +113,19 @@ def check_required_options_for_attributes(scaffolding_type, attributes, child, p
{}
end

data_type = if type == "image" && cloudinary_enabled?
"string"
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, here's that special case I mentioned above. Maybe we remove cloudinary_image from that list? (Or do we want to leave it for backwards compatibility?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we remove cloudinary_image from that list? (Or do we want to leave it for backwards compatibility?)

Right, I was planning on leaving it here for backwards compatibility. However, if we were to delete it, it technically wouldn't be breaking anything so I don't feel too strongly either way right now about leaving it or deleting it.

@gazayas
Copy link
Contributor Author

gazayas commented Oct 4, 2023

Since this will change scaffolding behavior on people, but will not break existing code, I'm thinking we should do a minor version bump when we release this one.

@jagthedrummer I think doing a minor version bump makes sense! Although I will say I'm not too strong when it comes to semantic versioning. I'm curious if there's a set of guidelines we should refer to when updating?

@jagthedrummer
Copy link
Contributor

I'm curious if there's a set of guidelines we should refer to when updating?

@gazayas, there is a guide, but I think our situation is complicated a bit by the fact that the starter repo and the core gems are so tightly intertwined. Maybe we should write out our own "Bullet Train Semver" guide that takes that fact into account.

@jagthedrummer jagthedrummer merged commit 77bb4f6 into main Oct 4, 2023
5 checks passed
@jagthedrummer jagthedrummer deleted the features/generate-models-when-super-scaffolding branch October 4, 2023 15:11
@kaspth
Copy link
Contributor

kaspth commented Oct 4, 2023

@jagthedrummer nice, I'm onboard with the minor bump!

@gazayas great work on this ❤️

jagthedrummer added a commit that referenced this pull request Oct 4, 2023
The PR for testing super scaffolding of Addresses (bullet-train-co/bullet_train#986)
landed right before the PR for automatically generating a migration
during super scaffolding (#547).
As a result a bug / test-failure crept in.

The `Address` model `belongs_to :addressable`, which means that
the relation is stored on the `Address` side, and not on the owning
model. So that means that when we super scaffold an address field it
turns out that we don't need to represent that in the migration for
the model that will own the address.
jagthedrummer added a commit that referenced this pull request Oct 4, 2023
The PR for testing super scaffolding of Addresses (bullet-train-co/bullet_train#986)
landed right before the PR for automatically generating a migration
during super scaffolding (#547).
As a result a bug / test-failure crept in.

The `Address` model `belongs_to :addressable`, which means that
the relation is stored on the `Address` side, and not on the owning
model. So that means that when we super scaffold an address field it
turns out that we don't need to represent that in the migration for
the model that will own the address.
@gazayas
Copy link
Contributor Author

gazayas commented Oct 5, 2023

@kaspth Thank you!

Excited to use this moving forward 🚀

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.

Run rails g model in bin/super-scaffold step
4 participants