key_value_ext 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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