key_struct 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(Base).tap{ |klass|
48
+ Class.new.tap{ |klass|
94
49
  klass.class_eval do
95
- @keys = keys
96
- @defaults = defaults
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
@@ -1,3 +1,3 @@
1
1
  module KeyStruct
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -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.1
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: &70230512662240 !ruby/object:Gem::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: *70230512662240
24
+ version_requirements: *70264478987700
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: simplecov
27
- requirement: &70230512661380 !ruby/object:Gem::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: *70230512661380
35
+ version_requirements: *70264478986820
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: simplecov-gem-adapter
38
- requirement: &70230512660520 !ruby/object:Gem::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: *70230512660520
46
+ version_requirements: *70264478985540
47
47
  description: Defines KeyStruct analogous to Struct, but constructor takes keyword
48
48
  arguments
49
49
  email: