typecollection 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -35,12 +35,3 @@ end
35
35
 
36
36
  task :default => :test
37
37
 
38
- require 'rake/rdoctask'
39
- Rake::RDocTask.new do |rdoc|
40
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
-
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "typecollection #{version}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
46
- end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.10
1
+ 0.0.11
@@ -1,6 +1,8 @@
1
1
  module TypeCollection
2
+ NAME_DECOMPOSER = /(^|(?<namespace>.*):{2})(?<constant>[^:]+)$/
3
+ class << self; attr_accessor :create_unknown_types; end
4
+
2
5
  module Base
3
-
4
6
  module BaseClassMethods
5
7
  # Returns all of the known subclass names for this collection
6
8
  def all_type_names(); return __tc_members().keys(); end
@@ -13,19 +15,48 @@ module TypeCollection
13
15
  raise TypeCollection::UnknownChildType.new("Unregistered type: #{type}") unless (mems.has_key?(type))
14
16
  return mems[type]
15
17
  end
16
- # Get similar type based on the object passed in which can be a String,
18
+ # Creates the type associated with the provided value (Class or Otherwise)
19
+ def generate_type(type)
20
+ type = type.inferred_type() if (type.kind_of?(Class))
21
+ root = __tc_collection_root()
22
+
23
+ name = TypeCollection::NAME_DECOMPOSER.match(root.name)
24
+
25
+ new_type = Class.new(root)
26
+ new_type_name = type + name[:constant]
27
+
28
+ # Back away. Just BACK. AWAY.
29
+ #
30
+ # We need to take this new class we've just created here
31
+ # and assign it to a constant in the same namespace as its
32
+ # collection root. That may be the global namespace.
33
+ # This mess accomplishes that.
34
+ ::Kernel.instance_exec(new_type, &eval("->(klass){ #{name[:namespace]}::#{new_type_name} = klass }"))
35
+
36
+ root.__tc_register_member(new_type)
37
+ new_type
38
+ end
39
+ # Get similar type based on the object passed in which can be a String,
17
40
  # Object (using the inferred type), or Class
18
- def get_associated_type(associate)
41
+ def get_associated_type(associate, create_if_unknown=TypeCollection.create_unknown_types)
19
42
  if (!associate.kind_of?(String))
20
43
  if (!associate.kind_of?(Class))
21
44
  associate = associate.class
22
45
  end
23
46
  associate = associate.inferred_type()
24
47
  end
25
- return self.get_type(associate)
48
+ begin
49
+ self.get_type(associate)
50
+ rescue TypeCollection::UnknownChildType => uct
51
+ if create_if_unknown
52
+ self.generate_type(associate)
53
+ else
54
+ raise
55
+ end
56
+ end
26
57
  end
27
58
  end
28
-
59
+
29
60
  def self.included(base)
30
61
  base.extend(TypeCollection::ClassMethods)
31
62
  base.extend(TypeCollection::Base::BaseClassMethods)
@@ -1,14 +1,15 @@
1
1
  class Class
2
- def inferred_type()
3
- klass_name = self.name.split("::").last
4
- parent_klass = self.superclass
5
- while(parent_klass != nil)
6
- check = /#{parent_klass.name.split("::").last}$/
7
- if (klass_name.match(check))
8
- return klass_name.gsub(check, '')
9
- end
10
- parent_klass = parent_klass.superclass
2
+ def __tc_collection_root()
3
+ root = self
4
+ while root.superclass && root.superclass.include?(TypeCollection::Base)
5
+ root = root.superclass
11
6
  end
12
- return nil
7
+ root
8
+ end
9
+
10
+ def inferred_type()
11
+ klass_name = self.name.split("::").last
12
+ root_name = __tc_collection_root.name.split("::").last
13
+ klass_name.gsub(root_name, "")
13
14
  end
14
- end
15
+ end
@@ -3,30 +3,37 @@ module TypeCollection
3
3
  # fails to comply with the correct naming convention for TypeCollection
4
4
  # to function properly
5
5
  class InvalidChildType < StandardError; end
6
-
6
+
7
7
  # Indicates that a request has been made to retrieve a child type that
8
8
  # is not currently registered with the type collection
9
9
  class UnknownChildType < StandardError; end
10
-
10
+
11
11
  # Extended by TypeCollections to provide class level functionality (almost
12
12
  # all functionality is class level as of the current design)
13
13
  module ClassMethods
14
14
  # Contains the Members mapped by type
15
15
  def __tc_members(); @_members ||= { }; end
16
-
17
- # Overrides the default behavior when being extended by a child class.
18
- # It ensures the child is mapped for future retrieval and checks the
19
- # subclass name to ensure it is a valid one
20
- def inherited(child)
21
- super if (defined?(super))
16
+
17
+ # Registers a member
18
+ def __tc_register_member(child)
22
19
  type = child.inferred_type()
23
20
  if (type.nil?)
24
21
  cname = child.name.split("::").last
25
22
  pname = self.name.split("::").last
26
- error = "Invalid Name: #{ cname }! Child class names must end with \"#{ pname }\"."
23
+ error = "Invalid name: '#{cname}'! Child class names must end with '#{pname}'."
27
24
  raise TypeCollection::InvalidChildType.new(error)
28
25
  end
29
26
  __tc_members()[type] = child
30
27
  end
28
+
29
+ # Overrides the default behavior when being extended by a child class.
30
+ # It ensures the child is mapped for future retrieval and checks the
31
+ # subclass name to ensure it is a valid one
32
+ def inherited(child)
33
+ super if (defined?(super))
34
+ unless child.name.nil?
35
+ __tc_collection_root.__tc_register_member(child)
36
+ end
37
+ end
31
38
  end
32
- end
39
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "typecollection"
8
- s.version = "0.0.10"
8
+ s.version = "0.0.11"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["James Petty"]
12
- s.date = "2012-08-13"
12
+ s.date = "2013-04-04"
13
13
  s.description = "Easily map subtypes into their parent type for later retrieval"
14
14
  s.email = "jp@jibe.com"
15
15
  s.extra_rdoc_files = [
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
36
36
  s.homepage = "http://github.com/pettyjamesm/TypeCollection"
37
37
  s.licenses = ["MIT"]
38
38
  s.require_paths = ["lib"]
39
- s.rubygems_version = "1.8.24"
39
+ s.rubygems_version = "1.8.25"
40
40
  s.summary = "TypeCollection maintains a record of sub-types for a given class based on a common suffix."
41
41
 
42
42
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typecollection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-13 00:00:00.000000000 Z
12
+ date: 2013-04-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: shoulda
@@ -97,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
97
  version: '0'
98
98
  segments:
99
99
  - 0
100
- hash: 110654369381516186
100
+ hash: 160659592697084515
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  none: false
103
103
  requirements:
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  version: '0'
107
107
  requirements: []
108
108
  rubyforge_project:
109
- rubygems_version: 1.8.24
109
+ rubygems_version: 1.8.25
110
110
  signing_key:
111
111
  specification_version: 3
112
112
  summary: TypeCollection maintains a record of sub-types for a given class based on