3

I'm using Rufus scheduler in a Sinatra app. Can I access helper methods from within "scheduler do" block? I didn't manage to do it (I get an "undefined method `check' for main:Object" error) so now I have to define the method inside helpers block (to use it in "post '/' do" block also) and then copy the method's body to scheduler block. It does not make sense:( Is there a way to avoid repetition? Can I define a method somewhere else and call it in scheduler?

hiirulainen
  • 107
  • 2
  • 8

2 Answers2

5

It depends where your scheduler is being used. A block will have access to the context local to it, so if you're using it somewhere you have access to a helper, then it should also have access to the helper.

Taken in part from the docs

class MyApp < Sinatra::Base
  # Hey, I'm in the application scope!

  helpers do
    def my_helper
    end
  end

  configure do
    scheduler.every('20s') do
      # my_helper is ***not*** accessible here
    end
  end

  get '/define_route/:name' do
    # Request scope for '/define_route/:name'
    scheduler.every('20s') do
      my_helper
      # my_helper is accessible here
    end
  end
end

Having said that, you wouldn't have access to the scheduler like that, so:

configure do
  set :scheduler, { Rufus::Scheduler.start_new }
end

and then you can do

  get '/define_route/:name' do
    # Request scope for '/define_route/:name'
    settings.scheduler.every('20s') do
      my_helper
      # my_helper is accessible here
    end
  end

or you could put it in a module's class instance variable:

module MyScheduler
  def self.scheduler
    @scheduler ||= Rufus::Scheduler.start_new
  end
end

then you can access the scheduler everywhere via:

MyScheduler.scheduler

but the my_helper would still only be accessible in the request scope. If you wanted to access a method as a helper and outside the request scope, then extract it as jmettraux implied to:

module MyHelpers
  def self.my_helper
    # do something
  end
end

in Sinatra:

helpers
  def my_helper
    MyHelpers.my_helper
  end
end

then can do:

configure do
  scheduler = Rufus::Scheduler.start_new
  set :scheduler, scheduler
  scheduler.every('20s') do
    MyHelpers.my_helper
    # my_helper is not accessible here
    # but the MyHelpers.my_helper is, because it's accessible everywhere
  end
end

# and/or

get "another-route" do
  setting.scheduler.every('20s') do
    my_helper
    # my_helper is accessible here
  end
end

All very convoluted! You can mix and match and find what works for your needs.

ian
  • 12,003
  • 9
  • 51
  • 107
2

I was looking at http://japhr.blogspot.jp/2009/03/sinatra-innards-deletgator.html

You could probably do something like:

# in a.rb

module A
  class << self; include A; end
  def nada
    puts "nada"
  end
end

# in another file...

require 'sinatra'

helpers do
  include A
end

scheduler.every('20s') do
  A.nada
end
jmettraux
  • 3,511
  • 3
  • 31
  • 30
  • You don't need to use `include`, you can just write `helpers A` or `helpers Namespace::To::My::Special::Module` – ian Jan 31 '13 at 15:37
  • …and just to say, it should be `nada` not `A.nada` as `helpers` includes the instance methods of a module, and `nada` is not a class method. If you were going to use `A.nada` just define it in your module as `self.nada`, there'd be no need to add it to the helpers. – ian Jan 31 '13 at 15:43
  • 1
    Thanks @iain, my solution was indeed not standing on its own. I had forgotten the "class << self; include A; end". Thanks for the "helpers Module", I didn't know Sinatra could do that. – jmettraux Jan 31 '13 at 21:26