rubysinatrascheduled-tasksrufus-scheduler

Rufus scheduler in Sinatra


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?


Solution

  • 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 do
      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.