msmg_public 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Rakefile +18 -0
- data/lib/comparable_by_attr.rb +43 -0
- data/lib/dig.rb +21 -0
- data/lib/to_hash.rb +46 -0
- data/msmg_public.gemspec +21 -0
- data/readme.md +78 -0
- data/test/test_helper.rb +7 -0
- data/test/unit/test_comparable_by_attr.rb +63 -0
- data/test/unit/test_dig.rb +54 -0
- data/test/unit/test_to_hash.rb +46 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 81762cbf5c6a373790c9b3377ce5b1371e769f45
|
4
|
+
data.tar.gz: 5e05a3462ede5afc08a8e6ecd42162a2caf32f66
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9f9f0219e41a521560b06a41de8a70eb43af9a7ccf9ccff6a0d938844010f1ad7471cb6327f29d479b3a0a4282e5fbfee18dd88e43b470af8882c1a6565f6f87
|
7
|
+
data.tar.gz: 0fd81f23a94643717688aec13815e3befdc8fa64aca41b2510cc5f0b992b4a66aa575b17b0fd29dc0dc543cf6644b05f2e13c1591c1494ba867fa6de833ecfec
|
data/.gitignore
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Tests
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs |= %w[
|
8
|
+
test
|
9
|
+
lib
|
10
|
+
]
|
11
|
+
t.test_files = FileList['test/unit/**/test_*.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
RuboCop::RakeTask.new(:rubocop) do |t|
|
15
|
+
t.fail_on_error = true
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: %i[test rubocop]
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Allow simple definitions for object comparisons
|
2
|
+
module ComparableByAttr
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
# rubocop:disable Metrics/MethodLength class_eval wrapper
|
6
|
+
def self.included(klass)
|
7
|
+
klass.class_eval do
|
8
|
+
@__attr_precedence = nil
|
9
|
+
|
10
|
+
# attr_compare allows selection of specific instance variables and order
|
11
|
+
# to use within the comparison of objects created off the class
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# class IgnoreC
|
15
|
+
# include ComparableByAttr
|
16
|
+
# attr_compare :a, :b
|
17
|
+
#
|
18
|
+
# def initialize(a, b, c)
|
19
|
+
# @a = a
|
20
|
+
# @b = b
|
21
|
+
# @c = c
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Arguments:
|
26
|
+
# *prec = (Optional Precedence Map)
|
27
|
+
def self.attr_compare(*prec)
|
28
|
+
attr_prec = prec.map do |attr|
|
29
|
+
"@#{attr}".to_sym
|
30
|
+
end
|
31
|
+
@__attr_precedence = attr_prec
|
32
|
+
end
|
33
|
+
|
34
|
+
def <=>(other)
|
35
|
+
prec = self.class.instance_variable_get(:@__attr_precedence)
|
36
|
+
comp_order = prec || instance_variables.sort
|
37
|
+
this = comp_order.map { |field| instance_variable_get(field) }
|
38
|
+
that = comp_order.map { |field| other.instance_variable_get(field) }
|
39
|
+
this <=> that
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/dig.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Hash/Array #dig backport from Ruby 2.3.0
|
2
|
+
# Dig method is common to Array and Hash
|
3
|
+
[[], {}].each do |obj|
|
4
|
+
next if obj.respond_to?(:dig)
|
5
|
+
obj.class.class_eval do
|
6
|
+
# dig for values in Array/Hash
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# g = { foo: [10, 11, 12] }
|
10
|
+
# g.dig(:foo, 1) #=> 11
|
11
|
+
#
|
12
|
+
# Arguments:
|
13
|
+
# *keys: (Accessor List)
|
14
|
+
def dig(*keys)
|
15
|
+
elem = self[keys.shift]
|
16
|
+
return elem if keys.empty? || elem.nil?
|
17
|
+
return elem.dig(*keys) if elem.respond_to?(:dig)
|
18
|
+
raise TypeError, "#{elem.class} does not have a #dig method"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/to_hash.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Generic ToHash mixin
|
2
|
+
module ToHash
|
3
|
+
# to_hash generic implementation, generates a hash from object Mixing in this
|
4
|
+
# module from instance variables of the object
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# class Foo
|
8
|
+
# include ToHash
|
9
|
+
# def initialize
|
10
|
+
# @a = 1
|
11
|
+
# @b = 2
|
12
|
+
# @c = 3
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Foo.new.to_hash #=> { :a => 1, :b => 2, :c => 3}
|
17
|
+
# Foo.new.to_hash(:c, 'a') #=> { 'a' => 1, :c => 3 }
|
18
|
+
#
|
19
|
+
# Arguments:
|
20
|
+
# *keys: (Optional key list)
|
21
|
+
def to_hash(*keys)
|
22
|
+
keys = keys.any? ? __named_map(keys) : __instance_map
|
23
|
+
keys = keys.map do |key, val|
|
24
|
+
[key, instance_variable_get(val)]
|
25
|
+
end
|
26
|
+
Hash[keys]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def __named_map(keys)
|
32
|
+
keys = keys.map do |key|
|
33
|
+
[key, "@#{key}".to_sym]
|
34
|
+
end
|
35
|
+
Hash[keys]
|
36
|
+
end
|
37
|
+
|
38
|
+
def __instance_map
|
39
|
+
keys = instance_variables.map do |var|
|
40
|
+
# Eliminate @ in naming key
|
41
|
+
key = var.to_s.delete('@').to_sym
|
42
|
+
[key, var]
|
43
|
+
end
|
44
|
+
Hash[keys]
|
45
|
+
end
|
46
|
+
end
|
data/msmg_public.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class << $LOAD_PATH
|
2
|
+
def merge!(other)
|
3
|
+
replace(self | other)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
$LOAD_PATH.merge! [File.expand_path('../lib', __FILE__)]
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
raise 'RubyGems 2.0 or newer is required.' unless spec.respond_to?(:metadata)
|
11
|
+
spec.name = 'msmg_public'
|
12
|
+
spec.version = '0.1.0'
|
13
|
+
spec.authors = ['Andrew Smith']
|
14
|
+
spec.email = ['andrew.smith at moneysupermarket.com']
|
15
|
+
|
16
|
+
spec.summary = 'Various Ruby Sources'
|
17
|
+
spec.description = 'MSM pubicly available Ruby'
|
18
|
+
# spec.homepage = ''
|
19
|
+
spec.license = 'Apache-2.0'
|
20
|
+
spec.files = `git ls-files -z`.split("\x0")
|
21
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generic mixins
|
2
|
+
|
3
|
+
Released by MSM DevOps group under Apache 2.0 license
|
4
|
+
|
5
|
+
## ToHash
|
6
|
+
|
7
|
+
Add a to_hash method to any class that will produce a hash from all instance variables or that can be called with a parameter set of instance variables in string or symbol form.
|
8
|
+
By default the keys produced are symbols but when called with parameters it will use the parameter form passed for the keys (which can be mixed symbols and strings).
|
9
|
+
In order to make an alternate default of to_hash with a specific set of attributes one may consider implementing to_hash can calling a super method to pass the params i.e.
|
10
|
+
|
11
|
+
class Foo
|
12
|
+
include ToHash
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@foo = 1
|
16
|
+
@bar = 2
|
17
|
+
@boo = 3
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash
|
21
|
+
super(:foo, 'bar')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Foo.new.to_hash == {
|
26
|
+
:foo => 1,
|
27
|
+
'bar' => 2
|
28
|
+
}
|
29
|
+
|
30
|
+
## ComparableByAttr
|
31
|
+
|
32
|
+
|
33
|
+
Adds a default behaviour for <=> based upon instance variables within the class and includes Comparable to produce other comparison operators.
|
34
|
+
Instance variables by default are enumerated, sorted and stored in an array and the arrays are compared with their own l to r behaviour.
|
35
|
+
One may override the instance variables used in the comparison and the order by specifying an attr_compare override in the class definition.
|
36
|
+
|
37
|
+
# instances will be comparable by [@a, @b, @c]
|
38
|
+
class Bar
|
39
|
+
include ComparableByAttr
|
40
|
+
|
41
|
+
def initialize(a, b, c)
|
42
|
+
@a = a
|
43
|
+
@b = b
|
44
|
+
@c = c
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# instances will be comparable by [@c, @a]
|
49
|
+
class Bar
|
50
|
+
include ComparableByAttr
|
51
|
+
attr_compare :c, :a
|
52
|
+
|
53
|
+
def initialize(a, b, c)
|
54
|
+
@a = a
|
55
|
+
@b = b
|
56
|
+
@c = c
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
## dig
|
61
|
+
|
62
|
+
A backport of the Ruby 2.3.0 dig instance method for Hash and Array written in Ruby.
|
63
|
+
|
64
|
+
Since this code aims not to introduce unnecessary modules into the namespace and is targetted at extending Hash and Array directly it is not implemented as a Mixin but rather extends those classes directly using class_eval.
|
65
|
+
|
66
|
+
The Ruby module aims for compatibility based upon the specification stated in the C library comments (which are recorded within the unit test for convenience).
|
67
|
+
|
68
|
+
Documentation from Ruby 2.3.0 states..
|
69
|
+
|
70
|
+
Extracts the nested value specified by the sequence of idx objects by calling dig at each step, returning nil if any intermediate step is nil.
|
71
|
+
|
72
|
+
h = { foo: {bar: {baz: 1}}}
|
73
|
+
|
74
|
+
h.dig(:foo, :bar, :baz) #=> 1
|
75
|
+
h.dig(:foo, :zot, :xyz) #=> nil
|
76
|
+
|
77
|
+
g = { foo: [10, 11, 12] }
|
78
|
+
g.dig(:foo, 1) #=> 11
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Test classes
|
2
|
+
|
3
|
+
require 'comparable_by_attr'
|
4
|
+
|
5
|
+
# Test class
|
6
|
+
class APrecB
|
7
|
+
include ComparableByAttr
|
8
|
+
|
9
|
+
def initialize(a, b)
|
10
|
+
@a = a
|
11
|
+
@b = b
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Test class
|
16
|
+
class BPrecA
|
17
|
+
include ComparableByAttr
|
18
|
+
attr_compare :b, :a
|
19
|
+
|
20
|
+
def initialize(a, b)
|
21
|
+
@a = a
|
22
|
+
@b = b
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Test class
|
27
|
+
class IgnoreC
|
28
|
+
include ComparableByAttr
|
29
|
+
attr_compare :a, :b
|
30
|
+
|
31
|
+
def initialize(a, b, c)
|
32
|
+
@a = a
|
33
|
+
@b = b
|
34
|
+
@c = c
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Unit Test
|
39
|
+
require 'minitest/autorun'
|
40
|
+
|
41
|
+
# rubocop:disable Lint/UselessComparison Unit Test
|
42
|
+
# Unit test
|
43
|
+
class TestComparableByAttr < Minitest::Test
|
44
|
+
def test_a_gt_b_aprecb
|
45
|
+
assert(APrecB.new(2, 1) > APrecB.new(1, 2))
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_a_lt_b_aprecb
|
49
|
+
assert(APrecB.new(1, 2) < APrecB.new(2, 1))
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_a_n_gt_b_aprecb
|
53
|
+
refute(APrecB.new(1, 2) > APrecB.new(1, 2))
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_a_gt_b_bpreca
|
57
|
+
assert(BPrecA.new(1, 2) > BPrecA.new(2, 1))
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_a_eq_b_ignorec
|
61
|
+
assert(IgnoreC.new(1, 1, 2) == IgnoreC.new(1, 1, 2))
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Unit test for #dig
|
2
|
+
|
3
|
+
# Contract from hash.c in Ruby 2.3.0 and later..
|
4
|
+
# rubocop:disable Metrics/LineLength original documentation
|
5
|
+
# /*
|
6
|
+
# * call-seq:
|
7
|
+
# * hsh.dig(key, ...) -> object
|
8
|
+
# *
|
9
|
+
# * Extracts the nested value specified by the sequence of <i>key</i>
|
10
|
+
# * objects by calling +dig+ at each step, returning +nil+ if any
|
11
|
+
# * intermediate step is +nil+.
|
12
|
+
# *
|
13
|
+
# * h = { foo: {bar: {baz: 1}}}
|
14
|
+
# *
|
15
|
+
# * h.dig(:foo, :bar, :baz) #=> 1
|
16
|
+
# * h.dig(:foo, :zot, :xyz) #=> nil
|
17
|
+
# *
|
18
|
+
# * g = { foo: [10, 11, 12] }
|
19
|
+
# * g.dig(:foo, 1) #=> 11
|
20
|
+
# * g.dig(:foo, 1, 0) #=> TypeError: Integer does not have #dig method
|
21
|
+
# * g.dig(:foo, :bar) #=> TypeError: no implicit conversion of Symbol into Integer
|
22
|
+
# */
|
23
|
+
# rubocop:enable all
|
24
|
+
|
25
|
+
require 'minitest/autorun'
|
26
|
+
require 'dig'
|
27
|
+
|
28
|
+
# Unit Test
|
29
|
+
class TestDig < Minitest::Test
|
30
|
+
def setup
|
31
|
+
@h = { foo: { bar: { baz: 1 } } }
|
32
|
+
@g = { foo: [10, 11, 12] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_hash_hash_hash
|
36
|
+
assert_equal(1, @h.dig(:foo, :bar, :baz))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_hash_miss_miss
|
40
|
+
assert_nil(@h.dig(:foo, :zot, :xyz))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_hash_array_fixnum_typerror
|
44
|
+
assert_raises(TypeError) do
|
45
|
+
@g.dig(:foo, 1, 0)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_hash_array_symbol_typerror
|
50
|
+
assert_raises(TypeError) do
|
51
|
+
@g.dig(:foo, :bar)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Test Classes
|
2
|
+
require 'to_hash'
|
3
|
+
|
4
|
+
# Test Class
|
5
|
+
class TestClass
|
6
|
+
include ToHash
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@foo = 1
|
10
|
+
@bar = 2
|
11
|
+
@moo = 'three'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'minitest/autorun'
|
16
|
+
|
17
|
+
# Unit test
|
18
|
+
class TestToHash < Minitest::Test
|
19
|
+
def test_no_param
|
20
|
+
expected = {
|
21
|
+
foo: 1,
|
22
|
+
bar: 2,
|
23
|
+
moo: 'three'
|
24
|
+
}
|
25
|
+
assert_equal expected, TestClass.new.to_hash
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_limited_text
|
29
|
+
expected = {
|
30
|
+
'foo' => 1,
|
31
|
+
'moo' => 'three'
|
32
|
+
}
|
33
|
+
assert_equal expected, TestClass.new.to_hash('foo', 'moo')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Of course with hash ordering is not important and neith should be
|
37
|
+
# the order provided to the parameterisation
|
38
|
+
def test_mixed_keys
|
39
|
+
expected = {
|
40
|
+
'moo' => 'three',
|
41
|
+
foo: 1,
|
42
|
+
bar: 2
|
43
|
+
}
|
44
|
+
assert_equal expected, TestClass.new.to_hash(:foo, 'moo', :bar)
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: msmg_public
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: MSM pubicly available Ruby
|
14
|
+
email:
|
15
|
+
- andrew.smith at moneysupermarket.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Rakefile
|
22
|
+
- lib/comparable_by_attr.rb
|
23
|
+
- lib/dig.rb
|
24
|
+
- lib/to_hash.rb
|
25
|
+
- msmg_public.gemspec
|
26
|
+
- readme.md
|
27
|
+
- test/test_helper.rb
|
28
|
+
- test/unit/test_comparable_by_attr.rb
|
29
|
+
- test/unit/test_dig.rb
|
30
|
+
- test/unit/test_to_hash.rb
|
31
|
+
homepage:
|
32
|
+
licenses:
|
33
|
+
- Apache-2.0
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 2.2.5
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: Various Ruby Sources
|
55
|
+
test_files: []
|