Skip to content

Instantly share code, notes, and snippets.

@paneq
Created February 7, 2012 23:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save paneq/1763038 to your computer and use it in GitHub Desktop.
Save paneq/1763038 to your computer and use it in GitHub Desktop.
bbq factories
class SessionFactory
def next(options)
Capybara::Session.new(options[:driver], Bbq.app)
end
end
class PooledSessionFactory
attr_accessor :idle, :taken
def initialize(session_factory)
@idle = []
@taken = []
end
def next(options)
take_idle(options) || create(options)
end
def release
taken.each(&:reset!)
idle.concat(taken)
taken.clear
end
private
def take_idle(options)
driver = options[:driver]
idle.find { |s| s.mode == driver }.tap do |session|
if session
idle.delete(session)
taken.push(session)
end
end
end
def create(options)
session_factory.create(options)
end
end
class NonPooledSessionFactory
attr_accessor :taken
def initialize(session_factory)
@taken = []
end
def next(options)
taken << session = session_factory.create(options)
session
end
def release
@taken.select{|u| u.mode == :selenium}.each do |u|
u.page.driver.quit if u.page.driver.browser? # http://img98.imageshack.us/img98/8158/lawglupcze.png
end
end
end
class SelectablePoolSessionFactory
def initialize(default_pool_session_factory, non_pool_session_factory)
end
def next(options)
if options.key?(:pool) && options[:pool].blank?
non_pool_session_factory.next(options)
else
default_pool_session_factory.next(options)
end
end
end
module SessionFactoryAware
def new(options)
sf = options[:sessions_factory] || session_factory
options[:session] ||= sf.next(options) if sf
super(options)
end
end
# Recommended way ?
class TestUserFactory
def initialize(session_factory)
end
include(Module.new{ def new; TestUser.new(options); end })
include SessionFactoryAware
end
sf = SessionFactory.new
psf = PooledSessionFactory.new(sf)
nsf = NonPooledSessionFactory.new(sf)
spsf = SelectablePoolSessionFactory.new(psf, nsf)
tuf = TestUserFactory.new(TestUser, spsf)
tuf.next()
tuf.next(:pool => true)
tuf.next(:pool => false)
tuf.next(:pool => nil)
# want different pool ?
tuf2 = TestUserFactory.new(PooledSessionFactory.new(sf))
tuf2.next
#or
psf2 = PooledSessionFactory.new(sf)
TestUser.new(:session => psf2.next)
# or
psf2 = PooledSessionFactory.new(sf)
tuf.next(:sessions_factory => psf2)
#####
class TestUser
# Keep TestUser as a factory that is aware of session
# to maintain backwards compatibility with sessions pool feature
# for those who use TestUser.new syntax or inherit from TestUser
extend(SessionFactoryAware)
class_attribute :session_factory
self.session_factory = nil
def initialize(options)
end
end
#####
# somewhere else set TestUser fields so that its behavior is backwards compatible
sf = SessionFactory.new
psf = PooledSessionFactory.new(sf)
nsf = NonPooledSessionFactory.new(sf)
spsf = SelectablePoolSessionFactory.new(psf, nsf)
TestUser.session_factory = spsf
## TODO: Change next to new (or call?) so that it can be called directly on classes when there is not need to overcomplicate things
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment