Difference among ruby gems, npm packages, and yarn - ruby-on-rails

When I start a new Rails project, it gives me a template with a few different files for packages: Gemfile, package.json, and yarn.lock. I'm trying to understand if all three of these packages work together, or if I'm supposed to choose one. For example, in my Gemfile, I can add 'jquery-rails' but is this the same as installing jQuery to my package.json file? I'm having trouble understanding the difference between running bundle install and npm install.
Thanks.

In short it looks like this:
In Ruby, the bundler analyzes the list of libraries (gems) specified in the Gemfile, builds a dependency tree and fixes it in Gemfile.lock, downloads gems from different sources
In JS, various managers do the same: npm, yarn, bower, etc. By default Rails use yarn. They download all libraries to node_modules folder
package.json is analogue of Gemfile (but more advanced, for example you can define command line scripts there). yarn.lock is analogue of Gemfile.lock
Thus, bundler for Ruby and yarn / npm for JS libraries

Gemfile is to manage ruby gems, while package.json and yarn.lock for js packages.
The good thing about installing jQuery via jquery-rails is that will allow you to easily integrate jQuery into a Rails project, regardless what asset manager you're using it.
On the other hand, installing jQuery using npm/yarn allows you to upgrade the package directly from the original repo, without having an intermediary (jquery-rails in this case) that eventually could have the gem unattended (as now that they're using jquery 3.6.0 while the last one is 3.6.1).
Personally, I'd choose the 2nd option, mostly because in general is a good practice to have these js/ruby worlds working separately, but the other reason is because any other js library you eventually will need it, probably will follow the same steps as installing jQuery, so it's not really a big deal integrating it with Rails in this way.

Related

How to add additional gems inside a RubyGem package?

I am going through the documentation at http://guides.rubygems.org/ to learn about RubyGems.
My goal is to package a Ruby application (no executables) which depends on some other Gems (for example, say, Rails!).
I am not a Ruby expert so I am confused and have the following two questions:
How can I add the Gem inside the package to be shipped with my app?
Should I instead not add the gem inside but create dependencies list, which is to be executed upon installation of my gem?
What is the right way to ship dependencies with my gem?
Thanks!
Each gem has a gemspec file where the dependencies are specified. Use bundle to install the gem and it will also install the dependencies.

Does bundle package install gems globally

I used to have a new ruby installation for each new rails project, because it's impossible not to have conflicting gems with between two of them.
I have seen that 'bundle package' command could freeze a project specific set of gems in the 'vendr/cache' directory.
I though it wouldn't install them globally, just store them in that directory.
However, when i did it, 'bundle package' ended up installing (globally) the gems before storing them in 'vendor/cache' folder.
Did I do something wrong? Is it a bug?
From the Bundler docs:
The package command will copy the .gem files for your gems in the bundle into ./vendor/cache.
As far as I can tell, Bundler does not handle installing gems, it passes that off to the gem command. What Bundler does is to make sure that you have the right version of the gem activated. So even when you package the gems, when you later install them it'll take those gems and install them "globally".
So, to answer your question: No, you didn't do anything wrong and this is not a bug but the intended behaviour.

When creating a new Rails application, why is there a Gemfile.lock file without running bundle install?

And, how does the system install all the gems for the application without going through the bundle install process?
Note: This question is about the process of creating a new application. Not the same question as In Rails, why there is a new Gemfile.lock when no bundle or bundle install was run? (and a new Gemfile timestamp too) .
Gemfile.lock is a snapshot of the gems and their versions created when you run bundle install. As explained in the Checking Your Code into Version Control section of the Bundler rationale:
Gemfile.lock makes your application a single package of both your own
code and the third-party code it ran the last time so you know for sure
that everything worked. Specifying exact versions of the third-party
code you depend on in your Gemfile would not provide the same
guarantee, because gems usually declare a range of versions for their
dependencies.
Gems can be installed outside of bundler by RubyGems (e.g. gem install gem_name) but it's best to use RVM which allows you to install separate versions of Ruby and manage individual gemsets for each application as explained in the RVM best practices.
When you do rails new <app>, as part of setup it runs bundle install for you.

What is the difference between Gemfile and Gemfile.lock in Ruby on Rails

I am a beginner to Ruby on Rails and I am using Rails 3.0.9.
What is the difference between Gemfile and Gemfile.lock in Rails?
The Gemfile is where you specify which gems you want to use, and lets you specify which versions.
The Gemfile.lock file is where Bundler records the exact versions that were installed. This way, when the same library/project is loaded on another machine, running bundle install will look at the Gemfile.lock and install the exact same versions, rather than just using the Gemfile and installing the most recent versions. (Running different versions on different machines could lead to broken tests, etc.) You shouldn't ever have to directly edit the lock file.
Check out Bundler's Purpose and Rationale, specifically the Checking Your Code into Version Control section.
Usually we write dependencies in Gemfile as:
gem "nokogiri", "~> 1.4.4"
gem 'bcrypt-ruby', '~> 3.0.0'
gem 'uglifier', '>= 1.2.3'
..
Here you basically say: "I want nokogiri as long as it’s greater than version 1.4.4", etc. Now suppose that I have set up my Gemfile 8 months ago and I successful setup my app with this requirement. 8 months ago nokogiri version was 1.4.4. My rails apps was running perfectly without any problems with this version.
Now think I'm trying to build with the same Gemfile. But if we look at nokogiri versions we see that the current stable version has changed to 1.4.9. That means if we try to build, bundler will install version 1.4.9 of nokogiri (suppose we don't have Gemfile.lock).
What does it mean ?
As you see if you don't have any Gemfile.lock and run:
bundle install
then the currently used gems can be different at any time. Your app used the version 1.4.4 and it works 8 months ago without any problems, but if you try to build it now you get the version 1.4.9. Maybe it's broken with the latest version of nokogiri, the awesome feature you used with 1.4.4 is not more available, etc..
To prevent this kind of problem Gemfile.lock is used. In Gemfile.lock only the exact versions are written and thus only these will be installed. That means if you distribute your app with a Gemfile.lock, every machine will have the same gems installed and most important they all get the same version. This will give you a stable and common deployment stack.
How is Gemfile.lock created?
It is automatically created with the first:
bundle install
command. After that everytime you run bundle install, bundle will first look up Gemfile.lock and install the gems specified there. It's an habit to distribute this file among your projects to provide consistently and stability.
How to update Gemfile.lock?
If you're happy with the the latest version of your apps than you can update Gemfile.lock. Just reflect your changes to Gemfile. That means change the dependencies to the new exact versions in Gemfile. After that run:
bundle install
This will update you Gemfile.lock with your newest version of apps.
The Gemfile.lock
When you run bundle install, Bundler will persist the full names and versions of all gems that you used (including dependencies of the gems specified in the Gemfile(5)) into a file called Gemfile.lock.
Bundler uses this file in all subsequent calls to bundle install, which guarantees that you always use the same exact code, even as your application moves across machines.
Because of the way dependency resolution works, even a seemingly small change (for instance, an update to a point-release of a dependency of a gem in your Gemfile(5)) can result in radically different gems being needed to satisfy all dependencies.
As a result, you SHOULD check your Gemfile.lock into version control. If you do not, every machine that checks out your repository (including your production server) will resolve all dependencies again, which will result in different versions of third-party code being used if any of the gems in the Gemfile(5) or any of their dependencies have been updated.

how does gem installation works ? how did gem get the installation files?

when I wanted to install SASS, I have been told to install ruby on my machine, ok fine.
then all I had to do is to run the following code
gem install sass
and now I am done, and I have SASS installed
my question is in general..
How did gem knows what SASS is, and from where did it get it ?
It is a cool thing but I just want to know what happened behind the scenes ?
Thanks
RubyGems is a package manager like many others. It depends on a central repository to host installable packages. The command line tool fetches these packages from the central repository and installs them.
See RubyGems FAQ and Introduction.

Resources