best/most elegant way to share objects between a s

2020-06-16 18:13发布

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

1条回答
够拽才男人
2楼-- · 2020-06-16 18:39

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.

查看更多
登录 后发表回答