Interactive "rails new"

Let’s exclude bootsnap on --minimal; I think that will be principle-of-least-surprise here. Folks who want bootsnap but not the rest of the big modern Rails grab bag can always add it for themselves later.

3 Likes

A big pain point for me is that rails new doesn’t check its inputs in many cases. In others, it provides less feedback than it could. I’d really like an interactive version to model the full domain of rails new options, and give assistance when it’s obviously needed. The current UX is this way because of its architecture of extensive opaque delegation without back-propagation of errors. But we can do things differently in the interactive version.

Examples of UX improvements that we could make in the interactive version:

Silent failure like this should be impossible. Because usually, the mistake is buried in a list of other options, and the incorrect config is discovered much later.

rails new my_app --skip-javascrpt`
      create
      create  README.md
      create  Rakefile
(etc.)

When a user clearly misuses the CLI API like this, we should at least show its synopsis and show how to get help:

$ rails new
No value provided for required arguments 'app_path'

Ditto, because it’s not clear where the app_path should be positioned on the command line:

$ rails new --skip-bundle
No value provided for required arguments 'app_path'
2 Likes

I’d love to have more control in the way rails generates apps.

I’d much rather see this implemented through a config file rather than an interactive installer though.

What would be really magnificent is if you could change your mind at a later date, change the config and run rails install:update to respond to changes

##install.yml

default: &default
#supported options are :none, :sqlite, :mysql, :postgres
  database: sqlite
#supported options are :rspec, :minitest
  testing: rspec
#whether to install active storage and run update the database to support it true/false
  active_storage: true

development:
  <<: *default


test:
  <<: *default


production:
  <<: *default
  database: postgres


just to elaborate on this idea - the issue for me is that I find interactive installers painful to use. They necessarily have to run through a bunch of questions and I have to come up with answers in order.

by contrast - a text file is in some ways the ultimate ‘interactive’ installer. I can open it up in my editor, scan through the things I want to find and read the comments (which could links to explanatory articles)

the flow here would be something like

> Rails new myApp
< Rails has generated an install configuration at ./config/install.yml  
< Please open this in your text editor, adjust as necessary, then run Rails install:update

another advantage of doing this in a file rather than an interactive session is that I can save and re-use the file. With the session, I need to remember my answer to question #7 and repeat it each time.

2 Likes

I think this is an excellent idea. Having a way to re-interrogate these choices later in the day is such a challenging problem to solve, and this gives a neat path forward.

Walter

1 Like

I’d much rather see this implemented through a config file rather than an interactive installer though.

I like this a lot. It scratches all my itches:

  • I can change my mind and install/uninstall something later
  • It documents the options available to me.
  • It allows future-me to clearly see the decisions that past-me has made.

I tend towards a minimalist gemfile, not even installing gems that I know I will need later until I am actually ready to make use of them. This option would be perfect for me along with a --minimal flag.

It seems to me that a config file doesn’t preclude an interactive installer. An --interactive flag could be a good teaching aid for first timers while more experienced devs would likely use the config file.

2 Likes

I like the idea of a config file a lot, although I might suggest something in application.rb itself rather than a yml file.

I think that getting there might take years of refactoring.

What are some small steps that you feel might get the ball rolling on that project?

What are some small steps that you feel might get the ball rolling on that project?

  1. Perhaps rails new could record what it did (and didn’t do) in an install.yml file.
  2. rails new --config=install.yml could make it easy to copy the options from a previous installation.
  3. Overtime, we could add comments to that file to explain how to change a decision manually (for example to switch from mysql to postgres or to add or get rid of turbolinks).
  4. There could be an incremental process of automating some of those choices by editing the install.yml file and running rake install:update. There would probably be some low-hanging fruit but other options might be more difficult.

As you say, Betsy, this might take a while to complete and an awkward period where install:update can update somethings but not others but the first two steps would be valuable on their own.

I was thinking of application.rb (and the Gemfile) as being downstream from this process.

1 Like

Hmm, I think application.rb might be central because I worry about an install.yml approach getting out of sync with the actual application.

I’m open to being wrong here.

I’m trying to think of a good way to do a “tryout” of this idea outside of mainline Rails. It’s difficult, because it’s not a situation where using a gem as the “tryout” vector is a natural fit.

Correct me if I’m wrong, but I see config/application.rb and this install.yml pseudo-script as quite different things? It sounds to me like the .yml is more like “instructions for the generator” whereas app.rb is ‘permanent config’.

I admit I really like the install file idea, and restricting that to app.rb makes it lose its benefits, unless there’s something I’m missing.

The way it appears to me, by default, application.rb just contains a load directive to rails/all. It’s up to the install process as to what “all” means. So having an install.yml record of what was installed, and allowing that to be re-played to remove or add things, would mean that application.rb could remain fixed in place, yet always get the correct definition of “all” based on what was installed.

One possible hitch – if installing something means also generating an initializer to configure/load/tweak it, and re-running install didn’t also remove or disable that initializer, then you would have genuine confusion.

Walter

As suggested earlier, perhaps simply replacing “require ‘rails/all’” with the full list would be a good start.

As for handling the initializers, couldn’t they all be wrapped in ActiveSupport.on_load hooks, and those hooks only run if the component is required? I appreciate that it isn’t perfect since you’d have unexecuted initializers around, but it would be easy to toggle on or off with a comment of the require line for the component.

1 Like

I recently sat down and generated fresh Rails 6 apps using each rails new skip flag to see what is actually being installed/removed. I diffed each codebase against an app generated without any skip flags and documented the differences here. The snippets in the documentation are the files/code that is not included when using the skip flag.

I admit the documentation is rather terse and not without errors, but nevertheless useful for those curious about the skip flags.

Edit: This was supposed to be a reply to Post #21 above.

5 Likes

please don’t anyone get hung up on my suggestion as a yml file!

I just wanted to demonstrate some kind of text file.

Proper thinking needs to be done on the format, location, etc…

I jumped at yml because I thought there might be some similarities with the database.yml in the sense of handling different environments with inheritance. Frankly I prefer .rb files generally - so perhaps install.rb.

I do think this should be separate from Application.rb for the reasons Walter outlined, but please don’t get hung up on my throwaway example. It wasn’t intended to be a thought-through solution.

1 Like

There is some similarity as well with bin/setup and db/seeds.rb.

We had started working on a new app to address the rails new fatigue even before “May of WTFs” came about. The discussion here confirmed our suspicion that creating new Rails apps is a source of significant pain in the Rails community.

We have shown the app to a couple of people, and the feedback has been unequivocally positive. Thus, we are releasing it publicly today (warning - initial release, rough around the edges, beta, yadda yadda):

https://railsnew.io

We believe that railsnew.io is the simplest and fastest way to create a new Rails app with (or without!) all the bells and whistles:

  • Choose what you’d like to keep/skip
  • Leverage the power of the Rails template API to add external libraries (using pre-made templates)
  • Copy the generated command and create your app

But wait, it doesn’t even end there! You get step-by-step instructions for non-trivial setups (e.g., Stimulus Reflex + Tailwind) to verify that everything works correctly.

Some clarification:

  • We do not think railsnew.io should replace interactive mode or any other ideas presented in this thread. It’s just a way (even if we currently believe it’s the best way, given that not much else exists :sweat_smile:) to address the problem
  • It could actually work well with some of the ideas proposed above (e.g., generating the configuration file)
  • There’s no catch! You won’t find anything shady here (not even google analytics or in-your-face social media share buttons). We aren’t trying to sell anything or have any ulterior motives.

As stated above, it is more of a concept than a finished product right now. With your feedback, we believe it could become something truly useful, though. So please let us know what do you think!

11 Likes

This looks amazing! Thanks for building :slight_smile:

Thanks! We already received a ton of useful feedback, so there’s more to come :muscle:.

1 Like

I have opened a PR for the --interactive flag. Would appreciate any feedback, thanks!

1 Like

I’m going to work on this shortly, just wanted a little bit more clarification on what you are expecting re: the API.

The one proposed seems nice:

  • bin/rails actionmailer:install

What do you think about this alternative one:

  • bin/rails stacks:install actionmailer
  • bin/rails stacks:remove actionmailer or bin/rails stacks:uninstall actionmailer
  • bin/rails stacks:list/info (display all current stacks configured)
2 Likes

An observation here. There was a post a little while ago about sensible infrastructure defaults:

and another post popped up today ‘how do I deploy to production’

It occurs to me that the setup decisions in ‘rails new’ are closely related to the production deployment requirements.

In terms of deployment, I wondered (elsewhere) whether Rails could abstract the requirements in such a way that different ‘production gems’ could take over. - If I want to run on Heroku, I add just gem 'HerokuInfrastructure' if I want to run on Hatchbox, it is gem 'HatchboxInfrastructure'

It may be that this is a good filter to use when thinking about the saved config from an install.config file (however that may be managed). Could the install config file be the same file that provides all the info a deployment gem requires??

certainly, a lot of the questions asked in install will provide the answers that a deployment solution needs to know:

database / redis / active storage / etc

obviously some might have different answers; sqlite in dev vs postgres in production (though I’m a fan of keeping dev/testing as close to production as reasonable)

anyway - my point is that making first-install friendly/flexible may be closely related to the question of making deployment friendly/flexible. It may help to keep both in mind as the first is tackled…

thanks.