I recently attended a conference where one of the speakers asked the audience if they knew the difference between gems and engines. I was very surprised to see that nobody knew the difference! Well except me, thanks to my work with engines in modular applications and the work I did for my book Modular Rails.
So let me ask you, do you know the difference between gems and engines? If you do, this article might be uninteresting for you. If you don’t, you should really read what follows because understanding the difference between them is really important, especially if you’re planning on creating your own libraries.
What’s a gem?
Gem is just a fancy term for a packaged Ruby library. A library is just a bit of code providing a set of functionalities to anyone who integrates it in its code.
The only thing you need to know to understand the difference with an engine is that a gem is pure Ruby code.
What defines a gem:
- Gemspec
- Lib folder
- Can be packaged and pushed to rubygems servers
- Can be used in any project simply by referencing the name (once pushed to Rubygems servers)
Creating a gem
Creating a gem is pretty easy. All you need actually is a lib
folder containing a file named my_gem.rb
and a my_gem.gemspec
file. Once you have this, you can use gem build my_gem.gemspec
to build the packaged gem. This package can then be published to rubygems servers or installed locally with gem install my_gem-x.x.x.gem
. Finally, if you want to publish your gem publicly on rubygems servers, you can use gem push my_gem-x.x.x.gem
.
Once pushed to public servers, you can easily install it with gem install my_gem
.
Note that you can also use Bundler to generate a gem with a nice file architecture by using bundle gem my_gem
. The steps to package and install are the same than above.
Now let’s talk about engines.
What’s an engine?
Engines are actually gems. All engines can be gems (if packaged) but not all gems are engines.
Engines are a Ruby on Rails feature. That’s where the difference lies. They are meant to work within a Ruby on Rails application which means that they can contains Rails-specific entities: models, controllers, views, migrations and so on.
They are basically minimalist Ruby on Rails applications that can’t run on their own: they need to be integrated inside an existing Ruby on Rails application to work.
What defines an Engine:
- Gemspec
- Rails entities: models, controllers, views, migrations, initializers, …
- Can be packaged and pushed to rubygems servers
- Can only be used in Ruby on Rails applications
Creating an engine
Engines can be created with the following command:
$ rails plugin new my_engine --mountable
or
$ rails plugin new my_engine --full
To package and install an engine, you can use the same commands than for gems.
Building:
gem build my_engine.gemspec
Installing in local:
gem install my_engine-x.x.x.gem
Pushing to rubygems servers:
gem push my_engine-x.x.x.gem
Mountable vs Full
There are two options when creating an engine: mountable and full. Mountable means that you will mount your engine inside your Ruby on Rails application at a specific path, like /my_engine
for example. It comes with folders for assets and controllers. A ‘full’ engine however is not meant to be mounted inside an application and is more there to provide new entities to an existing Ruby on Rails application. It won’t be encapsulated with namespacing and will just be an extension of the main application. Note that even after the creation, a full engine can easily be changed to be mountable vice versa.
Wrap Up
Gems are pure Ruby libraries while engines can contain Ruby on Rails features. Engines can still be packaged as regular gems though but will only work inside a Rails application.