key_struct 0.4.1 → 0.4.2
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.rdoc +1 -0
- data/lib/key_struct/key_struct.rb +38 -49
- data/lib/key_struct/version.rb +1 -1
- data/spec/key_struct_spec.rb +35 -8
- metadata +7 -7
data/README.rdoc
CHANGED
@@ -134,6 +134,7 @@ Requires ruby >= 1.9.2. (Has been tested on MRI 1.9.2 and MRI 1.9.3)
|
|
134
134
|
|
135
135
|
Release Notes:
|
136
136
|
|
137
|
+
* 0.4.2 - Bug fix: make class introspection work for derived classes. Restore metaprogramming: inheritance too fragile.
|
137
138
|
* 0.4.1 - Cache anonymous classes to avoid TypeError: superclass mismatch. Nicer strings for anonymous classes. Internals change: use base class rather than metaprogramming.
|
138
139
|
* 0.4.0 - Introduce class introspection
|
139
140
|
* 0.3.1 - Bug fix: to_hash when a value is an array. Was raising ArgumentError for Hash
|
@@ -14,51 +14,6 @@ module KeyStruct
|
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
-
class Base
|
18
|
-
include Comparable
|
19
|
-
|
20
|
-
class << self
|
21
|
-
attr_reader :keys, :defaults, :access
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(args={})
|
25
|
-
args = self.class.defaults.merge(args)
|
26
|
-
self.class.keys.each do |key|
|
27
|
-
instance_variable_set("@#{key}".to_sym, args.delete(key))
|
28
|
-
end
|
29
|
-
raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')} -- KeyStruct accepts #{self.class.keys.map(&:inspect).join(' ')}" if args.any?
|
30
|
-
end
|
31
|
-
|
32
|
-
def ==(other)
|
33
|
-
self.class.keys.all?{|key| other.respond_to?(key) and self.send(key) == other.send(key)}
|
34
|
-
end
|
35
|
-
|
36
|
-
def <=>(other)
|
37
|
-
self.class.keys.each do |key|
|
38
|
-
cmp = (self.send(key) <=> other.send(key))
|
39
|
-
return cmp unless cmp == 0
|
40
|
-
end
|
41
|
-
0
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_hash
|
45
|
-
Hash[*self.class.keys.map{ |key| [key, self.send(key)]}.flatten(1)]
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
"[#{self.class.display_name} #{self.class.keys.map{|key| "#{key}:#{self.send(key)}"}.join(' ')}]"
|
50
|
-
end
|
51
|
-
|
52
|
-
def inspect
|
53
|
-
"<#{self.class.display_name}:0x#{self.object_id.to_s(16)} #{self.class.keys.map{|key| "#{key}:#{self.send(key).inspect}"}.join(' ')}>"
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.display_name
|
57
|
-
self.name || "KeyStruct.#{access}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
17
|
# for anonymous superclasses, such as
|
63
18
|
#
|
64
19
|
# class Foo < KeyStruct[:a, :b]
|
@@ -90,12 +45,46 @@ module KeyStruct
|
|
90
45
|
defaults = (Hash === keys.last) ? keys.pop.dup : {}
|
91
46
|
keys += defaults.keys
|
92
47
|
|
93
|
-
Class.new
|
48
|
+
Class.new.tap{ |klass|
|
94
49
|
klass.class_eval do
|
95
|
-
|
96
|
-
|
97
|
-
@access = access
|
50
|
+
include Comparable
|
51
|
+
|
98
52
|
send "attr_#{access}", *keys
|
53
|
+
|
54
|
+
define_singleton_method(:keys) { keys }
|
55
|
+
define_singleton_method(:defaults) { defaults }
|
56
|
+
define_singleton_method(:access) { access }
|
57
|
+
define_singleton_method(:display_name) { self.name || "KeyStruct.#{access}" }
|
58
|
+
|
59
|
+
define_method(:initialize) do | args={} |
|
60
|
+
args = defaults.merge(args)
|
61
|
+
keys.each do |key|
|
62
|
+
instance_variable_set("@#{key}".to_sym, args.delete(key))
|
63
|
+
end
|
64
|
+
raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')} -- KeyStruct accepts #{keys.map(&:inspect).join(' ')}" if args.any?
|
65
|
+
end
|
66
|
+
|
67
|
+
define_method(:to_s) {
|
68
|
+
"[#{self.class.display_name} #{keys.map{|key| "#{key}:#{self.send(key)}"}.join(' ')}]"
|
69
|
+
}
|
70
|
+
define_method(:inspect) {
|
71
|
+
"<#{self.class.display_name}:0x#{self.object_id.to_s(16)} #{keys.map{|key| "#{key}:#{self.send(key).inspect}"}.join(' ')}>"
|
72
|
+
}
|
73
|
+
define_method(:to_hash) {
|
74
|
+
Hash[*keys.map{ |key| [key, self.send(key)]}.flatten(1)]
|
75
|
+
}
|
76
|
+
define_method(:==) { |other|
|
77
|
+
self.class.keys.all?{|key| other.respond_to?(key) and self.send(key) == other.send(key)}
|
78
|
+
}
|
79
|
+
|
80
|
+
define_method(:<=>) { |other|
|
81
|
+
keys.each do |key|
|
82
|
+
cmp = (self.send(key) <=> other.send(key))
|
83
|
+
return cmp unless cmp == 0
|
84
|
+
end
|
85
|
+
0
|
86
|
+
}
|
87
|
+
|
99
88
|
end
|
100
89
|
}
|
101
90
|
end
|
data/lib/key_struct/version.rb
CHANGED
data/spec/key_struct_spec.rb
CHANGED
@@ -12,14 +12,6 @@ shared_examples "a keystruct" do |method|
|
|
12
12
|
Class.should === @klass
|
13
13
|
end
|
14
14
|
|
15
|
-
it "should instrospect keys" do
|
16
|
-
@klass.keys.should == [:a, :b, :c]
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should instrospect defaults" do
|
20
|
-
@klass.defaults.should == {:c => 3}
|
21
|
-
end
|
22
|
-
|
23
15
|
it "provides getters" do
|
24
16
|
@klass.instance_methods.should include :a
|
25
17
|
@klass.instance_methods.should include :b
|
@@ -51,6 +43,41 @@ shared_examples "a keystruct" do |method|
|
|
51
43
|
|
52
44
|
end
|
53
45
|
|
46
|
+
context "introspection" do
|
47
|
+
context "when anonymous" do
|
48
|
+
before(:each) do
|
49
|
+
@klass = KeyStruct.send(method, :a, :b, :c => 3)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should instrospect keys" do
|
53
|
+
@klass.keys.should == [:a, :b, :c]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should instrospect defaults" do
|
57
|
+
@klass.defaults.should == {:c => 3}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when inherited" do
|
62
|
+
around(:each) do |example|
|
63
|
+
begin
|
64
|
+
class Inherited < KeyStruct.send(method, :p, :q, :r => 4)
|
65
|
+
end
|
66
|
+
example.run
|
67
|
+
ensure
|
68
|
+
Object.send(:remove_const, :Inherited)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
it "should instrospect keys" do
|
72
|
+
Inherited.keys.should == [:p, :q, :r]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should instrospect defaults" do
|
76
|
+
Inherited.defaults.should == {:r => 4}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
54
81
|
context "definition" do
|
55
82
|
it "can handle a default that's an array" do
|
56
83
|
expect { KeyStruct.send(method, :a => []) }.should_not raise_error
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: key_struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-05-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70264478987700 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70264478987700
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: simplecov
|
27
|
-
requirement: &
|
27
|
+
requirement: &70264478986820 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70264478986820
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: simplecov-gem-adapter
|
38
|
-
requirement: &
|
38
|
+
requirement: &70264478985540 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70264478985540
|
47
47
|
description: Defines KeyStruct analogous to Struct, but constructor takes keyword
|
48
48
|
arguments
|
49
49
|
email:
|