Rails 8.0 with Ruby 3.3 on Windows: It just works! (and what to do if it doesn't!)

Rails 8.0 was released just a few days back and as a user primarily on Windows, I was keen to see it all works and runs on Windows. I had done this check previously with Rails 7.1 on Ruby 3.2 on Windows and it had worked fine. Thanks to the stellar work of everyone involved, it just works. Let’s see a few more details below.

In short, all you need to do is as below:

  1. RubyInstaller – Download and install a supported version of Ruby on your Windows computer: I’m going to install Ruby 3.3.x as explained here but you can also follow instructions for Ruby 3.2.x | Ruby 3.1.x | Ruby 3.0.x
  1. Open a console window, and follow the commands below.
$ gem install rails
$ rails new hello8

If you run into an error at this stage with installing psych, do a gem update and it will probably get resolved since the installation will happen fine from the command line now, and bundle after rails new will pick up the installed version.

Once done, go on in to the hello8 folder and start the Rails Server

ruby bin\rails server

Then, open a web browser and take a look at http://localhost:3000/ to be greeted with this.

I was expecting to document some workarounds and problems I faced but at least at the very beginning, there was nothing. So, I decided to continue on to a part of the Rails Getting Started tutorial.

So, what’s next? Literally, everything! The basic application uses sqlite3 and you might want to use PostgreSQL – you can either install it directly or set it up without an installation.

Detailed steps

Let’s start by seeing the Ruby version we have.

$ ruby -v
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt]

Next, install Rails.

$ gem install rails
$ gem install rails
Fetching rack-3.1.8.gem
Fetching uri-1.0.2.gem
Fetching minitest-5.25.1.gem
Fetching concurrent-ruby-1.3.4.gem
Fetching activesupport-8.0.0.gem
Fetching actionview-8.0.0.gem
Fetching actionpack-8.0.0.gem
Fetching railties-8.0.0.gem
Fetching activemodel-8.0.0.gem
Fetching activerecord-8.0.0.gem
Fetching activejob-8.0.0.gem
Fetching activestorage-8.0.0.gem
Fetching actiontext-8.0.0.gem
Fetching actionmailer-8.0.0.gem
Fetching actionmailbox-8.0.0.gem
Fetching actioncable-8.0.0.gem
Fetching rails-8.0.0.gem
Successfully installed rack-3.1.8
Successfully installed uri-1.0.2
Successfully installed concurrent-ruby-1.3.4
Successfully installed minitest-5.25.1
Successfully installed activesupport-8.0.0
Successfully installed actionview-8.0.0
Successfully installed actionpack-8.0.0
Successfully installed railties-8.0.0
Successfully installed activemodel-8.0.0
Successfully installed activerecord-8.0.0
Successfully installed activejob-8.0.0
Successfully installed activestorage-8.0.0
Successfully installed actiontext-8.0.0
Successfully installed actionmailer-8.0.0
Successfully installed actionmailbox-8.0.0
Successfully installed actioncable-8.0.0
Successfully installed rails-8.0.0
Parsing documentation for rack-3.1.8
Installing ri documentation for rack-3.1.8
Parsing documentation for uri-1.0.2
Installing ri documentation for uri-1.0.2
Parsing documentation for concurrent-ruby-1.3.4
Installing ri documentation for concurrent-ruby-1.3.4
Parsing documentation for minitest-5.25.1
Couldn't find file to include 'README.rdoc' from lib/minitest.rb
Installing ri documentation for minitest-5.25.1
Parsing documentation for activesupport-8.0.0
Installing ri documentation for activesupport-8.0.0
Parsing documentation for actionview-8.0.0
Installing ri documentation for actionview-8.0.0
Parsing documentation for actionpack-8.0.0
Installing ri documentation for actionpack-8.0.0
Parsing documentation for railties-8.0.0
Installing ri documentation for railties-8.0.0
Parsing documentation for activemodel-8.0.0
Installing ri documentation for activemodel-8.0.0
Parsing documentation for activerecord-8.0.0
Installing ri documentation for activerecord-8.0.0
Parsing documentation for activejob-8.0.0
Installing ri documentation for activejob-8.0.0
Parsing documentation for activestorage-8.0.0
Installing ri documentation for activestorage-8.0.0
Parsing documentation for actiontext-8.0.0
Installing ri documentation for actiontext-8.0.0
Parsing documentation for actionmailer-8.0.0
Installing ri documentation for actionmailer-8.0.0
Parsing documentation for actionmailbox-8.0.0
Installing ri documentation for actionmailbox-8.0.0
Parsing documentation for actioncable-8.0.0
Installing ri documentation for actioncable-8.0.0
Parsing documentation for rails-8.0.0
Installing ri documentation for rails-8.0.0
Done installing documentation for rack, uri, concurrent-ruby, minitest, activesupport, actionview, actionpack, railties, activemodel, activerecord, activejob, activestorage, actiontext, actionmailer, actionmailbox, actioncable, rails after 93 seconds
17 gems installed

