key_value_ext 0.0.3

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/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ pkg
3
+ nbproject
4
+ TODO.txt
5
+ *.gemspec
6
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2009 Jeff Patmon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = Key Value Extensions for Array
2
+
3
+ A library of key-value operations
4
+
5
+ == Resources
6
+
7
+ Install
8
+
9
+ * sudo gem install key_value_ext
10
+
11
+ Use
12
+
13
+ * require 'key_value_ext'
14
+
15
+
16
+ == Description
17
+
18
+ A key-value array is one with the structure [[key1, val2], [key2, [value2, value3, ...]], ... ].
19
+
20
+ This library provides the following functions
21
+
22
+ * map_key_value
23
+ * group_key_value
24
+
25
+ for creating key-value arrays from arrays and hashes, and
26
+
27
+ * keys
28
+ * values
29
+ * consolidate
30
+ * expand
31
+ * invert_key_value
32
+ * to_hash
33
+
34
+ for arrays that are key-value arrays
35
+
36
+ == Usage
37
+
38
+ Good for laying out complex nested views and forms when group_by is not enough.
39
+
40
+ See the spec for examples.
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ #require 'rake/testtask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ gem 'gem_version', '>= 0.0.1'
5
+ require 'gem_version'
6
+ #require 'rake/contrib/sshpublisher'
7
+
8
+ spec = Gem::Specification.new do |s|
9
+ s.name = 'key_value_ext'
10
+ s.version = GemVersion.next_version
11
+ s.platform = Gem::Platform::RUBY
12
+ s.required_ruby_version = '>= 1.8.7'
13
+ s.description = 'Array and hash extensions for key-value operations.'
14
+ s.summary = 'Good for laying out complex nested views and forms when group_by is not enough.'
15
+
16
+ exclude_folders = '' # 'spec/rails/{doc,lib,log,nbproject,tmp,vendor,test}'
17
+ exclude_files = [] # FileList['**/*.log'] + FileList[exclude_folders+'/**/*'] + FileList[exclude_folders]
18
+ s.files = FileList['{lib,spec}/**/*'] + %w(init.rb LICENSE Rakefile README.rdoc .gitignore) - exclude_files
19
+ s.require_path = 'lib'
20
+ s.has_rdoc = true
21
+ s.test_files = Dir['spec/*_spec.rb']
22
+
23
+ s.author = 'Jeff Patmon'
24
+ s.email = 'jpatmon@gmail.com'
25
+ s.homepage = 'http://github.com/jeffp/key_value_ext/tree/master'
26
+ end
27
+
28
+ require 'spec/version'
29
+ require 'spec/rake/spectask'
30
+
31
+ desc "Run specs"
32
+ Spec::Rake::SpecTask.new(:spec) do |t|
33
+ t.spec_files = FileList['spec/*_spec.rb']
34
+ t.libs << 'lib' << 'spec'
35
+ t.rcov = false
36
+ t.spec_opts = ['--options', 'spec/spec.opts']
37
+ #t.rcov_dir = 'coverage'
38
+ #t.rcov_opts = ['--exclude', "kernel,load-diff-lcs\.rb,instance_exec\.rb,lib/spec.rb,lib/spec/runner.rb,^spec/*,bin/spec,examples,/gems,/Library/Ruby,\.autotest,#{ENV['GEM_HOME']}"]
39
+ end
40
+
41
+ desc "Generate documentation for the #{spec.name} gem."
42
+ Rake::RDocTask.new(:rdoc) do |rdoc|
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = spec.name
45
+ #rdoc.template = '../rdoc_template.rb'
46
+ rdoc.options << '--line-numbers' << '--inline-source'
47
+ rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'lib/**/*.rb')
48
+ end
49
+
50
+ desc "Clean up gem build"
51
+ task :clean do
52
+ FileUtil.rm_f Dir.glob('*.gem')
53
+ end
54
+
55
+ desc 'Generate a gemspec file.'
56
+ task :gemspec do
57
+ File.open("#{spec.name}.gemspec", 'w') do |f|
58
+ f.write spec.to_ruby
59
+ end
60
+ GemVersion.increment_version
61
+ GemVersion.commit_and_push
62
+ end
63
+
64
+ Rake::GemPackageTask.new(spec) do |p|
65
+ p.gem_spec = spec
66
+ p.need_tar = RUBY_PLATFORM =~ /mswin/ ? false : true
67
+ p.need_zip = true
68
+ end
69
+
70
+ Dir['tasks/**/*.rake'].each {|rake| load rake}
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'arspy'
@@ -0,0 +1,75 @@
1
+ class Object
2
+ def to_a
3
+ self.is_a?(Array) ? self : [self]
4
+ end
5
+ end
6
+
7
+ class Array
8
+ def map_key_value(key=nil, &block)
9
+ self.map{|elem| [(key.nil? ? elem : elem.__send__(key.to_sym)), (block_given? ? block.call(elem) : elem)] }
10
+ end
11
+ alias_method :mapkeyvalue, :map_key_value
12
+ def to_hash
13
+ acts_as_key_value!(:to_hash)
14
+ Hash[*self.consolidate.inject([]){|array, pair| array << pair.first << pair.last}]
15
+ end
16
+ def group_key_value(attribute, &block)
17
+ self.mapkeyvalue(attribute, &block).consolidate
18
+ end
19
+ alias_method :groupkeyvalue, :group_key_value
20
+ def consolidate
21
+ acts_as_key_value!(:consolidate)
22
+ keys, index = {}, -1
23
+ kv = self.dup
24
+ kv.delete_if do |pair|
25
+ index += 1
26
+ key_index = keys[pair.first]
27
+ if key_index
28
+ kv[key_index][1] = kv[key_index][1].to_a + pair.last.to_a
29
+ else
30
+ keys[pair.first] = index
31
+ end
32
+ key_index
33
+ end
34
+ end
35
+ def expand
36
+ acts_as_key_value!(:expand)
37
+ self.inject([]) do |result, pair|
38
+ result + pair.last.to_a.map{|val| [pair.first, val]}
39
+ end
40
+ end
41
+
42
+ def flip
43
+ acts_as_key_value!(:swap)
44
+ self.map{|pair| [pair.last, pair.first]}
45
+ end
46
+
47
+ def invert_key_value
48
+ acts_as_key_value!(:invert)
49
+ self.expand.flip.consolidate
50
+ end
51
+
52
+ def keys
53
+ acts_as_key_value!(:keys)
54
+ self.map{|pair| pair.first }
55
+ end
56
+ def values
57
+ acts_as_key_value!(:values)
58
+ self.map{|pair| pair.last }
59
+ end
60
+ private
61
+ def acts_as_key_value!(method)
62
+ raise "Cannot call '#{method}' on an non-key-value array" unless (self.empty? || self.first.is_a?(Array) && self.first.size == 2)
63
+ end
64
+ end
65
+
66
+ class Hash
67
+ def map_key_value(key=nil, &block)
68
+ self.map{|first, last| [(key.nil? ? first : last.__send__(key.to_sym)), (block_given? ? block.call(first, last) : last)]}
69
+ end
70
+ alias_method :mapkeyvalue, :map_key_value
71
+ def invert_key_value
72
+ self.to_a.invert_key_value
73
+ end
74
+ end
75
+
@@ -0,0 +1,137 @@
1
+ require 'ostruct'
2
+ require File.dirname(__FILE__) + '/../lib/key_value_ext'
3
+
4
+
5
+ describe 'mapkeyvalue' do
6
+ describe 'with no param and no block' do
7
+ describe 'for an array' do
8
+ it "should may the elements to themselves maintaining order" do
9
+ [:a, :b, :c].mapkeyvalue.should == [[:a, :a], [:b, :b], [:c, :c]]
10
+ end
11
+ end
12
+ describe 'for a hash ' do
13
+ it "should group by the key and produce a 2-dim key-value array with no guaranteed order" do
14
+ {:a=>1, :b=>2, :c=>3}.mapkeyvalue.should =~ [[:a, 1], [:b, 2], [:c, 3]]
15
+ end
16
+ end
17
+ end
18
+ describe 'with no param but with a block' do
19
+ describe 'for an array' do
20
+ it "should group the block content by the array elements maintaining order" do
21
+ [:a, :b, :c].mapkeyvalue{|elem| elem.to_s }.should == [[:a, 'a'], [:b, 'b'], [:c, 'c']]
22
+ end
23
+ end
24
+ describe 'for a hash' do
25
+ it "should group the block content by the hash keys producing a key-value array with no guaranteed order" do
26
+ {:a=>1, :b=>2, :c=>3}.mapkeyvalue{|k, v| k.to_s + v.to_s }.should =~ [[:a, 'a1'], [:b, 'b2'], [:c, 'c3']]
27
+ end
28
+ end
29
+ end
30
+ describe 'with a param but with no block' do
31
+ describe 'for an array of objects' do
32
+ it "should group the array elements by the value/object returned by the method specified in the param" do
33
+ a, b, c = OpenStruct.new(:meth=>1), OpenStruct.new(:meth=>2), OpenStruct.new(:meth=>3)
34
+ [a, b, c].mapkeyvalue(:meth).should == [[1, a], [2, b], [3, c]]
35
+ end
36
+ end
37
+ describe 'for a hash' do
38
+ it "should group the values by the value/object returned by the method specified in the param" do
39
+ a, b, c = OpenStruct.new(:meth=>1), OpenStruct.new(:meth=>2), OpenStruct.new(:meth=>3)
40
+ {:a=>a, :b=>b, :c=>c}.mapkeyvalue(:meth).should =~ [[1,a], [2,b], [3,c]]
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ describe 'consolidate' do
47
+ describe 'for a non-key-value array' do
48
+ it "should raise exception" do
49
+ lambda { [1, 2, 3].consolidate }.should raise_exception(/consolidate/)
50
+ end
51
+ end
52
+ describe 'for a key-value array' do
53
+ it "should consolidate values into arrays grouped by the same key maintaining first-in-line order" do
54
+ [[:a, 1], [:b, 2], [:c, 3], [:a, 4]].consolidate.should == [[:a, [1,4]], [:b, 2], [:c, 3]]
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'to_hash' do
60
+ describe 'for a non-key-value array' do
61
+ it "should raise exception" do
62
+ lambda { [1,2,3].to_hash }.should raise_exception(/to_hash/)
63
+ end
64
+ end
65
+ describe 'for a key-value array' do
66
+ it "should return a hash of keys containing values array preserving values with arrays" do
67
+ [[:a, 1], [:b, [2,3]], [:c, nil]].to_hash.should == {:a=>1, :b=>[2,3], :c=>nil}
68
+ end
69
+ it "should consolidate duplicate keys" do
70
+ [[:a, 1], [:b, [2,3]], [:c, nil], [:a, 5]].to_hash.should == {:a=>[1,5], :b=>[2,3], :c=>nil}
71
+ end
72
+ end
73
+ end
74
+
75
+ describe 'keys' do
76
+ describe 'for a non-key-value array' do
77
+ it "should raise exception" do
78
+ lambda { [1,2,3].keys }.should raise_exception(/keys/)
79
+ end
80
+ end
81
+ describe 'for a key-value array' do
82
+ it "should return an array of the keys" do
83
+ [[:a, 1], [:b, 2], [:c, 3]].keys.should == [:a, :b, :c]
84
+ end
85
+ end
86
+ end
87
+
88
+ describe 'values' do
89
+ describe 'for a non-key-value array' do
90
+ it "should raise exception" do
91
+ lambda { [1,2,3].values }.should raise_exception(/values/)
92
+ end
93
+ end
94
+ describe 'for a key-value array' do
95
+ it "should return an array of the values" do
96
+ [[:a, 1], [:b, 2], [:c, 3]].values.should == [1,2,3]
97
+ end
98
+ end
99
+ end
100
+
101
+ describe 'expand' do
102
+ describe 'for a non-key-value array' do
103
+ it "should raise exception" do
104
+ lambda { [1,2,3].expand }.should raise_exception(/expand/)
105
+ end
106
+ end
107
+ describe 'for a key-value array' do
108
+ it "should break out arrays of values" do
109
+ [[:a, [1, 2]], [:b, 1], [:c, [4,5]]].expand.should == [[:a,1],[:a,2],[:b,1],[:c,4],[:c,5]]
110
+ end
111
+ end
112
+ end
113
+
114
+ describe 'invert_key_value' do
115
+ describe 'for a non-key-value array' do
116
+ it "should raise exception" do
117
+ lambda { [1,2,3].invert_key_value }.should raise_exception(/invert/)
118
+ end
119
+ end
120
+ describe 'for a key-value array' do
121
+ it "should return a key-value array with keys constructed from values referencing previous keys preserving order" do
122
+ [[:a, 1], [:b, 2], [:c, 3]].invert_key_value.should == [[1, :a], [2, :b], [3, :c]]
123
+ end
124
+ it "should invert for values with arrays" do
125
+ [[:a, [1,2]], [:b, 2], [:c, [3,2]]].invert_key_value.should == [[1, :a], [2, [:a,:b,:c]], [3, :c]]
126
+ end
127
+ end
128
+ end
129
+
130
+ describe 'Object.to_a' do
131
+ it 'should convert an object to an array unless it is an array' do
132
+ 1.to_a.should == [1]
133
+ 'str'.to_a.should == ['str']
134
+ [1,'str'].to_a.should == [1,'str']
135
+ end
136
+ end
137
+
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: key_value_ext
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 3
9
+ version: 0.0.3
10
+ platform: ruby
11
+ authors:
12
+ - Jeff Patmon
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-13 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Array and hash extensions for key-value operations.
22
+ email: jpatmon@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/key_value_ext.rb
31
+ - spec/key_value_spec.rb
32
+ - spec/spec.opts
33
+ - init.rb
34
+ - LICENSE
35
+ - Rakefile
36
+ - README.rdoc
37
+ - .gitignore
38
+ has_rdoc: true
39
+ homepage: http://github.com/jeffp/key_value_ext/tree/master
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 1
53
+ - 8
54
+ - 7
55
+ version: 1.8.7
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.6
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Good for laying out complex nested views and forms when group_by is not enough.
70
+ test_files:
71
+ - spec/key_value_spec.rb