open_namespace 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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