Custom gem not loading into rails app

Viewed 1970

I've pushed gem into github & rubygems, but constants of that gem are not being loaded into rails app. Tried this by loading from multiple sources and results are like this:

  • rubygems = not loaded
  • github = not loaded
  • local path = loaded

Interesting things is that when I load with rubygems/github I can load constants with require 'module/gem_name'

The gemspecs looks fine to me:

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'module/gem_name/version'

Gem::Specification.new do |spec|
  spec.name          = 'gem_name'
  spec.version       = Module::GemName::VERSION
  spec.authors       = ['Mike QWERTY']
  spec.email         = ['mike.qwerty@gamil.com']

  spec.summary       = 'some_desc'
  spec.homepage      = 'https://github.com/mike/gem-name'
  spec.license       = 'MIT'

  if spec.respond_to?(:metadata)
    spec.metadata['allowed_push_host'] = 'https://rubygems.org'
  else
    raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
  end

  spec.files = `git ls-files -z`.split("\x0").reject do |f|
    f.match(%r{^(test|spec|features)/})
  end
  spec.bindir        = 'exe'
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ['lib']
  spec.required_ruby_version = '>= 2.4.0'
  spec.add_runtime_dependency 'graphql', '>= 1.6.0'

  spec.add_development_dependency 'bundler', '~> 1.14'
  spec.add_development_dependency 'rake', '~> 10.0'
  spec.add_development_dependency 'rspec', '~> 3.0'
end

And structure is:

lib/module/gem_name/stuff/others.rb
lib/module/gem_name/extras.rb
lib/module/gem_name.rb

Also, I've been working on this gem basing on other gem that has the same module name. But it loads correctly into app, if this matters. Any ideas on this?

1 Answers

The gem is not autoloading because the main file (gem_name.rb) is not at the root of the lib directory. It is recommended that your Gem adhere to the following structure:

% tree
.
├── gem_name.gemspec
└── lib
    ├── gem_name
    │   └── some_file.rb
    │   └── other_file.rb
    └── gem_name.rb

Yours has an extra module nesting. In your Rails application.rb you should see Bundler.require(*Rails.groups). What this method does is loop through every Gem in your Gemfile and call require gem_name. This works for Gem's that follow the convention mentioned above. Your gem does not - so the auto require being done by Bundler doesn't find the correct file to use.

See the Ruby Gems Guide for creating your own Gem for a bit more information on proper code organization.

If you don't want to change the structure of your application, either add require "module/gem_name" in an initializer, or within the Gemfile:

gem "gem_name", require: "module/gem_name"
Related