Interactive "rails new"

One of my common frustrations when setting up a Rails app is that I’ll do “rails new”, set up the application, and then get a little way in before remembering that I either wanted to disable turbolinks, or choose a different database, or whatever the option may be. Obviously you can append the options (listed under rails new --help), but the process of reversing some of these decisions once you’ve already started is a bit painful.

Would it be possible to have a rails new --interactive option, which then prompts for some of the following? (Defaulted, of course, to the rails defaults.)

  • Choose database
  • The various skip options, e.g. system tests, turbolinks, sprockets, webpack

This could even change the default “rails new” behaviour and ask if you want to toggle advanced options, with a note to say that if you’re new to Rails it’s recommended you stick with all the defaults.

36 Likes

This is a fun idea. I was thinking about something like this just yesterday as a way to go through all of the modules and figure out which ones you want to keep or not. The database chooser is an especially good idea because almost every time I run rails new for a project, I have to re-run it with the Postgres specifier.

5 Likes

Something similar to eslint --init ?

Why not having rails new be interactive on first run and save the choices a user makes to a .railsrc to avoid re-asking in future runs?

7 Likes

The “rails new” defaults should be the most basic config for a new user. The advanced stuff like turbolinks, console debugging, etc. should be opt-in. If I ever do “rails new” I have to abort it before it installs a bunch of wild gems I never wanted.

3 Likes

I do think there is value in rails new doing a setup that is simpler to get going with fewer things set up, and then perhaps the ability to add those via rails g «something» later. Things that I would omit from a basic rails new, not because they are bad or wrong, but because they cause confusion—especially during failure—and are not needed in order to get an app going

  • Turbolinks - hijacking links/navigation will be super confusing at first
  • Spring/listen - Spring often has weird caching issues
  • Active Storage - generates really strange routes in bin/rails routes and warnings by default when deploying
  • Action Mailbox - also generates really strange routes in bin/rails routes that can’t be turned off
  • Parallel Testing - failure modes can be very confusing

In general, inert features that don’t cause warnings, odd behavior, or strange failures should be left in. Action Cable is a good example. Most won’t need it, but it also doesn’t do anything.

4 Likes

Possibly wrapping in some of what http://www.railscomposer.com does?

Although, to contradict myself, things that aren’t on by default tend to never get used, so maybe a better approach, at least to the problem I’m solving, is to improve the failure modes of these parts of the API and/or change some default behavior.

4 Likes

I did a POC about that few months ago. :slight_smile:

https://github.com/rails/rails/compare/master...kassio:rails-new-interactive

2 Likes

I’m not in love with the idea of an interactive composer, but I can say that I’m never really looking forward to running rails new because I know I’ll want to customize a lot of defaults. (Edit: I could be convinced though. The one from Vue-cli looks pretty good when I think about it.)

Fun thing, I ran rails new this week, and what I tend to do is to commit right away the result of the generator, and then make a commit for every single change/customization I make until I get a to decent base commit I’ll then branch off.

(Protip: If you’re comfortable with the Git stage-commit workflow, it makes it easy to track/reuse these customizations!)

And so I’d like to share my own, hopefully to give an idea of where I aim for, as someone who’s been on Rails for almost 10 years now:

  • (.railsrc contains --database postgresql --skip-test)
  • Rails new!
  • Gems:
    • Remove tz-info-data (I don’t use windows or Jruby and don’t like the warning)
    • Add pry-rails and pry-rescue (I cannot live without pry)
    • Add redis
    • Add haml
  • Add and install Rspec
  • gitignore:
    • Add config/database.yml + rmcached (sometimes I add a config/database.yml.example)
    • Add notes/ folder (personal one!)
  • Add .envrc.example
    • (.envrc is not tracked – see direnv)
    • I will often add two things in there: export PORT=XXXX; PATH_add bin
  • config/env/dev.rb:
    • Add config.hosts << ".test" (puma-dev)
    • Add config.hosts << ".ngrok.io" (I’m never very happy to be needing this :wink: )
  • config/app.rb:
    • Add config.generators.system_tests = nil
      • (When I TDD I usually create the file myself. I would much rather opt-in to test file generation.)
    • Add config.{eager_load,autoload}_paths << Rails.root.join('lib')
  • Convert layout/application.(html -> haml) , stylesheets/application.(css -> sass) , javascripts/application.(js -> coffee)
    • (I get especially annoyed by this :upside_down_face:)
  • I18n/fr.yml: Add default error messages
    • (I usually copy those from Rails somewhere)
    • I18n is never the land of rainbows and unicorn :wink:
  • In the category almost-always-useful home brewed utilities:
    • Add ApplicationHelper#markdown method (and gem)
    • Add ApplicationHelper#title (alias for content_for(:title, ...))
    • Add ApplicationHelper#body_class (joins controller name, action, and content_for(:body_class))
  • Add Token concern (models can ask to generate an alphanum identifier on before_create)
  • Layout:
    • Link CSS framework
    • Add responsive meta tag
      • meta(name="viewport" content="width=device-width, initial-scale=1")
  • (After that first push to production):
  • config/env/prod.rb: Set config.action_mailer.smtp_settings = {x => ENV['SMTP_X'], ...}
    • x being [port, address, user_name, password]

