triad 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b102ba1a28f4a9bf80e239083ec5cfa6ecfa02cd
4
+ data.tar.gz: a2fbdcae55dae2126fdc315060bc2f9109b7a2aa
5
+ SHA512:
6
+ metadata.gz: 42e73cadff398ec9c7c751be0f4492990b0b2f7ac122694d750684ded08511f1f60e8a3addad520a61d2bf18e10a1467f23c4b3a13d88d9c037cac0610b278d5
7
+ data.tar.gz: eef77531a5080e84015c3c2664dba5f3222107a9d7c2b4139dcc21814deec4117827657706b8f968c42952fe69df33bdf1e3f45057f9e6a679b61c1c4e184a81
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - ruby-head
7
+ - jruby-head
8
+ - rbx-19mode
9
+ env:
10
+ - COVERALLS=true
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: ruby-head
14
+ - rvm: jruby-head
15
+ - rvm: rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in triad.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "rake"
8
+ gem "simplecov"
9
+ gem "minitest"
10
+ gem "coveralls"
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 'Jim Gay'
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # Triad
2
+
3
+ [![Build Status](https://travis-ci.org/saturnflyer/triad.png?branch=master)](https://travis-ci.org/saturnflyer/triad)
4
+ [![Code Climate](https://codeclimate.com/github/saturnflyer/triad.png)](https://codeclimate.com/github/saturnflyer/triad)
5
+ [![Coverage Status](https://coveralls.io/repos/saturnflyer/triad/badge.png)](https://coveralls.io/r/saturnflyer/triad)
6
+ [![Gem Version](https://badge.fury.io/rb/triad.png)](http://badge.fury.io/rb/triad)
7
+
8
+ A Triad is like a Set, or a collection of three-part arrays.
9
+
10
+ A Triad is a collection of items each with a `key`, `descriptor`, and `value`.
11
+
12
+ Each `key` must be a unique symbol.
13
+ Each `descriptor` must be a string.
14
+ Each `value` must not be a symbol nor a string.
15
+
16
+ ```ruby
17
+ user = Object.new
18
+
19
+ map = Triad.new
20
+ map << [:admin, 'Admin', user]
21
+
22
+ map.keys('Admin') #=> [:admin]
23
+ map.values('Admin') #=> [user]
24
+ map.descriptors('Admin') #=> ['Admin'] or raise DescriptorNotPresent
25
+
26
+ map.descriptors(user) #=> ['Admin']
27
+ map.keys(user) #=> [:admin]
28
+ map.values(user) #=> [user] or raise ValueNotPresent
29
+
30
+ map.values(:admin) #=> [user]
31
+ map.descriptors(:admin) #=> ['Admin']
32
+ map.keys(:admin) #=> [:admin] or raise KeyNotPresent
33
+
34
+ map.each do |key, descriptor, value|
35
+ #...
36
+ end
37
+ ```
38
+
39
+ ## Installation
40
+
41
+ Add this line to your application's Gemfile:
42
+
43
+ ```ruby
44
+ gem 'triad'
45
+ ```
46
+
47
+ And then execute:
48
+
49
+ $ bundle
50
+
51
+ Or install it yourself as:
52
+
53
+ $ gem install triad
54
+
55
+ ## Contributing
56
+
57
+ 1. Fork it
58
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
59
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
60
+ 4. Push to the branch (`git push origin my-new-feature`)
61
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ t.test_files = FileList['test/*_test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,3 @@
1
+ class Triad
2
+ VERSION = "0.1.0"
3
+ end
data/lib/triad.rb ADDED
@@ -0,0 +1,87 @@
1
+ require "triad/version"
2
+
3
+ class Triad
4
+ include Enumerable
5
+
6
+ class InvalidAddition < StandardError
7
+ def message
8
+ "your array length must be 3"
9
+ end
10
+ end
11
+ class ValueNotPresent < StandardError; end
12
+ class DescriptorNotPresent < StandardError; end
13
+ class KeyNotPresent < StandardError; end
14
+
15
+ # stored as {key => ['Descriptor', value]}
16
+ def initialize(*args)
17
+ @storage = {}
18
+ end
19
+ attr_reader :storage
20
+ private :storage
21
+
22
+ def keys(arg)
23
+ with_interest(arg).map{|key, _, _| key }
24
+ end
25
+
26
+ def descriptors(arg)
27
+ with_interest(arg).map{|_, descriptor, _| descriptor }
28
+ end
29
+
30
+ def values(arg)
31
+ with_interest(arg).map{|_, _, value| value }
32
+ end
33
+
34
+ def <<(array)
35
+ array_key = array.find{|item| item.is_a?(Symbol) }
36
+ raise InvalidAddition if array.length != 3 || key_exists?(array_key)
37
+
38
+ array_descriptor = array.find{|item| item.is_a?(String) }
39
+ array_value = array.find{|item| !item.is_a?(String) && !item.is_a?(Symbol) }
40
+
41
+ storage[array_key] = [array_descriptor, array_value]
42
+ self
43
+ end
44
+
45
+ def each
46
+ storage.each do |key, (descriptor, value)|
47
+ yield key, descriptor, value
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def key_exists?(key)
54
+ storage.has_key?(key)
55
+ end
56
+
57
+ def positions
58
+ [:key, :descriptor, :value]
59
+ end
60
+
61
+ def argument_type(arg)
62
+ case arg
63
+ when Symbol then :key
64
+ when String then :descriptor
65
+ else :value
66
+ end
67
+ end
68
+
69
+ def raise_error(type)
70
+ error_name = type.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
71
+ error_class = Triad.const_get("#{error_name}NotPresent")
72
+ raise error_class.new
73
+ end
74
+
75
+ def with_interest(interest)
76
+ type = argument_type(interest)
77
+ index = positions.index(type)
78
+
79
+ lookup = storage.select{|key, array|
80
+ [key, *array][index] == interest
81
+ }.map{|key, array| [key, *array] }
82
+
83
+ raise_error(type) if lookup.empty?
84
+
85
+ lookup
86
+ end
87
+ end
@@ -0,0 +1,13 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter 'test'
4
+ end
5
+ require 'coveralls'
6
+
7
+ if ENV['COVERALLS']
8
+ Coveralls.wear!
9
+ end
10
+
11
+ require 'minitest/autorun'
12
+
13
+ require 'triad'
@@ -0,0 +1,173 @@
1
+ require 'test_helper'
2
+
3
+ describe Triad, '#<<' do
4
+ let(:triad){ Triad.new }
5
+
6
+ it 'shovels 3 item arrays' do
7
+ assert triad << [:test, 'Test', Object.new]
8
+ end
9
+
10
+ it 'rejects arrays with more than 3 items' do
11
+ error = assert_raises(Triad::InvalidAddition){
12
+ triad << [:test, 'Test', Object.new, 'Other']
13
+ }
14
+ assert_match /array length must be 3/, error.message
15
+ end
16
+
17
+ it 'rejects arrays with fewer than 3 items' do
18
+ assert_raises(Triad::InvalidAddition){
19
+ triad << [:test, 'Test']
20
+ }
21
+ end
22
+
23
+ it 'rejects arrays with an existing key' do
24
+ triad << [:test, 'Test', Object.new]
25
+ assert_raises(Triad::InvalidAddition){
26
+ triad << [:test, 'More', Object.new]
27
+ }
28
+ end
29
+
30
+ it 'assigns symbol as key' do
31
+ object = Object.new
32
+ triad << ['OutOfOrder', object, :surprise]
33
+ assert_equal [:surprise], triad.keys('OutOfOrder')
34
+ assert_equal [:surprise], triad.keys(object)
35
+ end
36
+
37
+ it 'assigns string as descriptor' do
38
+ object = Object.new
39
+ triad << ['OutOfOrder', object, :surprise]
40
+ assert_equal ['OutOfOrder'], triad.descriptors(:surprise)
41
+ assert_equal ['OutOfOrder'], triad.descriptors(object)
42
+ end
43
+
44
+ it 'assigns non-symbol, non-string objects as value' do
45
+ object = Object.new
46
+ triad << ['OutOfOrder', object, :surprise]
47
+ assert_equal [object], triad.values(:surprise)
48
+ assert_equal [object], triad.values('OutOfOrder')
49
+ end
50
+ end
51
+
52
+ describe Triad, '#keys' do
53
+ let(:user){ Object.new }
54
+ let(:triad){
55
+ tri = Triad.new
56
+ tri << [:admin, 'Admin', user]
57
+ tri
58
+ }
59
+
60
+ it 'returns the key for the given descriptor' do
61
+ assert_equal [:admin], triad.keys('Admin')
62
+ end
63
+
64
+ it 'returns the key for the given value' do
65
+ assert_equal [:admin], triad.keys(user)
66
+ end
67
+
68
+ it 'returns the keys for the given key' do
69
+ assert_equal [:admin], triad.keys(:admin)
70
+ end
71
+
72
+ it 'errors when the given key is not found' do
73
+ assert_raises(Triad::KeyNotPresent){
74
+ triad.keys(:invalid_key)
75
+ }
76
+ end
77
+
78
+ it 'errors when the given descriptor is not found' do
79
+ assert_raises(Triad::DescriptorNotPresent){
80
+ triad.keys('Invalid Descriptor')
81
+ }
82
+ end
83
+
84
+ it 'errors when the given value is not found' do
85
+ assert_raises(Triad::ValueNotPresent){
86
+ triad.keys(Object.new)
87
+ }
88
+ end
89
+ end
90
+
91
+ describe Triad, '#descriptors' do
92
+ let(:user){ Object.new }
93
+ let(:triad){
94
+ tri = Triad.new
95
+ tri << [:admin, 'Admin', user]
96
+ tri
97
+ }
98
+
99
+ it 'returns the descriptor for the given key' do
100
+ assert_equal ['Admin'], triad.descriptors(:admin)
101
+ end
102
+
103
+ it 'returns the descriptor for the given value' do
104
+ assert_equal ['Admin'], triad.descriptors(user)
105
+ end
106
+
107
+ it 'returns the descriptors for the given descriptor' do
108
+ assert_equal ['Admin'], triad.descriptors('Admin')
109
+ end
110
+
111
+ it 'errors when the given descriptor is not found' do
112
+ assert_raises(Triad::DescriptorNotPresent){
113
+ triad.descriptors('Not Present')
114
+ }
115
+ end
116
+
117
+ it 'errors when the given key is not found' do
118
+ assert_raises(Triad::KeyNotPresent){
119
+ triad.descriptors(:invalid_key)
120
+ }
121
+ end
122
+
123
+ it 'errors when the given value is not found' do
124
+ assert_raises(Triad::ValueNotPresent){
125
+ triad.descriptors(Object.new)
126
+ }
127
+ end
128
+ end
129
+
130
+ describe Triad, '#values' do
131
+ let(:user){ Object.new }
132
+ let(:triad){
133
+ tri = Triad.new
134
+ tri << [:admin, 'Admin', user]
135
+ tri
136
+ }
137
+
138
+ it 'returns the value for the given key' do
139
+ assert_equal [user], triad.values(:admin)
140
+ end
141
+
142
+ it 'returns the value for the given descriptor' do
143
+ assert_equal [user], triad.values('Admin')
144
+ end
145
+
146
+ it 'errors when the given key is not found' do
147
+ assert_raises(Triad::KeyNotPresent){
148
+ triad.values(:invalid_key)
149
+ }
150
+ end
151
+
152
+ it 'errors when the given descriptor is not found' do
153
+ assert_raises(Triad::DescriptorNotPresent){
154
+ triad.values('Invalid Descriptor')
155
+ }
156
+ end
157
+ end
158
+
159
+ describe Triad, 'enumeration' do
160
+ let(:user){ Object.new }
161
+ let(:triad){
162
+ tri = Triad.new
163
+ tri << [:admin, 'Admin', user]
164
+ tri
165
+ }
166
+ it 'yields each triad as 3 block variables' do
167
+ result = ''
168
+ triad.each do |key, descriptor, value|
169
+ result << "key: #{key}, descriptor: #{descriptor}, value: #{value.class.name}"
170
+ end
171
+ assert_equal 'key: admin, descriptor: Admin, value: Object', result
172
+ end
173
+ end
data/triad.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'triad/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "triad"
8
+ spec.version = Triad::VERSION
9
+ spec.authors = ["'Jim Gay'"]
10
+ spec.email = ["jim@saturnflyer.com"]
11
+ spec.description = %q{Triad allows you to access data from keys, descriptors, and values}
12
+ spec.summary = %q{Manage a collection with 3 data points}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: triad
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - '''Jim Gay'''
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Triad allows you to access data from keys, descriptors, and values
42
+ email:
43
+ - jim@saturnflyer.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .travis.yml
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - lib/triad.rb
55
+ - lib/triad/version.rb
56
+ - test/test_helper.rb
57
+ - test/triad_test.rb
58
+ - triad.gemspec
59
+ homepage: ''
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.0.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Manage a collection with 3 data points
83
+ test_files:
84
+ - test/test_helper.rb
85
+ - test/triad_test.rb
86
+ has_rdoc: