open_namespace 0.2.0 → 0.3.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/ChangeLog.md CHANGED
@@ -1,3 +1,16 @@
1
+ ### 0.3.0 / 2010-04-28
2
+
3
+ * Added {OpenNamespace.constant_path}.
4
+ * Added {OpenNamespace::ClassMethods#require_file}.
5
+ * Added {OpenNamespace::ClassMethods#const_search}.
6
+ * Improved searching for constants with oddly capitalized names, such as
7
+ `SQL` or `RemoteTCP`.
8
+ * Ensure that {OpenNamespace::ClassMethods#const_missing} only returns the
9
+ constant with the requested name.
10
+ * Removed `OpenNamespace::ClassMethods#namespace`.
11
+ * Removed `OpenNamespace::ClassMethods#namespace=`.
12
+ * Removed the dependency on extlib.
13
+
1
14
  ### 0.2.0 / 2010-04-13
2
15
 
3
16
  * Renamed the open-namespace gem to open_namespace, for naming consistency.
data/README.md CHANGED
@@ -27,38 +27,39 @@ Explicit and implicit loading of constants:
27
27
  end
28
28
  end
29
29
 
30
- # explicit loading of constants
30
+ # explicitly load constants
31
31
  Project::Plguins.require_const :foo_bar
32
32
  # => Project::Plugins::FooBar
33
33
 
34
- # explicitly loading constants via sub-paths
34
+ # explicitly load constants with odd capitalization
35
+ Project::Plugins.require_const :tcp_session
36
+ # => Project::Plugins::TCPSession
37
+
38
+ # explicitly load constants via sub-paths
35
39
  Project::Plguins.require_const 'templates/erb'
36
40
  # => Project::Plugins::Templates::Erb
37
41
 
38
- # implicit loading of constants via const_missing
42
+ # implicitly load constants via const_missing
39
43
  Project::Plugins::Other
40
44
  # => Project::Plugins::Other
41
45
 
42
- Loading constants from alternate namespaces / directories:
46
+ Loading constants from alternate namespace root directories:
43
47
 
44
48
  module Project
45
49
  module UI
46
50
  module CommandLine
47
- include OpenNamespace
51
+ module Commands
52
+ include OpenNamespace
48
53
 
49
- self.namespace = 'Project::UI::CommandLine::Commands'
50
- self.namespace_root = File.join('project','ui','command_line','commands')
54
+ self.namespace_root = File.join('project','ui','command_line','commands')
55
+ end
51
56
  end
52
57
  end
53
58
  end
54
59
 
55
- Project::UI::CommandLine.require_const :help
60
+ Project::UI::CommandLine::Commands.require_const :help
56
61
  # => Project::UI::CommandLine::Commands::Help
57
62
 
58
- ## Requirements
59
-
60
- * [extlib](http://gemcutter.org/gems/extlib) >= 0.9.14
61
-
62
63
  ## Install
63
64
 
64
65
  $ sudo gem install open_namespace
data/Rakefile CHANGED
@@ -13,11 +13,11 @@ begin
13
13
  gem.email = 'postmodern.mod3@gmail.com'
14
14
  gem.homepage = 'http://github.com/postmodern/open-namespace'
15
15
  gem.authors = ['Postmodern']
16
- gem.add_dependency 'extlib', '>= 0.9.14'
17
16
  gem.add_development_dependency 'rspec', '>= 1.2.9'
18
17
  gem.add_development_dependency 'yard', '>= 0.5.3'
19
18
  gem.has_rdoc = 'yard'
20
19
  end
20
+ Jeweler::GemcutterTasks.new
21
21
  rescue LoadError
22
22
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
23
  end
@@ -1,35 +1,5 @@
1
- require 'extlib'
2
-
3
1
  module OpenNamespace
4
2
  module ClassMethods
5
- #
6
- # The namespace to search within.
7
- #
8
- # @return [String]
9
- # The namespace to search for constants within.
10
- #
11
- def namespace
12
- @namespace ||= self.name
13
- end
14
-
15
- #
16
- # Sets the namespace to search within.
17
- #
18
- # @param [Module, Class, String] new_namespace
19
- # The new namespace to search within.
20
- #
21
- # @return [String]
22
- # The namespace to search within.
23
- #
24
- def namespace=(new_namespace)
25
- case new_namespace
26
- when Module, Class
27
- @namespace = new_namespace.name
28
- else
29
- @namespace = new_namespace.to_s
30
- end
31
- end
32
-
33
3
  #
34
4
  # The file path that represents the namespace.
35
5
  #
@@ -37,7 +7,7 @@ module OpenNamespace
37
7
  # The file path used to load constants into the namespace.
38
8
  #
39
9
  def namespace_root
40
- @namespace_root ||= self.name.to_const_path
10
+ @namespace_root ||= OpenNamespace.constant_path(self.name)
41
11
  end
42
12
 
43
13
  #
@@ -73,6 +43,28 @@ module OpenNamespace
73
43
  # # => Fully::Qualified::Namespace::Network::Helper
74
44
  #
75
45
  def require_const(name)
46
+ require_file(name)
47
+
48
+ return const_search(name)
49
+ end
50
+
51
+ #
52
+ # Requires the file with the given name, within the namespace root
53
+ # directory.
54
+ #
55
+ # @param [Symbol, String] name
56
+ # The name of the file to require.
57
+ #
58
+ # @return [true, nil]
59
+ # Returns `true` if the file was successfully loaded, returns `nil`
60
+ # on a `LoadError` exception.
61
+ #
62
+ # @raise [Gem::LoadError]
63
+ # A dependency needed by the file could not be satisfied by RubyGems.
64
+ #
65
+ # @since 0.3.0
66
+ #
67
+ def require_file(name)
76
68
  name = name.to_s
77
69
  path = File.join(namespace_root,File.expand_path(File.join('',name)))
78
70
 
@@ -84,13 +76,44 @@ module OpenNamespace
84
76
  return nil
85
77
  end
86
78
 
87
- const_name = (self.namespace + '::' + name.to_const_string)
79
+ return true
80
+ end
88
81
 
89
- begin
90
- return Object.full_const_get(const_name)
91
- rescue NameError
92
- return nil
82
+ #
83
+ # Finds the constant with a name similar to the given file name.
84
+ #
85
+ # @param [Symbol, String] file_name
86
+ # The file name that represents the constant.
87
+ #
88
+ # @return [Object, nil]
89
+ # Returns the found constants, or `nil` if a `NameError` exception
90
+ # was encountered.
91
+ #
92
+ # @since 0.3.0
93
+ #
94
+ def const_search(file_name)
95
+ names = file_name.to_s.split(/[:\/]+/)
96
+ scope = self
97
+
98
+ until names.empty?
99
+ name = names.shift
100
+
101
+ # strip any dashes or underscores
102
+ name.tr!('_-','')
103
+
104
+ # perform a case insensitive search
105
+ const_pattern = /^#{name}$/i
106
+
107
+ # grep for the constant
108
+ const_name = scope.constants.find { |name| name =~ const_pattern }
109
+
110
+ # the constant search failed
111
+ return nil unless const_name
112
+
113
+ scope = scope.const_get(const_name)
93
114
  end
115
+
116
+ return scope
94
117
  end
95
118
 
96
119
  protected
@@ -110,7 +133,21 @@ module OpenNamespace
110
133
  # @see require_const.
111
134
  #
112
135
  def const_missing(name)
113
- require_const(name.to_s.to_const_path) || super(name)
136
+ file_name = OpenNamespace.constant_path(name)
137
+
138
+ if require_file(file_name)
139
+ #
140
+ # If const_missing is being called, the constant is not present yet.
141
+ # Therefor, only check for the constant if the file was
142
+ # successfully loaded by require_file.
143
+ #
144
+ if self.const_defined?(name)
145
+ # get the exact constant name that was requested
146
+ return self.const_get(name)
147
+ end
148
+ end
149
+
150
+ return super(name)
114
151
  end
115
152
  end
116
153
  end
@@ -4,4 +4,31 @@ module OpenNamespace
4
4
  def self.included(base)
5
5
  base.extend ClassMethods
6
6
  end
7
+
8
+ #
9
+ # Maps a constant name to a likely file path.
10
+ #
11
+ # @param [String, Symbol] name
12
+ # The constant name.
13
+ #
14
+ # @return [String]
15
+ # The file path that the constant is likely to be defined within.
16
+ #
17
+ # @since 0.3.0
18
+ #
19
+ def OpenNamespace.constant_path(name)
20
+ path = name.to_s
21
+
22
+ # back-ported from extlib's String#to_const_path
23
+ path.gsub!(/::/,'/')
24
+
25
+ # back-ported from extlib's String#snake_case
26
+ unless path.match(/\A[A-Z]+\z/)
27
+ path.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
28
+ path.gsub!(/([a-z])([A-Z])/, '\1_\2')
29
+ end
30
+ path.downcase!
31
+
32
+ return path
33
+ end
7
34
  end
@@ -1,4 +1,4 @@
1
1
  module OpenNamespace
2
2
  # open_namespace version
3
- VERSION = '0.2.0'
3
+ VERSION = '0.3.0'
4
4
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{open_namespace}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Postmodern"]
12
- s.date = %q{2010-04-13}
12
+ s.date = %q{2010-04-28}
13
13
  s.description = %q{OpenNamespace allows namespaces to require and find classes and modules from other RubyGems.}
14
14
  s.email = %q{postmodern.mod3@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -33,12 +33,14 @@ Gem::Specification.new do |s|
33
33
  "spec/classes/custom/bad_constant.rb",
34
34
  "spec/classes/custom/constant_one.rb",
35
35
  "spec/classes/custom/constant_two.rb",
36
+ "spec/classes/custom/odd_constant.rb",
36
37
  "spec/classes/custom/sub/constant_four.rb",
37
38
  "spec/classes/custom_namespace.rb",
38
39
  "spec/classes/simple_namespace.rb",
39
40
  "spec/classes/simple_namespace/bad_constant.rb",
40
41
  "spec/classes/simple_namespace/constant_one.rb",
41
42
  "spec/classes/simple_namespace/constant_two.rb",
43
+ "spec/classes/simple_namespace/odd_constant.rb",
42
44
  "spec/classes/simple_namespace/sub/constant_four.rb",
43
45
  "spec/open_namespace_spec.rb",
44
46
  "spec/spec_helper.rb"
@@ -58,11 +60,13 @@ Gem::Specification.new do |s|
58
60
  "spec/classes/custom/constant_one.rb",
59
61
  "spec/classes/custom/bad_constant.rb",
60
62
  "spec/classes/custom/sub/constant_four.rb",
63
+ "spec/classes/custom/odd_constant.rb",
61
64
  "spec/classes/simple_namespace.rb",
62
65
  "spec/classes/simple_namespace/constant_two.rb",
63
66
  "spec/classes/simple_namespace/constant_one.rb",
64
67
  "spec/classes/simple_namespace/bad_constant.rb",
65
- "spec/classes/simple_namespace/sub/constant_four.rb"
68
+ "spec/classes/simple_namespace/sub/constant_four.rb",
69
+ "spec/classes/simple_namespace/odd_constant.rb"
66
70
  ]
67
71
 
68
72
  if s.respond_to? :specification_version then
@@ -70,16 +74,13 @@ Gem::Specification.new do |s|
70
74
  s.specification_version = 3
71
75
 
72
76
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
- s.add_runtime_dependency(%q<extlib>, [">= 0.9.14"])
74
77
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
75
78
  s.add_development_dependency(%q<yard>, [">= 0.5.3"])
76
79
  else
77
- s.add_dependency(%q<extlib>, [">= 0.9.14"])
78
80
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
79
81
  s.add_dependency(%q<yard>, [">= 0.5.3"])
80
82
  end
81
83
  else
82
- s.add_dependency(%q<extlib>, [">= 0.9.14"])
83
84
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
84
85
  s.add_dependency(%q<yard>, [">= 0.5.3"])
85
86
  end
@@ -1,8 +1,6 @@
1
1
  module Classes
2
2
  module CusstomNamespace
3
- module Custom
4
- class ConstantThree
5
- end
3
+ class ConstantThree
6
4
  end
7
5
  end
8
6
  end
@@ -1,8 +1,6 @@
1
1
  module Classes
2
2
  module CustomNamespace
3
- module Custom
4
- class ConstantOne
5
- end
3
+ class ConstantOne
6
4
  end
7
5
  end
8
6
  end
@@ -1,8 +1,6 @@
1
1
  module Classes
2
2
  module CustomNamespace
3
- module Custom
4
- class ConstantTwo
5
- end
3
+ class ConstantTwo
6
4
  end
7
5
  end
8
6
  end
@@ -0,0 +1,6 @@
1
+ module Classes
2
+ module CustomNamespace
3
+ class ODDConstant
4
+ end
5
+ end
6
+ end
@@ -1,9 +1,7 @@
1
1
  module Classes
2
2
  module CustomNamespace
3
- module Custom
4
- module Sub
5
- class ConstantFour
6
- end
3
+ module Sub
4
+ class ConstantFour
7
5
  end
8
6
  end
9
7
  end
@@ -4,7 +4,6 @@ module Classes
4
4
  module CustomNamespace
5
5
  include OpenNamespace
6
6
 
7
- self.namespace = 'Classes::CustomNamespace::Custom'
8
7
  self.namespace_root = File.join('classes','custom')
9
8
  end
10
9
  end
@@ -0,0 +1,6 @@
1
+ module Classes
2
+ module SimpleNamespace
3
+ class ODDConstant
4
+ end
5
+ end
6
+ end
@@ -9,15 +9,11 @@ describe OpenNamespace do
9
9
  OpenNamespace.const_defined?('VERSION').should == true
10
10
  end
11
11
 
12
- describe "default namespace" do
12
+ context "default namespace" do
13
13
  before(:all) do
14
14
  @module = Classes::SimpleNamespace
15
15
  end
16
16
 
17
- it "should have the same namespace as the module name" do
18
- @module.namespace.should == 'Classes::SimpleNamespace'
19
- end
20
-
21
17
  it "should have the same namespace root as the module's directory" do
22
18
  @module.namespace_root.should == File.join('classes','simple_namespace')
23
19
  end
@@ -35,6 +31,13 @@ describe OpenNamespace do
35
31
  const.name.should == 'Classes::SimpleNamespace::ConstantOne'
36
32
  end
37
33
 
34
+ it "should find constants with odd capitalization" do
35
+ const = @module.require_const(:odd_constant)
36
+
37
+ const.class.should == Class
38
+ const.name.should == 'Classes::SimpleNamespace::ODDConstant'
39
+ end
40
+
38
41
  it "should load constants via sub-paths" do
39
42
  @module.require_const File.join('sub','constant_four')
40
43
 
@@ -77,43 +80,39 @@ describe OpenNamespace do
77
80
  end
78
81
  end
79
82
 
80
- describe "custom namespace" do
83
+ context "custom namespace" do
81
84
  before(:all) do
82
85
  @module = Classes::CustomNamespace
83
86
  end
84
87
 
85
- it "should have the same namespace as the module name" do
86
- @module.namespace.should == 'Classes::CustomNamespace::Custom'
87
- end
88
-
89
88
  it "should have the same namespace root as the module's directory" do
90
89
  @module.namespace_root.should == File.join('classes','custom')
91
90
  end
92
91
 
93
92
  it "should load constants into the namespace" do
94
93
  @module.require_const :constant_one
95
-
96
- @module.should be_const_defined('Custom')
97
- @custom = @module.const_get('Custom')
98
-
99
- @custom.should be_const_defined('ConstantOne')
94
+ @module.should be_const_defined('ConstantOne')
100
95
  end
101
96
 
102
97
  it "should find loaded constants in the namespace" do
103
98
  const = @module.require_const(:constant_one)
104
99
 
105
100
  const.class.should == Class
106
- const.name.should == 'Classes::CustomNamespace::Custom::ConstantOne'
101
+ const.name.should == 'Classes::CustomNamespace::ConstantOne'
102
+ end
103
+
104
+ it "should find constants with odd capitalization" do
105
+ const = @module.require_const(:odd_constant)
106
+
107
+ const.class.should == Class
108
+ const.name.should == 'Classes::CustomNamespace::ODDConstant'
107
109
  end
108
110
 
109
111
  it "should load constants via sub-paths" do
110
112
  @module.require_const File.join('sub','constant_four')
111
113
 
112
- @module.should be_const_defined('Custom')
113
- @custom = @module.const_get('Custom')
114
-
115
- @custom.should be_const_defined('Sub')
116
- @sub = @custom.const_get('Sub')
114
+ @module.should be_const_defined('Sub')
115
+ @sub = @module.const_get('Sub')
117
116
 
118
117
  @sub.should be_const_defined('ConstantFour')
119
118
  end
@@ -122,7 +121,7 @@ describe OpenNamespace do
122
121
  const = @module.require_const(File.join('sub','constant_four'))
123
122
 
124
123
  const.class.should == Class
125
- const.name.should == 'Classes::CustomNamespace::Custom::Sub::ConstantFour'
124
+ const.name.should == 'Classes::CustomNamespace::Sub::ConstantFour'
126
125
  end
127
126
 
128
127
  it "should return nil on LoadError exceptions" do
@@ -141,7 +140,7 @@ describe OpenNamespace do
141
140
  const = @module::ConstantTwo
142
141
 
143
142
  const.class.should == Class
144
- const.name.should == 'Classes::CustomNamespace::Custom::ConstantTwo'
143
+ const.name.should == 'Classes::CustomNamespace::ConstantTwo'
145
144
  end
146
145
 
147
146
  it "should raise a NameError exception const_missing fails" do
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Postmodern
@@ -14,27 +14,13 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-13 00:00:00 -07:00
17
+ date: 2010-04-28 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: extlib
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- - 9
30
- - 14
31
- version: 0.9.14
32
- type: :runtime
33
- version_requirements: *id001
34
20
  - !ruby/object:Gem::Dependency
35
21
  name: rspec
36
22
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
38
24
  requirements:
39
25
  - - ">="
40
26
  - !ruby/object:Gem::Version
@@ -44,11 +30,11 @@ dependencies:
44
30
  - 9
45
31
  version: 1.2.9
46
32
  type: :development
47
- version_requirements: *id002
33
+ version_requirements: *id001
48
34
  - !ruby/object:Gem::Dependency
49
35
  name: yard
50
36
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
37
+ requirement: &id002 !ruby/object:Gem::Requirement
52
38
  requirements:
53
39
  - - ">="
54
40
  - !ruby/object:Gem::Version
@@ -58,7 +44,7 @@ dependencies:
58
44
  - 3
59
45
  version: 0.5.3
60
46
  type: :development
61
- version_requirements: *id003
47
+ version_requirements: *id002
62
48
  description: OpenNamespace allows namespaces to require and find classes and modules from other RubyGems.
63
49
  email: postmodern.mod3@gmail.com
64
50
  executables: []
@@ -85,12 +71,14 @@ files:
85
71
  - spec/classes/custom/bad_constant.rb
86
72
  - spec/classes/custom/constant_one.rb
87
73
  - spec/classes/custom/constant_two.rb
74
+ - spec/classes/custom/odd_constant.rb
88
75
  - spec/classes/custom/sub/constant_four.rb
89
76
  - spec/classes/custom_namespace.rb
90
77
  - spec/classes/simple_namespace.rb
91
78
  - spec/classes/simple_namespace/bad_constant.rb
92
79
  - spec/classes/simple_namespace/constant_one.rb
93
80
  - spec/classes/simple_namespace/constant_two.rb
81
+ - spec/classes/simple_namespace/odd_constant.rb
94
82
  - spec/classes/simple_namespace/sub/constant_four.rb
95
83
  - spec/open_namespace_spec.rb
96
84
  - spec/spec_helper.rb
@@ -132,8 +120,10 @@ test_files:
132
120
  - spec/classes/custom/constant_one.rb
133
121
  - spec/classes/custom/bad_constant.rb
134
122
  - spec/classes/custom/sub/constant_four.rb
123
+ - spec/classes/custom/odd_constant.rb
135
124
  - spec/classes/simple_namespace.rb
136
125
  - spec/classes/simple_namespace/constant_two.rb
137
126
  - spec/classes/simple_namespace/constant_one.rb
138
127
  - spec/classes/simple_namespace/bad_constant.rb
139
128
  - spec/classes/simple_namespace/sub/constant_four.rb
129
+ - spec/classes/simple_namespace/odd_constant.rb