key_struct 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -74,13 +74,33 @@ The struct initializer checks for invalid arguments:
74
74
 
75
75
  name = Name.new(:this_is_a_typo => "Xavier") # --> raises ArgumentError
76
76
 
77
- == Equaltiy
77
+ == Comparison
78
78
 
79
79
  KeyStruct classes define the == operator, which returns true iff all corresponding struct members are equal (likewise via ==)
80
80
 
81
81
  Name.new(:first => "John", :last => "Doe") == Name.new(:first => "John", :last => "Doe") # --> true
82
82
  Name.new(:first => "John", :last => "Doe") == Name.new(:first => "Jane", :last => "Doe") # --> false
83
83
 
84
+ As a convenience when a well-defined ordering is needed, KeyStruct classes
85
+ defines the <=> operator and includes the +Comparable+ module. The <=>
86
+ operator applies <=> to the coresponding struct members sequentially,
87
+ returning the first that is non-0. The comparison is performed in the order
88
+ the keys were listed in the class definition, so the first key is the
89
+ primary comparison key, and so on down the line. Thus:
90
+
91
+ Name = KeyStruct[:first, :last]
92
+ Name.new(:first => "Abigail", :last => "Zither") <=> Name.new(:first => "Zenobia", :last => "Aardvark") # --> -1
93
+
94
+ LastFirst = KeyStruct[:last, :first]
95
+ LastFirst.new(:first => "Abigail", :last => "Zither") <=> LastFirst.new(:first => "Zenobia", :last => "Aardvark") # --> +1
96
+
97
+ == Converting to a hash
98
+
99
+ KeyStruct classes define a +to_hash+ method that returns a hash containing
100
+ all members and their values:
101
+
102
+ Name.new(:first => "Jack", :last => "Ripper").to_hash # --> {:first => "Jack", :last => "Ripper")
103
+
84
104
  == Installation
85
105
 
86
106
  Install via:
@@ -97,6 +117,12 @@ Requires ruby >= 1.9.2. (Has been tested on MRI 1.9.2 and MRI 1.9.3)
97
117
 
98
118
  == History
99
119
 
120
+ Release Notes:
121
+
122
+ * 0.2.0 - Introduced <=> and to_hash
123
+ * 0.1.0 - Introduced ==
124
+ * 0.0.1 - Initial version
125
+
100
126
  Past: There was some discussion around this idea in this thread:
101
127
  http://www.ruby-forum.com/topic/138124 in 2008.
102
128
 
@@ -1,38 +1,2 @@
1
1
  require "key_struct/version"
2
-
3
- module KeyStruct
4
-
5
- def self.reader(*keys)
6
- define_key_struct(:attr_reader, keys)
7
- end
8
-
9
- def self.accessor(*keys)
10
- define_key_struct(:attr_accessor, keys)
11
- end
12
-
13
- instance_eval do
14
- alias :[] :accessor
15
- end
16
-
17
- private
18
-
19
- def self.define_key_struct(access, keys)
20
- Class.new.class_eval do
21
- keyvalues = Hash[*keys.map{|key| (Hash === key) ? key.to_a : [key, nil]}.flatten(2)]
22
- keys = keyvalues.keys
23
- send access, *keys
24
- define_method(:initialize) do |args={}|
25
- args = keyvalues.merge(args)
26
- 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 #{keys.map(&:inspect).join(' ')}" if args.any?
30
- end
31
- define_method(:==) do |other|
32
- keys.all?{|key| self.send(key) == other.send(key)}
33
- end
34
- self
35
- end
36
- end
37
-
38
- end
2
+ require "key_struct/key_struct"
@@ -0,0 +1,48 @@
1
+ module KeyStruct
2
+
3
+ def self.reader(*keys)
4
+ define_key_struct(:attr_reader, keys)
5
+ end
6
+
7
+ def self.accessor(*keys)
8
+ define_key_struct(:attr_accessor, keys)
9
+ end
10
+
11
+ instance_eval do
12
+ alias :[] :accessor
13
+ end
14
+
15
+ private
16
+
17
+ def self.define_key_struct(access, keys)
18
+ Class.new.class_eval do
19
+ include Comparable
20
+ keyvalues = Hash[*keys.map{|key| (Hash === key) ? key.to_a : [key, nil]}.flatten(2)]
21
+ keys = keyvalues.keys
22
+ send access, *keys
23
+ define_method(:initialize) do |args={}|
24
+ args = keyvalues.merge(args)
25
+ keys.each do |key|
26
+ instance_variable_set("@#{key}".to_sym, args.delete(key))
27
+ end
28
+ raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')}; KeyStruct accepts #{keys.map(&:inspect).join(' ')}" if args.any?
29
+ end
30
+ define_method(:==) do |other|
31
+ keys.all?{|key| self.send(key) == other.send(key)}
32
+ end
33
+ define_method(:<=>) do |other|
34
+ keys.each do |key|
35
+ cmp = (self.send(key) <=> other.send(key))
36
+ return cmp unless cmp == 0
37
+ end
38
+ 0
39
+ end
40
+ define_method(:to_hash) do
41
+ Hash[*keys.map{ |key| [key, self.send(key)]}.flatten(2)]
42
+ end
43
+ self
44
+ end
45
+ end
46
+
47
+ end
48
+
@@ -1,3 +1,3 @@
1
1
  module KeyStruct
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -113,15 +113,36 @@ describe "KeyStruct" do
113
113
  end
