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.
- data/README.md +37 -0
- data/lib/namespace.rb +92 -0
- 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
|
+
|