Search code examples
ruby-on-railsrubyrubygemssinatra

Create Ruby Gem from Rails classes to use in Sinatra


I'm trying to extract several classes from a Rails app into its own Gem so that I can reuse the code from a Sinatra app.

In the Rails app I have the following structure:

app > classes > api > (bunch of folders and subfiles)

I'm trying to move the api folder into a gem, for that I created a new gem using bundler:

bundle gem myapp-core --no-exe --no-coc --no-mit --no-ext

so I ended up with a file structure like:

myapp-core > lib > myapp > core > version.rb
myapp-core > lib > myapp > core.rb

I've copied the api folder to myapp-core > lib > myapp > api and tried to require it from sinatra doing:

require 'myapp/api/somefile.rb'

but that didn't work, I have of course added the gem to the Gemfile of the sinatra app. I tried all kinds of combinations of where to put the folder and how to require the files in it but I either get cannot load such file or uninitialized constant Api (NameError).

What is the correct way to go about this so that ideally from both Sinatra and Rails I would just add the gem to the Gemfile, require whatever file I need and the code that uses those API files would remain unchanged or change as little as possible?


Solution

  • Without the Rails auto-loader you'll need to establish all the intermediate class and module components yourself.

    This usually means you need to either declare things like:

    module Api
      class Somefile
        # ...
      end
    end
    

    Where that Api module is automatically declared, allowing you to require lib/api/somefile directly, or you need to shift this responsibility up the chain:

    # lib/api.rb
    module Api
      # ...
    end
    
    require_relative './api/somefile'
    

    Where that automatically loads in any dependencies and you now do require 'api' instead, presuming your $LOAD_PATH includes this particular lib/ path.