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.
@@ -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: