skip to Main Content

I’m moving my first steps into Rails world. I’m developing inside a container, where I have ruby interpreter working.

The official documentation say that I need to gem install rails and then create a new project. The new project has bin/rails too, exact same version of my "global" rails executable. This is confusing.

I guess the rails is only needed to scaffold a new project, right? If so, can I install rails in a way that I don’t need the "global" rails gem? Like a skeleton Github repository?

Example: in the PHP word usually you just need a composer.json file (= Gemfile) and do a composer install (bundle install) for a given framwork in order to get a skeleton where you can work on, including the usual executable files, installed locally.

2

Answers


  1. When you run rails you’re running the latest version that you have currently installed. You can have multiple gem versions installed at the same time, for example this is what I have currently for rails (for one of my ruby versions):

    $ gem list | ag "^railss"
    rails (7.1.0, 7.0.4.3, 7.0.4.2, 7.0.4.1, 6.1.7.6, 6.1.7.3, 6.1.7, 6.1.6, 6.1.5, 6.1.4.6, 6.1.4.1, 6.1.4, 6.1.0.rc1, 6.0.6.1, 6.0.3.4, 6.0.0, 5.2.8.1, 5.0.7.2, 4.2.11.3)
    

    Running rails gives me the latest version currently installed:

    $ rails -v
    Rails 7.1.0
    

    If I have a project from a few years back it would need to use rails v5.2.8.1. bin/rails ensures that you’re using the correct version of rails for that project.

    $ cd ~/code/SO/rails_five 
    $ bin/rails -v
    Rails 5.2.8.1
    
    # depending on your shell config (rbenv), this does automagically work (although, super slow for some reason)
    $ rails -v
    Rails 5.2.8.1
    

    bin/rails – is equivalent to bundle exec rails and it is there to ensure everyone using your project uses the correct version of rails, including yourself a few years later. Global versions change all the time.

    If you do have a million rails versions there is special syntax to specify the version you want to use for a new project:

    $ rails _5.2.8.1_ new rails_five 
    

    usually you just need a composer.json file (= Gemfile)

    Being an outsider to php, am I supposed to know what goes into "composer.json" before I start my project? You can totally create a directory and create a Gemfile with some gems and run bundle install – now what? Rails project has quite the structure that gets generated by rails new – you don’t want to do all that manually and bundle install only installs gems (aka downloads them), it doesn’t generate the project structure, if that makes sense.

    For rails you do this:

    gem install rails
    rails new my_project
    cd my_project
    # use bin/rails from now on for years to come
    

    https://bundler.io/v2.4/man/bundle-binstubs.1.html

    Login or Signup to reply.
  2. bin/rails is simply a bin stub. Binstubs are wrapper scripts around executables whose purpose is to prepare the environment before dispatching the call to the original executable.

    The binstubs generated by rails just look like:

    #!/usr/bin/env ruby
    APP_PATH = File.expand_path("../config/application", __dir__)
    require_relative "../config/boot"
    require "rails/commands"
    

    And config/boot.rb just uses Bundler to resolve the correct dependencies from the Gemfile:

    ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
    
    require "bundler/setup" # Set up gems listed in the Gemfile.
    require "bootsnap/setup" # Speed up boot time by caching expensive operations.
    

    rails/commands is Rails CLI interface.

    This ensures that even if you call the binstub from outside of the project directory it will still work the same way.

    If so, can I install rails in a way that I don’t need the "global" rails gem?

    You can. But there is very little point in doing so and you have better stuff to worry about.

    If you generate a Gemfile and install the gems with Bundler normally they will be installed in the gem path (the location varies depending on how Ruby is installed/configured). This is exactly the same as if you ran gem install rails. Bundler merely makes the job of dependency resolution easier as it will try to find versions that do not conflict with the other other gems in the gemfile.

    While you can configure bundler to instead install the gems into a folder in the project that’s not commonly done. In Ruby it’s quite normal with gems that are invoked without Bundler such as CLI tools.

    Unlike with PHP you can simply invoke the correct version of a package (if needed) with underscores. In a container this matters even less as you won’t have multiple versions laying about.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search