namespace 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/README.md +37 -0
  2. data/lib/namespace.rb +92 -0
  3. metadata +70 -0
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ Namespaces for ruby <hack>
2
+ ==========================
3
+
4
+ Brings a namespace system to ruby. By loading the .rb files into a temporary
5
+ module, it is possible to avoid polluting the global namespace and select what to import
6
+ in the current module.
7
+
8
+ This system is inspired by the CommonJS module system, but it was adapted
9
+ for the ruby particularities.
10
+
11
+ Feature:
12
+ * Possible to avoid namespace collision on the module level
13
+ * Relative requires (if import is used in the top-level of the file)
14
+
15
+ Unfeatures:
16
+ * uses eval and other nasty ruby hacks
17
+ * classes and namespaces don't mix well because "class X; <<here>>; end"
18
+ is a new context that doesn't inherit from it's parent.
19
+
20
+ TODO
21
+ ----
22
+
23
+ * Handle circular dependencies ?
24
+ * Avoid eval (but I don't see how)
25
+
26
+ Bikeshed
27
+ --------
28
+
29
+ * Should ruby "namespaced" modules have their own $LOAD_PATH and file extensions ?
30
+
31
+ Licence
32
+ -------
33
+
34
+ Public domain
35
+
36
+ Cheers,
37
+ Jonas
data/lib/namespace.rb ADDED
@@ -0,0 +1,92 @@
1
+ # Namespaces for ruby.
2
+ #
3
+ # See Namespace#import
4
+ module Namespace
5
+ @cache = {}
6
+ class << self;
7
+ attr_reader :cache
8
+ include Namespace
9
+ end
10
+
11
+ module Def
12
+ def self.included(mod)
13
+ eigenclass = (class << mod
14
+ # Override to not show Namespace::NS for all modules
15
+ def inspect
16
+ defined?(@__namespace__) ? "<#{@__namespace__} #{(constants+instance_methods).sort.join(', ')}>" : super
17
+ end
18
+ self
19
+ end)
20
+ eigenclass.send(:include, mod, Namespace)
21
+ end
22
+ end
23
+
24
+ #
25
+ # Loads a file according to the +namespace+ in the context of a module,
26
+ # and returns that object.
27
+ #
28
+ # It's not a Python import, where the namespace is available. What you
29
+ # get here, is a sort of Sandbox where constants defined in the file are
30
+ # not polluting the global namespace but available on the returned object.
31
+ # Since the returned object is a Module, it can be included in the current
32
+ # module if you're also in the contect of a "Sandbox".
33
+ #
34
+ # #import has been chosen because the ruby namespace is already crowded
35
+ # (require, load and include are already taken)
36
+ #
37
+ def import(namespace)
38
+ namespace = namespace.to_s.gsub(/[\/\\:]+/, ':') # allow symbols
39
+
40
+ # @__namespace__ is not available outside of the ruby top-level
41
+ if defined?(@__namespace__) && namespace[0..0] != ":"
42
+ # expand namespace
43
+ namespace = @__namespace__.sub(/:[^:]+$/,'') + ':' + namespace
44
+ else
45
+ namespace = ':' + namespace
46
+ end
47
+ puts "ns##{namespace}"
48
+
49
+ # Cache lookup
50
+ ns = Namespace::cache[namespace]
51
+ return ns if ns
52
+
53
+ file = nil
54
+ # File lookup
55
+ file_path = namespace[1..-1].gsub(':', File::SEPARATOR) + '.rb'
56
+ $LOAD_PATH.each do |path|
57
+ path = File.join(path, file_path)
58
+ if File.exists? path
59
+ file = path
60
+ break
61
+ end
62
+ end
63
+
64
+ raise LoadError, "no such file to load -- #{file_path}" unless file
65
+
66
+ file_content = File.read(file_path)
67
+ # Pre-process __NAMESPACE__ keyword to act like __FILE__
68
+ # in know... it's not exactly the same... (eg "__FILE__") but it should do the trick
69
+ file_content.gsub!('__NAMESPACE__', namespace.inspect)
70
+
71
+ # Make sure NS is new (in the cases where the current NS requires another NS)
72
+ Object.send(:remove_const, :NS) rescue nil
73
+ # String is on 1 line to make sure line-errors are preserved
74
+ ns = eval("module NS; @__namespace__ = #{namespace.inspect}; include Namespace::Def; #{file_content}; self; end", TOPLEVEL_BINDING, file)
75
+
76
+ # Cache
77
+ Namespace::cache[namespace] = ns
78
+
79
+ return ns
80
+ ensure
81
+ Object.send(:remove_const, :NS) rescue nil
82
+ end
83
+ end
84
+
85
+ # Make #import available to all
86
+ class Object; include Namespace; end
87
+
88
+ if __FILE__ == $0
89
+ require 'irb'
90
+ require 'irb/completion'
91
+ IRB.start
92
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: namespace
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Jonas Pfenniger
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-20 00:00:00 +00:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: |-
22
+ This module is a hack that allows you to load specific
23
+ ruby files in the context of a Module, thus avoiding global namespace
24
+ pollution
25
+ email: jonas@pfenniger.name
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - README.md
34
+ - lib/namespace.rb
35
+ has_rdoc: true
36
+ homepage: https://github.com/zimbatm/namespace.rb
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 3
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.7
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Bringing namespaces to Ruby
69
+ test_files: []
70
+