1

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).

Community
  • 1
  • 1
XåpplI'-I0llwlg'I -
  • 21,649
  • 28
  • 102
  • 151

1 Answers1

2

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.

matt
  • 78,533
  • 8
  • 163
  • 197
  • Thanks. But I found that I did not need `require 'sinatra/base` in `sinatra.rb`, nor did I need `Sinatra.register CoolGem::Sinatra`. Just adding `register CoolGem::Sinatra` to my application's class seems to be all that was needed... – XåpplI'-I0llwlg'I - Jul 12 '13 at 13:07
  • @XåpplI'-I0llwlg'I- Yes, if you have already required sinatra (e.g. in your main app) you won’t need to again. Also `Sinatra.register CoolGem::Sinatra` will make the extensions available in classic Sinatra apps. If you are using modular style you’ll need to use `register` in your apps class as well. If you are making the gem available you might want to include `Sinatra.register CoolGem::Sinatra` so that it will work as expected for people using the classic style. – matt Jul 12 '13 at 16:13