class Bezel
The idea of Bezel
is to overcome the limitations of using different versions of the same package in the same Ruby proccess.
It works like this. Let’s say I wrote a library called TomsLib. Now I want to use TomsLib in my new fancy app, FancyApp. In my FancyApp namespace I have to create a reference to TomsLib.
module FancyApp TomsLib = lib('tomslib', '1.5') ...
Now I have access to TomsLib, but it is localized to my application. If Jane comes along and wants to use a different version of TomsLib but also utilizes my FancyApp, she could do so:
module JanesProgram TomsLib = lib('tomslib', '1.0') FancyApp = lib('fancyapp') # use newest available ...
How does this work? When you call lib(), Bezel
looks for the package in the current gem paths (and, in the future, Roll ledger) then it reads the bezel file (e.g. lib/tomslib.rbz) from the package and evals it into an anonymous module.
This has a some important effects on how you write your Ruby programs:
-
Any reference to core/standard libraries must be referenced via toplevel ‘::` prefix (eg. ::Enumerable).
-
Core extensions are not version controlled. So avoid them when possible, or depend on highly stable standardized bases such as Facets and ActiveSupport.
-
Since
Bezel
is a completely different alternative to Ruby’s normal load system, your program will requireBezel
be installed by your users.
Despite these necessary practices for its use, Bezel
is highly advantageous to developers and end-users alike in that it puts an end to the dreaded Dependency Hell.
TODO: Consider how best to support alternate loadpaths beyond ‘lib/’.
Constants
- SCRIPT
Script cache.
- STACK
Load stack keeps track of what modules are in the process of being loaded.
- TABLE
Cache of loaded modules. This speeds things up if two libraries load the same third library.
Public Class Methods
When in development mode, Bezel
uses the latest and greatest available version regardless of version settings.
# File lib/bezel.rb, line 63 def self.development=(boolean) @development = !!boolean end
# File lib/bezel.rb, line 68 def self.development? @development end
Load library into a module namespace.
# File lib/bezel.rb, line 73 def self.lib(name, version=nil) version = nil if development? ##path = find(name, version) ##raise LoadError, "#{name}-#{version} not found" unless path ## location of main requirement file ## TODO: should we require a dedicated bezel file instead? e.g. `*.rbz`. #main = File.join(path, 'lib', name + '.rb') #.rbz #TODO: LOADPATH main = Find.feature(name, :from=>name, :version=>version, :absolute=>true).first ## check cache return TABLE[main] if TABLE.key?(main) ## load error if no bezel file raise LoadError, "#{name}-#{version} has no bezel!" unless main && File.exist?(main) ## read in bezel file #script = File.read(main) ## create new Bezel module for file mod = new(name, version) #, main) ## put module on STACK STACK.push mod ## evaluate script in the context of module #mod.module_eval(script, main, 0) # r = mod.__load_feature__(main) ## pop module off STACK STACK.pop ## add module to cache, and return module TABLE[main] = mod end
Construct new Bezel
module.
# File lib/bezel.rb, line 130 def initialize(name, version) #, path) @__name__ = name @__version__ = version #@__path__ = path @__features__ = [] super() end
# File lib/bezel.rb, line 111 def self.require(path) if current = STACK.last begin current.__load_feature__(path) ? true : false rescue LoadError require_without_bezel(path) end else require_without_bezel(path) end end
Public Instance Methods
# File lib/bezel.rb, line 154 def __features__ @__features__ end
# File lib/bezel.rb, line 159 def __load_feature__(path) if path =~ /^[\.\/]/ # if absolute path file = File.expand_path(path) else file = Find.feature(path, :from=>__name__, :version=>__version__, :absolute=>true).first end raise LoadError, "no such file to load -- #{file}" unless file if __features__.include?(file) return false else __features__ << file script = File.read(file) #(SCRIPT[file] ||= File.read(file)) module_eval(script, file, 0) end return file end
Name of library.
# File lib/bezel.rb, line 139 def __name__ @__name__ end
Version of library.
# File lib/bezel.rb, line 144 def __version__ @__version__ end