Gems, Plugins, Engines, and Mountable Engines: 4 ways to make a Gem.


Every time I go to make a new ruby gem, I need to look up the specific way to get started. Here’s a summary of the different options.

Ruby Gem

bundle gem <name>

When to use it

Your gem can be used outside of Rails.

Why it’s a good fit
  • Does not put any rails dependencies in the gemspec
  • Gem code lives in lib/ and must be explicitly required

https://bundler.io/guides/creating_gem.html

Rails Plugin

rails plugin new <name>

When to use it

Your gem is intended to be used by a Rails application as model-level code. You want to be able to test your gem as if it were running in a rails app.

Why it’s a good fit
  • Puts rails dependencies in the gemspec
  • Provides a simple rails application for testing in test/dummy
  • Provides a railtie for integrating with rails internals or running code at application startup
  • Gem code lives in lib/ and must be explicitly required

https://guides.rubyonrails.org/plugins.html

Rails Engine

rails plugin new <name> --full

When to use it

Your gem includes models, views, controllers, helpers, assets, etc that you want to make available to a rails app as if that code were written directly in the application. You want to allow the application to override your gem’s files.

Why it’s a good fit
  • Puts rails dependencies in the gemspec
  • Provides a simple rails application for testing in test/dummy
  • Provides an app/ folder with the standard rails subfolders (models, controllers, etc). Code in this folder will be autoloaded just like it were written directly in the including application
  • If the including rails application and your gem have files at the same path within the app/ folder, the including application’s file will take precedence (handy for local customization)
  • You can still write code in lib/ and explicitly require it

https://guides.rubyonrails.org/engines.html

Rails Mountable Engine

rails plugin new <name> --mountable

When to use it

Your gem is a complete rails application that other applications can include and mount at the route of their choosing. You want to avoid name collisions with the including rails app.

Why it’s a good fit
  • Puts rails dependencies in the gemspec
  • Provides a simple rails application for testing in test/dummy
  • Includes an app/ folder with the standard rails subfolders (models, controllers, etc) where you can write your engine’s application code
  • Includes files needed for a standalone mini-application (routes, ApplicationController/Helper, asset manifests)
  • Sets up namespace isolation so gem routes, assets, and base classes don’t conflict with the including applications’
  • You can still write code in lib/ and explicitly require it

https://guides.rubyonrails.org/engines.html