This time it installed fewer gems for me than previously – it’s probably because some of the dependencies are older installed on my PC since I was using rails main for development a few months back.

You may have noticed this:

Parsing documentation for minitest-5.25.1
Couldn't find file to include 'README.rdoc' from lib/minitest.rb

This is unexpected and there were many more gems with these problems earlier. I had opened an issue on the Rails GitHub for this – most of the earlier list has been resolved, but the warning on minitest still remains.

Quick check – what version of Rails do we have?

$ rails -v
Rails 8.0.0

Good! Now, let’s create a new project.

$ rails new hello8
...
         run  bundle install --quiet
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/psych-5.2.0/ext/psych
D:/Ruby33-x64/bin/ruby.exe extconf.rb
checking for pkg-config for yaml-0.1... not found
checking for yaml.h... no
yaml.h not found
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include=${opt-dir}/include
        --without-opt-include
        --with-opt-lib=${opt-dir}/lib
        --without-opt-lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=D:/Ruby33-x64/bin/$(RUBY_BASE_NAME)
        --with-libyaml-source-dir
        --without-libyaml-source-dir
        --with-yaml-0.1-dir
        --without-yaml-0.1-dir
        --with-yaml-0.1-include=${yaml-0.1-dir}/include
        --without-yaml-0.1-include
        --with-yaml-0.1-lib=${yaml-0.1-dir}/lib
        --without-yaml-0.1-lib
        --with-yaml-0.1-config
        --without-yaml-0.1-config
        --with-pkg-config
        --without-pkg-config
        --with-libyaml-dir
        --without-libyaml-dir
        --with-libyaml-include=${libyaml-dir}/include
        --without-libyaml-include
        --with-libyaml-lib=${libyaml-dir}/lib
        --without-libyaml-lib

To see why this extension failed to compile, please check the mkmf.log which can
be found here:

