Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

best/most elegant way to share objects between a stack of rack mounted apps/middlewares?

Tags:

ruby

sinatra

rack

What is the best idiom to share an object between rack mounted applications/middlewares?

For example, this config.ru has two Sinatra apps mapped to differents endpoints:

class App1 < Sinatra::Base
  # ...
end

class App2 < Sinatra::Base
  # ...
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

Now if these two applications need to share an object, be it a database connector or any other object, what would be the best idiom for this?

I see basically two options:

1- Create a constant at the config.ru level and simply refer to that constant within the apps. For example:

SHARED_OBJECT = "hello world"

class App1 < Sinatra::Base
  get '/' do
    SHARED_OBJECT
  end
end

class App2 < Sinatra::Base
  get '/' do
    SHARED_OBJECT
  end
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

2- Create a singleton object at the config.ru level and use it within the apps. For example:

class SharedObject
  include Singleton

  def test
    @test ||= "hello world"
  end
end

class App1 < Sinatra::Base
  get '/' do
    SharedObject.instance.test
  end
end

class App2 < Sinatra::Base
  get '/' do
    SharedObject.instance.test
  end
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

Comments/suggestions?
Colin

like image 645
Colin Surprenant Avatar asked Apr 01 '11 19:04

Colin Surprenant


1 Answers

I would move the shared object into a separate file and namespace it. If it were a database connection object, it might look like this:

# config.ru:
require 'lib/my_app/database'
...
class App1 < Sinatra::Base
  get '/' do
    MyApp::Database.with_connection do |conn|
      ...
    end
  end
end

# lib/my_app/database:
module MyApp
  module Database
    def self.with_connection(&block)
      ...
    end
  end
end

I see this as having several benefits:

  1. it reduces the size of your config.ru file, improving readability
  2. it separates concerns -- config.ru is about Rack applications; lib/my_app/database.rb is about databases
  3. it makes it easier to extract. At some point down the line, you might want to separate App1 and App2 into separate projects and include the database connectivity as a gem. This is easy when the database code is in its own module and file.

Phrogz's comment about constants being enough and not needing singletons is wise.

like image 71
James A. Rosen Avatar answered Oct 20 '22 13:10

James A. Rosen