contrast 0.1.4

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,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/.rvmrc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.3-p0@contrast"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in contrast.gemspec
4
+ gemspec
5
+
6
+ gem 'rake'
7
+ gem 'subtle'
8
+
9
+ group :development do
10
+ gem 'mocha'
11
+ gem 'guard'
12
+ gem 'guard-minitest', :git => 'git://github.com/aspiers/guard-minitest.git'
13
+ gem 'ruby_gntp'
14
+ end
data/Guardfile ADDED
@@ -0,0 +1,12 @@
1
+ guard 'minitest' do
2
+ watch(%r|^test/test_(.*)\.rb|)
3
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
4
+ watch(%r|^test/test_helper\.rb|) { "test" }
5
+ watch(%r|^lib/(.*)\.rb|) { |m| "test/test_#{m[1]}.rb" }
6
+
7
+ watch(%r{^spec/.+_spec\.rb$})
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
+ watch(%r{^lib/contrast/(.+)\.rb$}) { |m| "spec/contrast/#{m[1]}_spec.rb" }
10
+ watch(%r{^spec/models/.+\.rb$}) { ["spec/models", "spec/acceptance"] }
11
+ watch('spec/spec_helper.rb') { "spec" }
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Darren Cauthon
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,29 @@
1
+ # Contrast
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'contrast'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install contrast
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/contrast.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/contrast/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Darren Cauthon"]
6
+ gem.email = ["darren@cauthon.com"]
7
+ gem.description = %q{Contrast two objects by a defined set of values}
8
+ gem.summary = %q{Contrast two objects by a defined set of values}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "contrast"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Contrast::VERSION
17
+
18
+ gem.add_runtime_dependency 'subtle'
19
+ gem.add_development_dependency 'mocha'
20
+ gem.add_development_dependency 'rake'
21
+ end
@@ -0,0 +1,29 @@
1
+ module Contrast
2
+ class Detective
3
+ def initialize(*args)
4
+ @fields = args
5
+ end
6
+
7
+ def examine(a, b)
8
+ @fields.select do |field|
9
+ first = get_the_value(a, field)
10
+ second = get_the_value(b, field)
11
+ the_values_the_do_not_match(first, second)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def get_the_value(object, field)
18
+ begin
19
+ object.send(field)
20
+ rescue
21
+ object[field]
22
+ end
23
+ end
24
+
25
+ def the_values_the_do_not_match(a, b)
26
+ a != b && a.to_s != b.to_s
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module Contrast
2
+ class MatchingException < StandardError
3
+ attr_accessor :results
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Contrast
2
+ VERSION = "0.1.4"
3
+ end
data/lib/contrast.rb ADDED
@@ -0,0 +1,5 @@
1
+ Dir[File.dirname(__FILE__) + '/contrast/*.rb'].each {|file| require file }
2
+ require 'contrast_with'
3
+
4
+ module Contrast
5
+ end
@@ -0,0 +1,15 @@
1
+ class Object
2
+ def contrast_with(other, fields)
3
+ detective = Contrast::Detective.new(fields)
4
+ detective.examine(self, other)
5
+ end
6
+
7
+ def contrast_with!(other, fields)
8
+ results = self.contrast_with(other, fields)
9
+ if results.any?
10
+ exception = Contrast::MatchingException.new
11
+ exception.results = results
12
+ raise exception
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,154 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Contrast::Detective do
4
+ describe "one method comparison" do
5
+ describe "two objects that match" do
6
+ before do
7
+ @a = [:name].to_object
8
+ @b = [:name].to_object
9
+ @a.name = ""
10
+ @b.name = ""
11
+ detective = Contrast::Detective.new :name
12
+ @result = detective.examine(@a, @b)
13
+ end
14
+
15
+ it "should return no results" do
16
+ @result.count.must_equal 0
17
+ end
18
+ end
19
+
20
+ describe "two objects that do not match" do
21
+ before do
22
+ @a = [:name].to_object
23
+ @b = [:name].to_object
24
+ @a.name = 'apple'
25
+ @b.name = 'orange'
26
+ detective = Contrast::Detective.new :name
27
+ @result = detective.examine(@a, @b)
28
+ end
29
+
30
+ it "should return one result" do
31
+ @result.count.must_equal 1
32
+ end
33
+
34
+ it "should return the field" do
35
+ @result[0].must_equal :name
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "two methods comparison" do
41
+ describe "two objects that match" do
42
+ before do
43
+ @a = [:first_name, :last_name].to_object
44
+ @b = [:first_name, :last_name].to_object
45
+ objects = [:first_name, :last_name].to_objects {[
46
+ ['a', 'b'], ['a', 'b']
47
+ ]}
48
+
49
+ detective = Contrast::Detective.new :first_name, :last_name
50
+ @result = detective.examine(objects[0], objects[1])
51
+ end
52
+
53
+ it "should return no results" do
54
+ @result.count.must_equal 0
55
+ end
56
+ end
57
+
58
+ describe "two objects that do not match by first property" do
59
+ before do
60
+ @a = [:first_name, :last_name].to_object
61
+ @b = [:first_name, :last_name].to_object
62
+ objects = [:first_name, :last_name].to_objects {[
63
+ ['a', 'b'], ['z', 'b']
64
+ ]}
65
+ detective = Contrast::Detective.new :first_name, :last_name
66
+ @result = detective.examine(objects[0], objects[1])
67
+ end
68
+
69
+ it "should return one result" do
70
+ @result.count.must_equal 1
71
+ end
72
+
73
+ it "should return the field" do
74
+ @result[0].must_equal :first_name
75
+ end
76
+ end
77
+
78
+ describe "two objects that do not match by second property" do
79
+ before do
80
+ @a = [:first_name, :last_name].to_object
81
+ @b = [:first_name, :last_name].to_object
82
+ objects = [:first_name, :last_name].to_objects {[
83
+ ['a', 'b'], ['a', 'c']
84
+ ]}
85
+ detective = Contrast::Detective.new :first_name, :last_name
86
+ @result = detective.examine(objects[0], objects[1])
87
+ end
88
+
89
+ it "should return one result" do
90
+ @result.count.must_equal 1
91
+ end
92
+
93
+ it "should return the field" do
94
+ @result[0].must_equal :last_name
95
+ end
96
+ end
97
+
98
+ describe "two objects that do not match by both properties" do
99
+ before do
100
+ @a = [:first_name, :last_name].to_object
101
+ @b = [:first_name, :last_name].to_object
102
+ objects = [:first_name, :last_name].to_objects {[
103
+ ['a', 'b'], ['y', 'z']
104
+ ]}
105
+ detective = Contrast::Detective.new :first_name, :last_name
106
+ @result = detective.examine(objects[0], objects[1])
107
+ end
108
+
109
+ it "should return one result" do
110
+ @result.count.must_equal 2
111
+ end
112
+
113
+ it "should return the fields" do
114
+ @result[0].must_equal :first_name
115
+ @result[1].must_equal :last_name
116
+ end
117
+ end
118
+
119
+ describe 'strange matching' do
120
+ before do
121
+ @a = [:value].to_object
122
+ @b = [:value].to_object
123
+ @detective = Contrast::Detective.new :value
124
+ end
125
+
126
+ it "should match integers to strings" do
127
+ @a.value = 1; @b.value = '1'
128
+ @detective.examine(@a, @b).count.must_equal 0
129
+ @detective.examine(@b, @a).count.must_equal 0
130
+ end
131
+
132
+ it "should match floats to integers" do
133
+ @a.value = 1; @b.value = 1.0
134
+ @detective.examine(@a, @b).count.must_equal 0
135
+ @detective.examine(@b, @a).count.must_equal 0
136
+ end
137
+ end
138
+
139
+ describe 'matching objects to hashes' do
140
+ before do
141
+ @a = [:value].to_object
142
+ @b = {}
143
+ @detective = Contrast::Detective.new :value
144
+ end
145
+
146
+ it "should match the two" do
147
+ @a.value = 1; @b[:value] = 1
148
+ @detective.examine(@a, @b).count.must_equal 0
149
+ @detective.examine(@b, @a).count.must_equal 0
150
+ end
151
+ end
152
+ end
153
+ end
154
+
@@ -0,0 +1,89 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe 'contrast with' do
4
+ it "should pass the arguments to the contrast detective" do
5
+ fields = [:city, :state]
6
+ first = fields.to_object
7
+ second = fields.to_object
8
+ expected_value = Object.new
9
+ Contrast::Detective.any_instance.expects(:examine).
10
+ with(first, second).returns(expected_value)
11
+
12
+ result = first.contrast_with(second, fields)
13
+
14
+ result.must_be_same_as expected_value
15
+ end
16
+ end
17
+
18
+ describe 'contrast with!' do
19
+ it "should pass the arguments to the contrast detective" do
20
+ fields = [:city, :state]
21
+ first = fields.to_object
22
+ second = fields.to_object
23
+ expected_value = []
24
+ Contrast::Detective.any_instance.expects(:examine).
25
+ with(first, second).returns(expected_value)
26
+
27
+ first.contrast_with!(second, fields)
28
+ end
29
+ it "should throw an exception if any results are returned" do
30
+ fields = [:city, :state]
31
+ first = fields.to_object
32
+ second = fields.to_object
33
+ result = [:city]
34
+ Contrast::Detective.any_instance.expects(:examine).
35
+ with(first, second).returns(result)
36
+
37
+ exception_thrown = -> { first.contrast_with!(second, fields) }.
38
+ call_safely { true }
39
+
40
+ exception_thrown.must_equal true
41
+ end
42
+
43
+ it "should not throw an exception if no results are thrown" do
44
+ fields = [:city, :state]
45
+ first = fields.to_object
46
+ second = fields.to_object
47
+ result = []
48
+ Contrast::Detective.any_instance.expects(:examine).
49
+ with(first, second).returns(result)
50
+
51
+ exception_thrown = -> { first.contrast_with!(second, fields); false }.
52
+ call_safely { true }
53
+
54
+ exception_thrown.must_equal false
55
+ end
56
+
57
+ it "should return a contrast exception" do
58
+ fields = [:city, :state]
59
+ first = fields.to_object
60
+ second = fields.to_object
61
+ result = [:city]
62
+ Contrast::Detective.any_instance.expects(:examine).
63
+ with(first, second).returns(result)
64
+
65
+ exception_thrown = false
66
+ begin
67
+ first.contrast_with!(second, fields)
68
+ rescue Contrast::MatchingException
69
+ exception_thrown = true
70
+ end
71
+
72
+ exception_thrown.must_equal true
73
+ end
74
+
75
+ it "should return the contrast results in the exception" do
76
+ fields = [:city, :state]
77
+ first = fields.to_object
78
+ second = fields.to_object
79
+ result = [:city]
80
+ Contrast::Detective.any_instance.expects(:examine).
81
+ with(first, second).returns(result)
82
+
83
+ begin
84
+ first.contrast_with!(second, fields)
85
+ rescue Contrast::MatchingException => e
86
+ e.results.must_be_same_as(result)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,5 @@
1
+ require 'mocha'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require './lib/contrast.rb'
5
+ require 'subtle'
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: contrast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Darren Cauthon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: subtle
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Contrast two objects by a defined set of values
63
+ email:
64
+ - darren@cauthon.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rvmrc
71
+ - Gemfile
72
+ - Guardfile
73
+ - LICENSE
74
+ - README.md
75
+ - Rakefile
76
+ - contrast.gemspec
77
+ - lib/contrast.rb
78
+ - lib/contrast/detective.rb
79
+ - lib/contrast/matching_exception.rb
80
+ - lib/contrast/version.rb
81
+ - lib/contrast_with.rb
82
+ - spec/contrast/detective_spec.rb
83
+ - spec/contrast_with_spec.rb
84
+ - spec/spec_helper.rb
85
+ homepage: ''
86
+ licenses: []
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.24
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Contrast two objects by a defined set of values
109
+ test_files:
110
+ - spec/contrast/detective_spec.rb
111
+ - spec/contrast_with_spec.rb
112
+ - spec/spec_helper.rb