0

Have you had success refactoring your Sinatra Apps in this way?:

before

require 'sinatra/base'

class UserApp < Sinatra::Base
  get '/' do
    content_type :json
    User.all.to_json
  end

  get '/:id' do |id|
    content_type :json
    User.find(id).to_json
  end

  # etc, etc.  (there are many routes)
end

after?

require 'sinatra/base'
require 'user_routes'

class UserApp < Sinatra::Base
  register UserRoutes
end

# ----- a separate file -----
module UserRoutes
  def list
    content_type :json
    User.all.to_json
  end

  def find(id)
    content_type :json
    User.find(id).to_json
  end

  def self.registered(app)
    app.get '/', &UserRoutes.list # <-- this is the piece I cannot figure out
    app.get '/:id', &UserRoutes.find # <-- this is the piece I cannot figure out

    # etc, etc.  (there are many routes)
  end
end

I cannot seem to figure out how to pass the UserModule's methods to app.get in such a way that those methods are called with the same scope as simply passing a block (e.g., how can those methods have access to content_type and other Sinatra features).


ruby 2.0.0

this is a very simplified version of the problem

Pat Newell
  • 2,219
  • 2
  • 18
  • 23

1 Answers1

1

First of all, to be able to call module methods with Module.method idiom you should declare them module-wide:

module UserRoutes
  #   ⇓⇓⇓⇓⇓
  def self.list
    content_type :json
    User.all.to_json
  end
  ...
end

Now you could:

app.get '/', &proc{ |_, *args| UserRoutes.send(:list, *args) }

Please be aware, that results in performance penalties.

Further reading.

Community
  • 1
  • 1
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • yikes... thanks a lot for the response @mudasobwa. This seems less than ideal and it's not the end of the world if I can't refactor that code. Thanks again – Pat Newell Feb 13 '15 at 18:00