How do I make functions in a gem available to Sinatra views?

The question here asks how to extract Rails view helper functions into a gem, and the accept answer is pretty good.

I am wondering - how to do the same for Sinatra? I'm making a gem that has a bunch of helper functions defined in a module, and I'd like to make these functions available to Sinatra views. But whatever I try, I cannot seem to access the functions, I just get a undefined local variable or method error.

So far, my gem structure looks like this (other stuff like gemspec omitted):

cool_gem/
  lib/
    cool_gem/
      helper_functions.rb
      sinatra.rb 
  cool_gem.rb

In cool_gem.rb, I have:

if defined?(Sinatra) and Sinatra.respond_to? :register
  require 'cool_gem/sinatra'
end

In helper_functions.rb, I have:

module CoolGem
  module HelperFunctions

    def heading_tag(text)
      "<h1>#{text}</h1>"
    end

    # + many more functions
  end
end

In sinatra.rb, I have:

require 'cool_gem/helper_functions'

module CoolGem
  module Sinatra

    module MyHelpers
      include CoolGem::HelperFunctions
    end

    def self.registered(app)
      app.helpers MyHelpers
    end

  end
end

This doesn't work. Where am I going wrong?

(And in case you're wondering, yes, I need the helper functions in a separate file. I plan to make the gem compatible with Rails as well, so I want to keep the functions isolated/de-coupled if possible).

Upvotes: 1

Views: 500

Answers (1)

matt
matt

Reputation: 79733

You’re mainly just missing the call to Sinatra.register (in cool_gem/sinatra.rb):

require 'sinatra/base'
require 'cool_gem/helper_functions'

module CoolGem
  # you could just put this directly in the CoolGem module if you wanted,
  # rather than have a Sinatra sub-module
  module Sinatra

    def self.registered(app)
      #no need to create another module here
      app.helpers CoolGem::HelperFunctions
    end

  end
end

# this is what you're missing:
Sinatra.register CoolGem::Sinatra

Now any classic style Sinatra app that requires cool_gem will have the helpers available. If you use the modular style you’ll also need to call register CoolGem::Sinatra inside the Sinatra::Base subclass.

In this case, if you are just providing some helper methods, an easier way might be to just use the helpers method (again in cool_gem/sinatra.rb):

require 'sinatra/base'
require 'cool_gem/helper_functions'

Sinatra.helpers CoolGem::HelperFunctions

Now the methods will be available in classic style apps, and modular style apps will need to call helpers CoolGem::HelperFunctions. This is a bit simpler, but if you are adding methods to the DSL context you will need to use registered as above.

Upvotes: 2

Related Questions