And so with that done, that addresses a lot of annoyances. Hopefully that gives an insight into what dev-UX tweaks can be made.

5 Likes

Mega big +1 on this — a (possibly optional) interactive rails new would be truly fabulous, and perhaps isn’t a huge lift if it’s just choosing the options which are already available.

2 Likes

Thanks for sharing this! I’m curious if you know of or considered/rejected the --template argument of rails new, which allows using Rails generator methods to automate these steps. Here’s mine: https://github.com/bensheldon/rails_new/blob/master/rails_template.rb

I’m in favor of interactive mode because I think it makes the switches and features more discoverable, especially for the Intermediate developer who is capable with Rails and is learning how to go deeper with the framework.

5 Likes

Being able to turn frameworks on and off more easily would be amazing. Not just with rails new --skip methods but later too, during upgrades (app:update), or just because of changing requirements.

Replacing require 'rails/all' with the full list by default. And having some kind of rails ungenerate x or config feature flag for the major frameworks would be great.

2 Likes

What do you mean by “frameworks”? Like ActiveRecord, ActionView, and so on?

Here’s the rails new command I ran to start our last project:

rails new my_app \
  --database postgresql \
  --skip-action-mailer \
  --skip-action-mailbox \
  --skip-action-text \
  --skip-active-storage \
  --skip-sprockets \
  --skip-listen \
  --skip-javascript \
  --skip-turbolinks \
  --skip-test \
  --skip-system-test \
  --skip-bundle \
  --skip-webpacker \
  --skip-webpack-install \
  --skip-spring \
  --skip-bootsnap

The list of things installed by default is insane. A rich text editor? I can understand that with Wordpress, but it’s very strange to assume every rails app needs a rich text editor. Or needs to receive email. Or send email. Or wants to use turbolinks. Etc, etc.

I know Rails is meant to be batteries included (omakase :grin:) but it seems like it could benefit from a weight loss plan, or at least more pared down defaults. Then, maybe add a way to quickly add action-text, if and when desired, for example.

8 Likes

There’s some discussion of what that could look like in Interactive "rails new" – would you mind looking at some of the ideas there and telling me what you’d find most helpful?

Feel free to merge this thread in, it’s related enough.

An interactive approach sidesteps the real problem which is the every-growing list of things that most people don’t need or want being thrust upon us.

I agree with others who are interested in being able to “rails g” things later, though really, some documentation on adding in X (like every gem must do anyway) is sufficient. Optimizing for the first 10 minutes of a project or adding a new gem doesn’t do much in the long run.

3 Likes

When creating a new app, there are so many things that could be skipped that I did not know about and did not find an explanation of how to add those features later on if I need them. I had to look up into each of them, decide if I needed them now or could maybe who knows need it later.

The lack of simplicity (maybe only perceived) of adding those features later makes a choice that should be simple (do you need X now or soon?) much more difficult (Is there any chance you will need X at one point? Do you even know what X does? Go look it up!).

There needs to be at least a guide on how to retrofit an app to add each of these feature. Maybe there is one? I didn’t find it. I think it should be mentionned clearly in the doc and in the help for the rails new command. Having this clear would even allow the default of rails new to not include everything. So things become opt-in instead of opt-out, food for thoughts.

5 Likes

What is your motivation behind removing parts like ActionText, ActionMailbox, etc.?

--skip-bootsnap

If you have time, I’d like to understand that one. Because I can see how one might think that spring for instance is a tradeoff, but I can’t think of any downside of bootsnap, so I really wonder what makes you pass on a faster boot time.

3 Likes