114
114
  end
115
115
 
116
- context "==" do
116
+ context "comparison" do
117
117
  before(:all) do
118
- @klass = KeyStruct.accessor(:a, :b)
118
+ @klass = KeyStruct.accessor(:a, :b, :c)
119
119
  end
120
120
 
121
121
  it "returns true iff all members are ==" do
122
122
  @klass.new(:a => 1, :b => 2).should == @klass.new(:a => 1, :b => 2)
123
123
  @klass.new(:a => 1, :b => 2).should_not == @klass.new(:a => 1, :b => 3)
124
124
  end
125
+
126
+ it "compares based on primary key" do
127
+ @klass.new(:a => 1, :b => 2).should < @klass.new(:a => 2, :b => 2)
128
+ end
129
+
130
+ it "compares based on second key if first is equal" do
131
+ @klass.new(:a => 1, :b => 2).should > @klass.new(:a => 1, :b => 1)
132
+ end
133
+
134
+ it "compares based on third key if first two are equal" do
135
+ @klass.new(:a => 1, :b => 2, :c => 3).should > @klass.new(:a => 1, :b => 2, :c => 1)
136
+ end
137
+
138
+ it "returns zero for <=> if all are equal" do
139
+ (@klass.new(:a => 1, :b => 2) <=> @klass.new(:a => 1, :b => 2)).should == 0
140
+ end
141
+
142
+ end
143
+
144
+ it "returns hash using to_hash" do
145
+ KeyStruct.accessor(:a => 3, :b => 4).new.to_hash.should == {:a => 3, :b => 4}
125
146
  end
126
147
 
127
148
 
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.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-29 00:00:00.000000000 Z
12
+ date: 2011-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70161596448140 !ruby/object:Gem::Requirement
16
+ requirement: &70350516522720 !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: *70161596448140
24
+ version_requirements: *70350516522720
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: simplecov
27
- requirement: &70161596447560 !ruby/object:Gem::Requirement
27
+ requirement: &70350516521800 !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: *70161596447560
35
+ version_requirements: *70350516521800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: simplecov-gem-adapter
38
- requirement: &70161596438560 !ruby/object:Gem::Requirement
38
+ requirement: &70350516536920 !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: *70161596438560
46
+ version_requirements: *70350516536920
47
47
  description: Defines KeyStruct analogous to Struct, but constructor takes keyword
48
48
  arguments
49
49
  email:
@@ -61,6 +61,7 @@ files:
61
61
  - Rakefile
62
62
  - key_struct.gemspec
63
63
  - lib/key_struct.rb
64
+ - lib/key_struct/key_struct.rb
64
65
  - lib/key_struct/version.rb
65
66
  - spec/key_struct_spec.rb
66
67
  - spec/spec_helper.rb