classy 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +23 -0
- data/VERSION +1 -1
- data/lib/classy/aliasable.rb +15 -12
- data/lib/classy/subclass_aware.rb +44 -4
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -6,6 +6,29 @@ SubclassAware lets a class know about all of its subclasses (and
|
|
6
6
|
sub-subclasses, etc), and Aliasable lets you refer to classes via symbols
|
7
7
|
(useful for creating friendly DSLs).
|
8
8
|
|
9
|
+
== Examples
|
10
|
+
|
11
|
+
class Parent
|
12
|
+
extend Aliasable
|
13
|
+
extend SubclassAware
|
14
|
+
|
15
|
+
aka :pop
|
16
|
+
end
|
17
|
+
|
18
|
+
class ChildA
|
19
|
+
aka :kid1
|
20
|
+
end
|
21
|
+
|
22
|
+
class ChildB
|
23
|
+
aka :kid2
|
24
|
+
end
|
25
|
+
|
26
|
+
Parent.find(:kid1) # => ChildA
|
27
|
+
Parent.subclasses # => [ ChildA, ChildB ]
|
28
|
+
|
29
|
+
More extensive documentation and example code can be found in the RDoc for each
|
30
|
+
module, or in the spec files.
|
31
|
+
|
9
32
|
== Note on Patches/Pull Requests
|
10
33
|
|
11
34
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/classy/aliasable.rb
CHANGED
@@ -8,27 +8,28 @@
|
|
8
8
|
# @@classy_aliases, on the extending class. This could concievably lead to
|
9
9
|
# namespace conflicts and strange bugs in the unlikely event that this variable
|
10
10
|
# is used for anything else. Later versions may implement a hash of identity
|
11
|
-
# maps as a class variable on the
|
11
|
+
# maps as a class variable on the Aliasable module itself, but for reasons of
|
12
12
|
# complexity and performance, that has not been done at this time.
|
13
13
|
#
|
14
14
|
# Example:
|
15
15
|
#
|
16
|
-
# class
|
16
|
+
# class ParentClass
|
17
17
|
# extend Aliasable
|
18
18
|
# aka :pop
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
# class
|
21
|
+
# class AliasedSubclass < ParentClass
|
22
22
|
# aka :kid
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
# Parent.find(:pop) # =>
|
26
|
-
# Parent.find(:kid) # =>
|
25
|
+
# Parent.find(:pop) # => ParentClass
|
26
|
+
# Parent.find(:kid) # => AliasedSubclass
|
27
27
|
#
|
28
28
|
# More complex usage examples can be found in the aliasable_spec.rb file.
|
29
29
|
#
|
30
30
|
module Aliasable
|
31
|
-
|
31
|
+
|
32
|
+
def self.extended (klass) #:nodoc:
|
32
33
|
klass.class_exec do
|
33
34
|
class_variable_set(:@@classy_aliases, {})
|
34
35
|
end
|
@@ -37,25 +38,25 @@ module Aliasable
|
|
37
38
|
# When passed a class, just returns it. When passed a symbol that is an
|
38
39
|
# alias for a class, returns that class.
|
39
40
|
#
|
40
|
-
#
|
41
|
+
# ParentClass.find(AliasedSubclass) # => AliasedSubclass
|
42
|
+
# ParentClass.find(:kid) # => AliasedSubclass
|
41
43
|
#
|
42
44
|
def find (klass)
|
43
45
|
return klass if klass.kind_of? Class
|
44
46
|
class_variable_get(:@@classy_aliases)[klass] or raise ArgumentError, "Could not find alias #{klass}"
|
45
47
|
end
|
46
48
|
|
47
|
-
# Forget all known aliases.
|
49
|
+
# Forget all known aliases. Mainly useful for testing purposes.
|
48
50
|
#
|
49
51
|
def forget_aliases
|
50
52
|
class_variable_get(:@@classy_aliases).clear
|
51
53
|
end
|
52
54
|
|
53
55
|
# Specifies a symbol (or several) that a given framework might be known
|
54
|
-
# by.
|
55
|
-
# you might do this:
|
56
|
+
# by.
|
56
57
|
#
|
57
|
-
# class
|
58
|
-
# aka :
|
58
|
+
# class AnotherClass
|
59
|
+
# aka :kid2, :chunky_bacon
|
59
60
|
# ...
|
60
61
|
# end
|
61
62
|
#
|
@@ -68,6 +69,8 @@ module Aliasable
|
|
68
69
|
|
69
70
|
# Return a hash of known aliases to Class objects
|
70
71
|
#
|
72
|
+
# ParentClass.aliases # => { :pop => ParentClass, :kid => AliasedSubclass, :kid2 => AnotherClass, :chunky_bacon => AnotherClass }
|
73
|
+
#
|
71
74
|
def aliases
|
72
75
|
class_variable_get(:@@classy_aliases).dup
|
73
76
|
end
|
@@ -1,15 +1,55 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
|
+
# SubclassAware allows a class to know about all of the subclasses that descend
|
4
|
+
# from it in the inheritance tree.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# class Parent
|
9
|
+
# extend SubclassAware
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# class ChildA < Parent
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class ChildB < Parent
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Class ChildB1 < ChildB
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Parent.subclasses # => [ ChildA, ChildB, ChildB1 ]
|
22
|
+
#
|
23
|
+
# Warning: This module defines an inherited() class method on the extending
|
24
|
+
# class to keep track of subclasses. Unfortunately, if this method is later
|
25
|
+
# re-defined, this inherited() method is lost and subclass tracking will break.
|
26
|
+
# In order to work around this, constructions like the following might be
|
27
|
+
# necessary:
|
28
|
+
#
|
29
|
+
# class ChildC < Parent
|
30
|
+
#
|
31
|
+
# class << self; alias :old_inherited :inherited end
|
32
|
+
# def self.inherited(sub)
|
33
|
+
# old_inherited(sub)
|
34
|
+
# # ...your inherited() code...
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# This is not considered an acceptable long-term state of affairs - hopefully
|
40
|
+
# in future versions of this module, this work around will not be necessary.
|
41
|
+
#
|
3
42
|
module SubclassAware
|
4
43
|
|
5
|
-
def self.extended (klass)
|
44
|
+
def self.extended (klass) #:nodoc:
|
6
45
|
klass.class_exec { class_variable_set(:@@subclasses, Set.new) }
|
7
46
|
end
|
8
47
|
|
9
48
|
# TODO: Find a way for self.inherited on the extended class not to blow
|
10
49
|
# this away without requiring a bunch of alias chain hoops to be jumped
|
11
50
|
# through.
|
12
|
-
|
51
|
+
#
|
52
|
+
def inherited(sub) #:nodoc:
|
13
53
|
class_exec { class_variable_get(:@@subclasses).add sub }
|
14
54
|
end
|
15
55
|
|
@@ -20,8 +60,8 @@ module SubclassAware
|
|
20
60
|
class_exec { class_variable_get(:@@subclasses).to_a }
|
21
61
|
end
|
22
62
|
|
23
|
-
# Clear all info about known subclasses.
|
24
|
-
#
|
63
|
+
# Clear all info about known subclasses. This method is probably mainly
|
64
|
+
# useful for testing.
|
25
65
|
#
|
26
66
|
def forget_subclasses
|
27
67
|
class_exec { class_variable_get(:@@subclasses).clear }
|