D:/Ruby33-x64/lib/ruby/gems/3.3.0/extensions/x64-mingw-ucrt/3.3.0/psych-5.2.0/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/psych-5.2.0 for inspection.
Results logged to
D:/Ruby33-x64/lib/ruby/gems/3.3.0/extensions/x64-mingw-ucrt/3.3.0/psych-5.2.0/gem_make.out

  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/builder.rb:125:in `run'
  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/ext_conf_builder.rb:28:in `build'
  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/builder.rb:193:in `build_extension'
D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/builder.rb:227:in `block in
build_extensions'
  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/builder.rb:224:in `each'
  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/ext/builder.rb:224:in `build_extensions'
  D:/Ruby33-x64/lib/ruby/3.3.0/rubygems/installer.rb:852:in `build_extensions'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/rubygems_gem_installer.rb:76:in
`build_extensions'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/rubygems_gem_installer.rb:28:in
`install'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/source/rubygems.rb:205:in
`install'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/installer/gem_installer.rb:54:in
`install'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/installer/gem_installer.rb:16:in
`install_from_spec'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/installer/parallel_installer.rb:132:in
`do_install'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/installer/parallel_installer.rb:123:in
`block in worker_pool'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/worker.rb:62:in
`apply_func'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/worker.rb:57:in
`block in process_queue'
  <internal:kernel>:187:in `loop'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/worker.rb:54:in
`process_queue'
D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/bundler-2.5.6/lib/bundler/worker.rb:90:in
`block (2 levels) in create_threads'

An error occurred while installing psych (5.2.0), and Bundler cannot continue.
...

That’s not great! So, I ran into a new problem – one with installing psych. For some reason, in bundle install, it fails to build and install psych but that worked fine when I did a gem update on the command line, as recommended here for an earlier version.

$gem update
...
Updating psych
Installing required msys2 packages: mingw-w64-ucrt-x86_64-libyaml
Building native extensions. This could take a while...
Successfully installed psych-5.2.0
Parsing documentation for psych-5.2.0
Installing ri documentation for psych-5.2.0
Done installing documentation for psych after 1 seconds
Parsing documentation for psych-5.2.0
Done installing documentation for psych after 0 seconds
...

With that done, I decided to give it a shot again.

$ rails new hello8
      create
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
      create  .gitattributes
      create  Gemfile
         run  git init from "."
Initialized empty Git repository in D:/projects/blog/_posts-trials/rails/hello8/.git/
      create  app
      create  app/assets/stylesheets/application.css
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/jobs/application_job.rb
      create  app/mailers/application_mailer.rb
      create  app/models/application_record.rb
      create  app/views/layouts/application.html.erb
      create  app/views/layouts/mailer.html.erb
      create  app/views/layouts/mailer.text.erb
      create  app/views/pwa/manifest.json.erb
      create  app/views/pwa/service-worker.js
      create  app/assets/images
      create  app/assets/images/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/brakeman
      create  bin/dev
      create  bin/rails
      create  bin/rake
      create  bin/rubocop
      create  bin/setup
      create  bin/thrust
      create  Dockerfile
      create  .dockerignore
      create  bin/docker-entrypoint
      create  .rubocop.yml
      create  .github/workflows
      create  .github/workflows/ci.yml
      create  .github/dependabot.yml
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/cable.yml
      create  config/puma.rb
      create  config/storage.yml
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/assets.rb
      create  config/initializers/content_security_policy.rb
      create  config/initializers/cors.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/new_framework_defaults_8_0.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/master.key
      append  .gitignore
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  log
      create  log/.keep
      create  public
      create  public/400.html
      create  public/404.html
      create  public/406-unsupported-browser.html
      create  public/422.html
      create  public/500.html
      create  public/icon.png
      create  public/icon.svg
      create  public/robots.txt
      create  script
      create  script/.keep
      create  tmp
      create  tmp/.keep
      create  tmp/pids
      create  tmp/pids/.keep
      create  vendor
      create  vendor/.keep
      create  test/fixtures/files
      create  test/fixtures/files/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/test_helper.rb
      create  test/system
      create  test/system/.keep
      create  test/application_system_test_case.rb
      create  storage
      create  storage/.keep
      create  tmp/storage
      create  tmp/storage/.keep
      remove  config/initializers/cors.rb
      remove  config/initializers/new_framework_defaults_8_0.rb
         run  bundle install --quiet
WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
      stringio (>= 0)
      Available/installed versions of this gem:
      - 3.1.2
      - 3.1.0
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
         run  bundle lock --add-platform=x86_64-linux
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Writing lockfile to D:/projects/blog/_posts-trials/rails/hello8/Gemfile.lock
         run  bundle binstubs bundler
       rails  importmap:install
       apply  D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/importmap-rails-2.0.3/lib/install/install.rb
  Add Importmap include tags in application layout
      insert    app/views/layouts/application.html.erb
  Create application.js module as entrypoint
      create    app/javascript/application.js
  Use vendor/javascript for downloaded pins
      create    vendor/javascript
      create    vendor/javascript/.keep
  Configure importmap paths in config/importmap.rb
      create    config/importmap.rb
  Copying binstub
      create    bin/importmap
         run  bundle install --quiet
       rails  turbo:install stimulus:install
       apply  D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/turbo-rails-2.0.11/lib/install/turbo_with_importmap.rb
  Import Turbo
      append    app/javascript/application.js
  Pin Turbo
      append    config/importmap.rb
         run  bundle install --quiet
       apply  D:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/stimulus-rails-1.3.4/lib/install/stimulus_with_importmap.rb
  Create controllers directory
      create    app/javascript/controllers
      create    app/javascript/controllers/index.js
      create    app/javascript/controllers/application.js
      create    app/javascript/controllers/hello_controller.js
  Import Stimulus controllers
      append    app/javascript/application.js
  Pin Stimulus
  Appending: pin "@hotwired/stimulus", to: "stimulus.min.js"
      append    config/importmap.rb
  Appending: pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
      append    config/importmap.rb
  Pin all controllers
  Appending: pin_all_from "app/javascript/controllers", under: "controllers"
      append    config/importmap.rb
         run  bundle install --quiet
         run  bundle binstubs kamal
         run  bundle exec kamal init
Created configuration file in config/deploy.yml
Created .kamal/secrets file
Created sample hooks in .kamal/hooks
       force  .kamal/secrets
       force  config/deploy.yml
       rails  solid_cache:install solid_queue:install solid_cable:install
      create  config/cache.yml
      create  db/cache_schema.rb
        gsub  config/environments/production.rb
      create  config/queue.yml
      create  config/recurring.yml
      create  db/queue_schema.rb
      create  bin/jobs
        gsub  config/environments/production.rb
      create  db/cable_schema.rb
       force  config/cable.yml

This is a lot better – and it seems fine. This is where we see the one warning and comment. I will try this later after we see if things seem to be working.

WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
      stringio (>= 0)
      Available/installed versions of this gem:
      - 3.1.2
      - 3.1.0
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.

Now, move into that folder (hello8 in our case) and start the server by doing ruby bin\rails server in that directory. Remember to hit Ctrl-C to shut down the server once you’re done using it.

$ ruby bin\rails server

After this, you should be able to go to http://localhost:3000 and see the page below.

You can now continue with the Getting Started tutorial, and I did the following.

Continuing the Tutorial

Following the Rails Getting Started tutorial, I did the following:

  • Added the route
  • Added the controller
  • Updated the view

Let’s add the route get "/articles", to: "articles#index" into config/routes.rb as recommended in the tutorial

Now we go ahead and create the controller.

$ ruby bin\rails generate controller Articles index --skip-routes
      create  app/controllers/articles_controller.rb
      invoke  erb
      create    app/views/articles
      create    app/views/articles/index.html.erb
      invoke  test_unit
      create    test/controllers/articles_controller_test.rb
      invoke  helper
      create    app/helpers/articles_helper.rb
      invoke    test_unit

We also update the template in app/views/articles/index.html.erb and go to http://localhost:3000/articles and we are now greeted with this:

Next, we add the model.

$ ruby bin\rails generate model Article title:string body:text
      invoke  active_record
      create    db/migrate/20241116095243_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml

and run db:migrate as below:

$ ruby bin\rails db:migrate
== 20241116095243 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0050s
== 20241116095243 CreateArticles: migrated (0.0058s) ==========================

Also, we add two articles using rails/console:

hello8(dev)> article = Article.new(title: "Hello Rails", body: "I am on Rails!")
=> #<Article:0x0000022cd5cce418 id: nil, title: "Hello Rails", body: "I am on Rails!", created_at: nil, updated_at: nil>
hello8(dev)> article.save
hello8(dev)> article = Article.new(title: "Hello Ruby 3", body: "New Ruby brings more")
  TRANSACTION (0.3ms)  BEGIN immediate TRANSACTION /*application='Hello8'*/
  Article Create (3.0ms)  INSERT INTO "articles" ("title", "body", "created_at", "updated_at") VALUES ('Hello Rails', 'I am on Rails!', '2024-11-16 09:55:06.458798', '2024-11-16 09:55:06.458798') RETURNING "id" /*application='Hello8'*/
  TRANSACTION (12.5ms)  COMMIT TRANSACTION /*application='Hello8'*/
=> #<Article:0x0000022cd7131900 id: nil, title: "Hello Ruby 3", body: "New Ruby brings more", created_at: nil, updated_at: nil>
hello8(dev)> article.save
  TRANSACTION (0.1ms)  BEGIN immediate TRANSACTION /*application='Hello8'*/
  Article Create (0.5ms)  INSERT INTO "articles" ("title", "body", "created_at", "updated_at") VALUES ('Hello Ruby 3', 'New Ruby brings more', '2024-11-16 09:55:22.801409', '2024-11-16 09:55:22.801409') RETURNING "id" /*application='Hello8'*/
  TRANSACTION (0.1ms)  COMMIT TRANSACTION /*application='Hello8'*/
=> true

Now, as recommended, update the view template and the controller code. Finally, off to the http://localhost:3000/articles and you will see this.

We are ready for more! If you have any comments, please leave them below so that we can improve this page. Just remember that once you are running within your project, you need to do ruby bin\rails wherever other tutorials ask you to do bin\rails normally.

comments powered by Disqus