sumhash 0.0.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.
@@ -0,0 +1,62 @@
1
+ class Hash
2
+ NUMBER_CLASSES = [Integer, Fixnum, Bignum, Float, Rational]
3
+ SUPPORTED_CLASSES = NUMBER_CLASSES + [Hash, OpenStruct]
4
+
5
+ # Plus
6
+ def +(hash)
7
+ (self.keys + hash.keys).inject({}) do |sum, k|
8
+ sum[k] = sum(self[k], hash[k])
9
+ sum
10
+ end
11
+ end
12
+
13
+ # Minus
14
+ def -(hash)
15
+ (self.keys + hash.keys).inject({}) do |sum, k|
16
+ sum[k] = sum(self[k], hash[k], :-)
17
+ sum
18
+ end
19
+ end
20
+
21
+ # Unary minus
22
+ def -@
23
+ self.inject({}) do |res, (k, v)|
24
+ res[k] = SUPPORTED_CLASSES.include?(v.class) ? -v : v
25
+ res
26
+ end
27
+ end
28
+
29
+ # Unary plus
30
+ def +@
31
+ self
32
+ end
33
+
34
+ # Division
35
+ def /(num)
36
+ raise TypeError, "#{num.class} can't be coerced into Float" unless NUMBER_CLASSES.include? num.class
37
+ self.inject({}) do |res, (k, v)|
38
+ res[k] = SUPPORTED_CLASSES.include?(v.class) ? v/num : v
39
+ res
40
+ end
41
+ end
42
+
43
+ # Multiplication
44
+ def *(num)
45
+ raise TypeError, "#{num.class} can't be coerced into Float" unless NUMBER_CLASSES.include? num.class
46
+ self.inject({}) do |res, (k, v)|
47
+ res[k] = SUPPORTED_CLASSES.include?(v.class) ? v*num : v
48
+ res
49
+ end
50
+ end
51
+
52
+ private
53
+ # Can sum Objects if: 1) both numbers; 2) both Hashes; 3) both OpenStructs.
54
+ def sum(n, m, sign=:+)
55
+ if (NUMBER_CLASSES.include?(n.class) && NUMBER_CLASSES.include?(m.class)) || (n.class == Hash && m.class == Hash) || (n.class == OpenStruct && m.class == OpenStruct)
56
+ n.send(sign, m)
57
+ else
58
+ n || m
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,69 @@
1
+ class OpenStruct
2
+ NUMBER_CLASSES = [Integer, Fixnum, Bignum, Float, Rational]
3
+ SUPPORTED_CLASSES = NUMBER_CLASSES + [Hash, OpenStruct]
4
+
5
+ def _fields
6
+ @table.keys.map{|k| k.to_sym }
7
+ end
8
+
9
+ # Plus
10
+ def +(os)
11
+ (self._fields + os._fields).inject(OpenStruct.new()) do |sum, f|
12
+ sum.send(:"#{f}=", sum(self.send(f), os.send(f)))
13
+ sum
14
+ end
15
+ end
16
+
17
+ # Minus
18
+ def -(os)
19
+ (self._fields + os._fields).inject(OpenStruct.new()) do |sum, f|
20
+ sum.send(:"#{f}=", sum(self.send(f), os.send(f), :-))
21
+ sum
22
+ end
23
+ end
24
+
25
+ # Unary minus
26
+ def -@
27
+ self._fields.inject(OpenStruct.new()) do |res, f|
28
+ v = self.send(f)
29
+ res.send(:"#{f}=", SUPPORTED_CLASSES.include?(v.class) ? -v : v)
30
+ res
31
+ end
32
+ end
33
+
34
+ # Unary plus
35
+ def +@
36
+ self
37
+ end
38
+
39
+ # Division
40
+ def /(num)
41
+ raise TypeError, "#{num.class} can't be coerced into Float" unless NUMBER_CLASSES.include? num.class
42
+ self._fields.inject(OpenStruct.new()) do |res, f|
43
+ v = self.send(f)
44
+ res.send(:"#{f}=", SUPPORTED_CLASSES.include?(v.class) ? v/num.to_f : v)
45
+ res
46
+ end
47
+ end
48
+
49
+ # Multiplication
50
+ def *(num)
51
+ raise TypeError, "#{num.class} can't be coerced into Float" unless NUMBER_CLASSES.include? num.class
52
+ self._fields.inject(OpenStruct.new()) do |res, f|
53
+ v = self.send(f)
54
+ res.send(:"#{f}=", SUPPORTED_CLASSES.include?(v.class) && !v.kind_of?(String) ? v*num.to_f : v)
55
+ res
56
+ end
57
+ end
58
+
59
+ private
60
+ # Can sum Objects if: 1) both numbers; 2) both Hashes; 3) both OpenStructs.
61
+ def sum(n, m, sign=:+)
62
+ if (NUMBER_CLASSES.include?(n.class) && NUMBER_CLASSES.include?(m.class)) || (n.class == Hash && m.class == Hash) || (n.class == OpenStruct && m.class == OpenStruct)
63
+ n.send(sign, m)
64
+ else
65
+ n || m
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,4 @@
1
+ module Sumhash
2
+ VERSION = "0.0.2"
3
+ end
4
+
data/lib/sumhash.rb ADDED
@@ -0,0 +1,6 @@
1
+ $:.unshift File.dirname(__FILE__) # for use/testing when no gem is installed
2
+
3
+ require 'ostruct'
4
+ require 'sumhash/hash'
5
+ require 'sumhash/ostruct'
6
+
data/sumhash.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sumhash/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sumhash"
7
+ s.version = Sumhash::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Alex Avoyants"]
10
+ s.email = ["shhavel@gmail.com"]
11
+ s.homepage = "https://github.com/shhavel/sumhash"
12
+ s.summary = %q{Sum operations for Hash & OpenStruct classes}
13
+ s.description = %q{This gem provides summing operations to Hashes and OpenStructs. Works with nested structures. If you need a feature added, send me a message on Github!}
14
+ s.rubyforge_project = "sumhash"
15
+ s.files = [
16
+ "sumhash.gemspec",
17
+ "lib/sumhash.rb",
18
+ "lib/sumhash/hash.rb",
19
+ "lib/sumhash/ostruct.rb",
20
+ "lib/sumhash/version.rb",
21
+ "test/suite.rb",
22
+ "test/test_division.rb",
23
+ "test/test_multiplication.rb",
24
+ "test/test_plus.rb",
25
+ "test/test_unary_minus.rb",
26
+ ]
27
+ s.test_files = [
28
+ "test/suite.rb",
29
+ "test/test_division.rb",
30
+ "test/test_multiplication.rb",
31
+ "test/test_plus.rb",
32
+ "test/test_unary_minus.rb",
33
+ ]
34
+ s.require_paths = ["lib"]
35
+ end
36
+
data/test/suite.rb ADDED
@@ -0,0 +1,5 @@
1
+ tests = Dir["#{File.dirname(__FILE__)}/test_*.rb"]
2
+ tests.each do |file|
3
+ require file
4
+ end
5
+
@@ -0,0 +1,14 @@
1
+ require "ostruct"
2
+ require "#{File.expand_path('../')}/lib/sumhash.rb"
3
+ require "test/unit"
4
+
5
+ class TestDivision < Test::Unit::TestCase
6
+ def test_division
7
+ assert_equal( { n: 2.1, m: 3.2, os: OpenStruct.new(x: 1.1, y: 2.1), s: 'str' },
8
+ { n: 4.2, m: 6.4, os: OpenStruct.new(x: 2.2, y: 4.2), s: 'str' } / 2)
9
+
10
+ assert_raise(TypeError) { { n: 10, m: 14 }/"2" }
11
+ assert_raise(TypeError) { OpenStruct.new({ n: 10, m: 14 })/"2" }
12
+ end
13
+ end
14
+
@@ -0,0 +1,14 @@
1
+ require "ostruct"
2
+ require "#{File.expand_path('../')}/lib/sumhash.rb"
3
+ require "test/unit"
4
+
5
+ class TestMultiplication < Test::Unit::TestCase
6
+ def test_multiplication
7
+ assert_equal( { n: 4.2, m: 6.4, os: OpenStruct.new(x: 2.2, y: 4.2), s: 'str' },
8
+ { n: 2.1, m: 3.2, os: OpenStruct.new(x: 1.1, y: 2.1), s: 'str' } * 2)
9
+
10
+ assert_raise(TypeError) { { n: 5, m: 7 } * "2" }
11
+ assert_raise(TypeError) { OpenStruct.new({ n: 5, m: 7 }) * "2" }
12
+ end
13
+ end
14
+
data/test/test_plus.rb ADDED
@@ -0,0 +1,61 @@
1
+ require "ostruct"
2
+ require "#{File.expand_path('../')}/lib/sumhash.rb"
3
+ require "test/unit"
4
+
5
+ class TestPlus < Test::Unit::TestCase
6
+ def test_hashes
7
+ h1 = { n: 1.0, m: 2.3, s: 'beg' }
8
+ h2 = { n: 3.2 }
9
+ h3 = { m: 1.0, s: 'end' }
10
+
11
+ sum = h1 + h2 + h3
12
+
13
+ assert_equal({ n: 4.2, m: 3.3, s: "beg" }, sum)
14
+ end
15
+
16
+ def test_openstructs
17
+ os1 = OpenStruct.new(n: 1.0, m: 2.3, s: 'beg')
18
+ os2 = OpenStruct.new(n: 3.2)
19
+ os3 = OpenStruct.new(m: 1.0, s: 'end')
20
+
21
+ sum = os1 + os2 + os3
22
+
23
+ assert_equal OpenStruct.new(n: 4.2, m: 3.3, s: "beg"), sum
24
+ end
25
+
26
+ def test_nested_hashes
27
+ h1 = { n: 1.0, m: 2.3, h: { x: 1.0, y: 4.2 } }
28
+ h2 = { n: 3.2 }
29
+ h3 = { m: 1.0, h: { x: 1.2 } }
30
+
31
+ sum = h1 + h2 + h3
32
+
33
+ assert_equal({ n: 4.2, m: 3.3, h: { x: 2.2, y: 4.2 } }, sum)
34
+ end
35
+
36
+ def test_nested_openstructs
37
+ h1 = { n: 1.0, m: 2.3, os: OpenStruct.new(x: 1.0, y: 4.2) }
38
+ h2 = { n: 3.2 }
39
+ h3 = { m: 1.0, os: OpenStruct.new(x: 1.2) }
40
+
41
+ sum = h1 + h2 + h3
42
+
43
+ assert_equal({ n: 4.2, m: 3.3, os: OpenStruct.new(x: 2.2, y: 4.2) }, sum)
44
+ end
45
+
46
+ def test_unary_minus
47
+ assert_equal( { n: -4.2, m: -3.3, os: OpenStruct.new(x: -2.2, y: 4.2), s: 'str' },
48
+ -{ n: 4.2, m: 3.3, os: OpenStruct.new(x: 2.2, y: -4.2), s: 'str' })
49
+ end
50
+
51
+ def test_division
52
+ assert_equal( { n: 2.1, m: 3.2, os: OpenStruct.new(x: 1.1, y: 2.1), s: 'str' },
53
+ { n: 4.2, m: 6.4, os: OpenStruct.new(x: 2.2, y: 4.2), s: 'str' } / 2)
54
+ end
55
+
56
+ def test_multiplication
57
+ assert_equal( { n: 4.2, m: 6.4, os: OpenStruct.new(x: 2.2, y: 4.2), s: 'str' },
58
+ { n: 2.1, m: 3.2, os: OpenStruct.new(x: 1.1, y: 2.1), s: 'str' } * 2)
59
+ end
60
+ end
61
+
@@ -0,0 +1,11 @@
1
+ require "ostruct"
2
+ require "#{File.expand_path('../')}/lib/sumhash.rb"
3
+ require "test/unit"
4
+
5
+ class TestUnaryMinus < Test::Unit::TestCase
6
+ def test_unary_minus
7
+ assert_equal( { n: -4.2, m: -3.3, os: OpenStruct.new(x: -2.2, y: 4.2), s: 'str' },
8
+ -{ n: 4.2, m: 3.3, os: OpenStruct.new(x: 2.2, y: -4.2), s: 'str' })
9
+ end
10
+ end
11
+
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sumhash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Avoyants
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: This gem provides summing operations to Hashes and OpenStructs. Works
15
+ with nested structures. If you need a feature added, send me a message on Github!
16
+ email:
17
+ - shhavel@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - sumhash.gemspec
23
+ - lib/sumhash.rb
24
+ - lib/sumhash/hash.rb
25
+ - lib/sumhash/ostruct.rb
26
+ - lib/sumhash/version.rb
27
+ - test/suite.rb
28
+ - test/test_division.rb
29
+ - test/test_multiplication.rb
30
+ - test/test_plus.rb
31
+ - test/test_unary_minus.rb
32
+ homepage: https://github.com/shhavel/sumhash
33
+ licenses: []
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project: sumhash
52
+ rubygems_version: 1.8.24
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Sum operations for Hash & OpenStruct classes
56
+ test_files:
57
+ - test/suite.rb
58
+ - test/test_division.rb
59
+ - test/test_multiplication.rb
60
+ - test/test_plus.rb
61
+ - test/test_unary_minus.rb