simple_units 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "activesupport"
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", ">= 2.8.0"
10
+ gem "rdoc", ">= 3.12"
11
+ gem "bundler", ">= 1.0.0"
12
+ gem "jeweler", ">= 1.8.4"
13
+ gem "simplecov"
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.12)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ diff-lcs (1.2.1)
8
+ git (1.2.5)
9
+ i18n (0.6.4)
10
+ jeweler (1.8.4)
11
+ bundler (~> 1.0)
12
+ git (>= 1.2.5)
13
+ rake
14
+ rdoc
15
+ json (1.7.7)
16
+ multi_json (1.6.1)
17
+ rake (10.0.3)
18
+ rdoc (4.0.0)
19
+ json (~> 1.4)
20
+ rspec (2.13.0)
21
+ rspec-core (~> 2.13.0)
22
+ rspec-expectations (~> 2.13.0)
23
+ rspec-mocks (~> 2.13.0)
24
+ rspec-core (2.13.0)
25
+ rspec-expectations (2.13.0)
26
+ diff-lcs (>= 1.1.3, < 2.0)
27
+ rspec-mocks (2.13.0)
28
+ simplecov (0.7.1)
29
+ multi_json (~> 1.0)
30
+ simplecov-html (~> 0.7.1)
31
+ simplecov-html (0.7.1)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ activesupport
38
+ bundler (>= 1.0.0)
39
+ jeweler (>= 1.8.4)
40
+ rdoc (>= 3.12)
41
+ rspec (>= 2.8.0)
42
+ simplecov
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Thomas
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,19 @@
1
+ = simple_units
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to simple_units
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2013 Thomas. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "simple_units"
18
+ gem.homepage = "http://github.com/foxnewsnetwork/simple_units"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Simple units implementation. Similar to ruby-units except with a lot less features and zero collisons with rails.}
21
+ gem.description = %Q{Sure, ruby is dynamic and that is one of its greatest strength. Object polymorphisms, duck typing, and the like is great in ruby, there is a time and place for everything. Sometimes, it just makes more sense to be strongly typed.}
22
+ gem.email = "foxnewsnetwork@gmail.com"
23
+ gem.authors = ["Thomas Chen"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ task :default => :spec
35
+
36
+ require 'rdoc/task'
37
+ Rake::RDocTask.new do |rdoc|
38
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
39
+
40
+ rdoc.rdoc_dir = 'rdoc'
41
+ rdoc.title = "simple_units #{version}"
42
+ rdoc.rdoc_files.include('README*')
43
+ rdoc.rdoc_files.include('lib/**/*.rb')
44
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,6 @@
1
+ require "active_support"
2
+ module SimpleUnits
3
+ require File.join(File.dirname(__FILE__), "simple_units", "composite")
4
+ require File.join(File.dirname(__FILE__), "simple_units", "context")
5
+ require File.join(File.dirname(__FILE__), "simple_units", "unit")
6
+ end
@@ -0,0 +1,101 @@
1
+ module SimpleUnits
2
+ class Composite
3
+
4
+ class << self
5
+ def from_context(context)
6
+ new.tap do |composite|
7
+ composite.append_numerators! context
8
+ end
9
+ end
10
+
11
+ def from_string(string)
12
+ from_context SimpleUnits::Context.get_context string
13
+ end
14
+ end
15
+
16
+ def append_numerators!(*contexts)
17
+ contexts.each { |context| append_numerator! context }
18
+ simplify!
19
+ end
20
+
21
+ def append_denominators!(*contexts)
22
+ contexts.each { |context| append_denominator! context }
23
+ simplify!
24
+ end
25
+
26
+ def append_numerator!(context)
27
+ modify_context_by_order!(context, 1)
28
+ end
29
+
30
+ def append_denominator!(context)
31
+ modify_context_by_order!(context, -1)
32
+ end
33
+
34
+ def modify_context_by_order!(context, order)
35
+ @contexts_hash ||= {}
36
+ if @contexts_hash[context.name.to_s].nil?
37
+ @contexts_hash[context.name.to_s] = { :context => context, :order => order }
38
+ else
39
+ @contexts_hash[context.name.to_s][:order] += order
40
+ end
41
+ end
42
+
43
+
44
+ def numerators
45
+ @contexts_hash.reject do |name, hash|
46
+ hash[:order] < 0
47
+ end
48
+ end
49
+
50
+ def denominators
51
+ @contexts_hash.reject do |name, hash|
52
+ hash[:order] > 0
53
+ end
54
+ end
55
+
56
+
57
+ def inverse
58
+ self.class.new.tap do |composite|
59
+ (numerators.to_a + denominators.to_a).each { |name, hash| composite.modify_context_by_order!(hash[:context], -hash[:order]) }
60
+ composite.simplify!
61
+ end
62
+ end
63
+
64
+ def simplify!
65
+ @contexts_hash.reject! do |name, hash|
66
+ hash[:order].zero?
67
+ end
68
+ end
69
+
70
+ def inspector
71
+ if @contexts_hash.keys.count == 1
72
+ @contexts_hash[@contexts_hash.keys.first][:context].inspector
73
+ end
74
+ end
75
+
76
+ def to_str
77
+ @contexts_hash.to_a.sort { |a,b| a.first <=> b.first }.inject("") do |str, package|
78
+ order = package.last[:order]
79
+ name = package.first
80
+ str + "(#{name}^#{order})"
81
+ end.gsub("^1", "")
82
+ end
83
+
84
+ def to_s; to_str; end
85
+
86
+ def *(other)
87
+ array = other.denominators.to_a + self.denominators.to_a + other.numerators.to_a + self.numerators.to_a
88
+ self.class.new.tap do |composite|
89
+ array.each do |name, hash|
90
+ composite.modify_context_by_order!(hash[:context], hash[:order])
91
+ end
92
+ composite.simplify!
93
+ end
94
+ end
95
+
96
+ def ==(other)
97
+ to_str == other.to_str
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,24 @@
1
+ module SimpleUnits
2
+ class Context
3
+
4
+ class << self
5
+ def define_unit(name, &block)
6
+ @contexts ||= {}
7
+ @contexts[name.to_s] = new(name, &block)
8
+ end
9
+
10
+ def get_context(name)
11
+ throw :UndefinedUnitError if @contexts[name].nil?
12
+ @contexts[name.to_s]
13
+ end
14
+ end
15
+
16
+ attr_accessor :name, :type, :inspector
17
+ def initialize(name=nil, &block)
18
+ @name = name
19
+ yield(self)
20
+ end
21
+
22
+ end
23
+ end
24
+
@@ -0,0 +1,104 @@
1
+ module SimpleUnits
2
+ class Unit < Numeric
3
+ class MismatchError < Exception; end
4
+ class UnknownUnitError < Exception; end
5
+ class << self
6
+ def convert_dimension(to_unit, from_unit)
7
+ throw :CannotConvertDimension
8
+ end
9
+
10
+ # Not really implemented yet
11
+ def simplify_dimensions(unit)
12
+ unit
13
+ end
14
+ end
15
+
16
+ attr_accessor :value, :composite
17
+
18
+ def initialize(value, units)
19
+ @value = value
20
+ case units.class.to_s
21
+ when "String", "Symbol"
22
+ @composite = SimpleUnits::Composite.from_string units.to_s
23
+ when "SimpleUnits::Context"
24
+ @composite = SimpleUnits::Composite.from_context units
25
+ when "SimpleUnits::Composite"
26
+ @composite = units
27
+ else
28
+ raise UnknownUnitError.new("#{units} is a #{units.class}")
29
+ end
30
+
31
+ end
32
+
33
+ def units
34
+ composite.to_s
35
+ end
36
+
37
+ def to_i
38
+ to_something("i")
39
+ end
40
+
41
+ def to_f
42
+ to_something("f")
43
+ end
44
+
45
+ def to_something(thing)
46
+ value.send("to_#{thing}")
47
+ end
48
+
49
+ def +(other)
50
+ if same_dimension? other
51
+ self.class.new(value + other.value, composite)
52
+ else
53
+ self + SimpleUnits::Unit.convert_dimension(self, other)
54
+ end
55
+ end
56
+
57
+ def -(other)
58
+ self + other.opposite
59
+ end
60
+
61
+ def *(other)
62
+ case other.class.to_s
63
+ when "Fixnum", "Float", "Integer", "Numeric"
64
+ new_value = value * other
65
+ new_composite = composite
66
+ when "SimpleUnits::Unit"
67
+ new_value = value * other.value
68
+ new_composite = composite * other.composite
69
+ else
70
+ raise MismatchError.new "#{other} is a #{other.class.to_s}"
71
+ end
72
+ self.class.simplify_dimensions self.class.new(new_value, new_composite)
73
+ end
74
+
75
+ def /(other)
76
+ self * other.inverse
77
+ end
78
+
79
+ def opposite
80
+ self.class.new(-value, composite)
81
+ end
82
+
83
+ def inverse
84
+ self.class.new(1 / value.to_f, composite.inverse)
85
+ end
86
+
87
+ def inspect
88
+ if composite.inspector.nil?
89
+ "#{value} #{composite.to_s}"
90
+ else
91
+ composite.inspector.call(value)
92
+ end
93
+ end
94
+
95
+ def to_s; inspect; end
96
+
97
+ def to_str; to_s; end
98
+
99
+ def same_dimension?(other)
100
+ self.composite == other.composite
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleUnits::Composite do
4
+ let(:api) { SimpleUnits::Composite }
5
+ let(:cc) { SimpleUnits::Context }
6
+ before :each do
7
+ cc.define_unit("dog") { |unit| unit.type = :animal }
8
+ cc.define_unit("cat") { |unit| unit.type = :animal }
9
+ cc.define_unit("user") { |unit| unit.type = :person }
10
+ end
11
+ describe "::new" do
12
+ let(:composite) { api.new }
13
+ let(:dog) { cc.get_context "dog" }
14
+ let(:cat) { cc.get_context "cat" }
15
+ let(:user) { cc.get_context "user" }
16
+
17
+ specify { composite.should be_a api }
18
+
19
+ describe "#==" do
20
+ let(:pet_owner) { api.new }
21
+ let(:faggot) { api.new }
22
+ before :each do
23
+ pet_owner.append_numerators! dog
24
+ pet_owner.append_denominators! user
25
+ faggot.append_numerators! dog, cat, user, dog, cat
26
+ faggot.append_denominators! dog, cat, cat, user, user
27
+ end
28
+
29
+ it "should be equal since we simplify the units" do
30
+ pet_owner.should == faggot
31
+ end
32
+
33
+ it "should not equal to things with differing units" do
34
+ pet_owner.append_numerators! user
35
+ pet_owner.should_not == faggot
36
+ end
37
+ end
38
+
39
+ describe "#*" do
40
+ let(:dog_per_user) { api.new }
41
+ let(:cat_per_user) { api.new }
42
+ let(:dog_cat_per_user_squared) { dog_per_user * cat_per_user }
43
+ before :each do
44
+ dog_per_user.append_numerators! dog
45
+ dog_per_user.append_denominators! user
46
+ cat_per_user.append_numerators! cat
47
+ cat_per_user.append_denominators! user
48
+ end
49
+
50
+ context "reductions" do
51
+ describe "#inverse" do
52
+ let(:user_per_dog) { dog_per_user.inverse }
53
+ let(:user_per_cat) { cat_per_user.inverse }
54
+ it "should properly give me the units for user per dog" do
55
+ user_per_dog.to_s.should eq "(dog^-1)(user)"
56
+ dog_per_user.to_s.should eq "(dog)(user^-1)"
57
+ user_per_cat.to_s.should eq "(cat^-1)(user)"
58
+ cat_per_user.to_s.should eq "(cat)(user^-1)"
59
+ end
60
+
61
+ describe "#*" do
62
+ let(:scalar) { dog_per_user * user_per_dog }
63
+ it "should reduce down to a scalar if something is hit with its inverse" do
64
+ scalar.numerators.should eq({})
65
+ scalar.denominators.should eq({})
66
+ scalar.to_s.should eq ""
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "#numerators" do
73
+ before :each do
74
+ @expected = {
75
+ "dog" => { :order => 1, :context => dog },
76
+ "cat" => { :order => 1, :context => cat }
77
+ }
78
+ end
79
+
80
+ it "should match the numerator list" do
81
+ dog_cat_per_user_squared.numerators.should eq @expected
82
+ end
83
+ end
84
+
85
+ describe "#denominators" do
86
+ before :each do
87
+ @expected = {
88
+ "user" => { :order => -2, :context => user }
89
+ }
90
+ end
91
+
92
+ it "should match the numerator list" do
93
+ dog_cat_per_user_squared.denominators.should eq @expected
94
+ end
95
+ end
96
+
97
+ describe "#to_str" do
98
+ before(:each) { @expected = "(cat)(dog)(user^-2)" }
99
+
100
+ specify { dog_cat_per_user_squared.to_str.should eq @expected }
101
+ end
102
+ end
103
+
104
+ describe "#append_numerators" do
105
+ before :each do
106
+ composite.append_numerators! dog, cat, user
107
+ end
108
+
109
+ describe "#numerators" do
110
+ before :each do
111
+ @expected = {
112
+ "dog" => {:order => 1, :context => dog} ,
113
+ "cat" => {:order => 1, :context => cat} ,
114
+ "user" => {:order => 1, :context => user}
115
+ }
116
+ end
117
+
118
+ it "should spit out all the numerators involved in building my composite" do
119
+ composite.numerators.count.should eq @expected.count
120
+ composite.numerators.should eq @expected
121
+ end
122
+ end
123
+
124
+ describe "#denominators" do
125
+ specify { composite.denominators.should be_empty }
126
+ end
127
+
128
+ describe "#to_str" do
129
+ before :each do
130
+ @expected = "(cat)(dog)(user)"
131
+ end
132
+
133
+ it "should be an alias to to_s" do
134
+ composite.to_str.should eq composite.to_s
135
+ end
136
+
137
+ it "should give me the expected string result" do
138
+ composite.to_str.should eq @expected
139
+ end
140
+ end
141
+
142
+ describe "#append_denominators" do
143
+ before :each do
144
+ composite.append_denominators! dog, dog, dog
145
+ end
146
+
147
+ describe "#numerators" do
148
+ before :each do
149
+ @expected = {
150
+ "cat" => {:order => 1, :context => cat} ,
151
+ "user" => {:order => 1, :context => user}
152
+ }
153
+ end
154
+
155
+ it "should spit out only the numerators as in things with order > 0" do
156
+ composite.numerators.should eq @expected
157
+ end
158
+ end
159
+
160
+ describe "#denominators" do
161
+ before :each do
162
+ @expected = {
163
+ "dog" => { :order => -2, :context => dog }
164
+ }
165
+ end
166
+ it "should have the denominators as per expectation" do
167
+ composite.denominators.should eq @expected
168
+ end
169
+ end
170
+
171
+ describe "#to_str" do
172
+ before :each do
173
+ @expected = "(cat)(dog^-2)(user)"
174
+ end
175
+ it "should give me the expected stringified version as well as match its alias" do
176
+ composite.to_s.should eq @expected
177
+ composite.to_str.should eq composite.to_s
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleUnits::Context do
4
+ let(:api) { SimpleUnits::Context }
5
+ describe "::define" do
6
+ before(:each) do
7
+ api.define_unit("meter") do |unit|
8
+ unit.type = :length
9
+ end
10
+ end
11
+ describe "::get_context" do
12
+ it "should be able to fetch the context I just defined" do
13
+ api.get_context("meter").should be_a api
14
+ api.get_context("meter").name.should eq "meter"
15
+ api.get_context("meter").type.should eq :length
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleUnits::Unit do
4
+ let(:model) { SimpleUnits::Unit }
5
+ let(:cc) { SimpleUnits::Context }
6
+ context "usage" do
7
+ before :each do
8
+ cc.define_unit("user") do |unit|
9
+ unit.type = :people
10
+ end
11
+ cc.define_unit("faggots") do |unit|
12
+ unit.type = :people
13
+ unit.inspector = lambda { |value| "8==D #{value} G==8" }
14
+ end
15
+ cc.define_unit("baggage") do |unit|
16
+ unit.type = :stuff
17
+ end
18
+ end
19
+
20
+ describe "::new" do
21
+ let(:four) { model.new 4, "user" }
22
+ let(:three) { model.new 3, "user" }
23
+ let(:five) { model.new 5, "faggots" }
24
+ let(:sixteen) { model.new 16, cc.get_context("baggage")}
25
+
26
+ context "crap" do
27
+ let(:crap) { model.new 33, RSpec }
28
+ it "should throw an error that indictates you've passed crap to try to start a new unit" do
29
+ expect { crap }.to raise_error(SimpleUnits::Unit::UnknownUnitError, "RSpec is a Module")
30
+ end
31
+ end
32
+ it "should give me an unit of the correct number" do
33
+ four.should be_a model
34
+ four.value.should eq 4
35
+ four.units.should eq "(user)"
36
+ sixteen.should be_a model
37
+ sixteen.value.should eq 16
38
+ sixteen.units.should eq "(baggage)"
39
+ end
40
+
41
+ describe "#to_i" do
42
+ it "should just give the absolute value of a current unit in integer form" do
43
+ five.to_i.should eq 5
44
+ three.to_i.should eq 3
45
+ four.to_i.should eq 4
46
+ end
47
+ end
48
+
49
+ describe "#to_f" do
50
+ it "should give the absolute value as a float" do
51
+ five.to_f.should eq 5.0
52
+ three.to_f.should eq 3.0
53
+ four.to_i.should eq 4.0
54
+ end
55
+ end
56
+
57
+ describe "#inverse" do
58
+ context "normal" do
59
+ let(:one_fifth) { five.inverse }
60
+ it "should properly invert a number" do
61
+ one_fifth.to_f.should eq 0.2
62
+ end
63
+ it "should have the correct units" do
64
+ one_fifth.units.to_s.should eq "(faggots^-1)"
65
+ end
66
+ end
67
+
68
+ context "infinity" do
69
+ let(:zero) { model.new 0, "faggots" }
70
+ let(:infinity) { zero.inverse }
71
+ it "should give me infinity" do
72
+ infinity.value.should eq Float::INFINITY
73
+ end
74
+ it "should still be the correct units" do
75
+ zero.units.to_s.should eq "(faggots)"
76
+ infinity.units.to_s.should eq "(faggots^-1)"
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#/" do
82
+ context "unitary" do
83
+ let(:eleven) { model.new 11, "faggots" }
84
+ let(:one) { eleven / eleven }
85
+ let(:one2) { eleven * eleven.inverse }
86
+ it "should support proper division" do
87
+ one.value.should eq 1.0
88
+ end
89
+
90
+ it "should become a scalar at this point" do
91
+ eleven.units.to_s.should eq "(faggots)"
92
+ eleven.inverse.units.to_s.should eq "(faggots^-1)"
93
+ one.units.to_s.should eq one2.units.to_s
94
+ one.units.to_s.should eq ""
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ describe "#to_s" do
101
+ specify { five.to_s.should eq "8==D 5 G==8" }
102
+ end
103
+
104
+ describe "#same_dimension?" do
105
+ it "should be true when two units have the same context name" do
106
+ four.same_dimension?(three).should be_true
107
+ three.same_dimension?(four).should be_true
108
+ end
109
+ end
110
+ describe "#+" do
111
+ let(:seven) { four + three }
112
+ it "should be able to add users together and give me the correct resulting number" do
113
+ seven.should be_a model
114
+ seven.value.should eq 7
115
+ seven.units.should eq "(user)"
116
+ end
117
+ end
118
+ describe "#-" do
119
+ let(:one) { four - three }
120
+
121
+ it "should subtract an user from others" do
122
+ one.should be_a model
123
+ one.value.should eq 1
124
+ one.units.should eq "(user)"
125
+ end
126
+ end
127
+ describe "#*" do
128
+
129
+ context "dimensional" do
130
+ let(:twelve) { four * three }
131
+ it "should produce a squared user when two users are multiplied" do
132
+ twelve.should be_a model
133
+ twelve.value.should eq 12
134
+ twelve.units.should eq "(user^2)"
135
+ end
136
+
137
+ describe "#+" do
138
+ it "should throw an error when you attempt to add together things of differing units" do
139
+ expect { twelve + four }.to throw_symbol :CannotConvertDimension
140
+ end
141
+ end
142
+ end
143
+
144
+ context "scalar" do
145
+ let(:sixty_six) { three * 22 }
146
+ it "should still have the same model with the same units, but be scaled up 22 times" do
147
+ sixty_six.should be_a model
148
+ sixty_six.value.should eq 66
149
+ sixty_six.units.should eq three.units
150
+ end
151
+ end
152
+
153
+ context "nonsensical" do
154
+ let(:crap) { three * RSpec }
155
+
156
+ it "should throw an error since it doesn't make sense to multiple numbers with units to random objects" do
157
+ expect { crap }.to raise_error( SimpleUnits::Unit::MismatchError, "RSpec is a Module" )
158
+ end
159
+ end
160
+ end
161
+ describe "#to_str" do
162
+ it "should stringify simply and predicably" do
163
+ four.to_str.should eq four.to_s
164
+ four.to_str.should eq "4 (user)"
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,5 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe SimpleUnits do
4
+
5
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ require 'rspec'
3
+ require "simplecov"
4
+ SimpleCov.start
5
+ require File.expand_path("../../lib/simple_units", __FILE__)
6
+
7
+
8
+ # Requires supporting files with custom matchers and macros, etc,
9
+ # in ./support/ and its subdirectories.
10
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+ config.fail_fast = true
14
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_units
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Thomas Chen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
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: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.8.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: 2.8.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '3.12'
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: '3.12'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.8.4
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.8.4
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Sure, ruby is dynamic and that is one of its greatest strength. Object
111
+ polymorphisms, duck typing, and the like is great in ruby, there is a time and place
112
+ for everything. Sometimes, it just makes more sense to be strongly typed.
113
+ email: foxnewsnetwork@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files:
117
+ - LICENSE.txt
118
+ - README.rdoc
119
+ files:
120
+ - .document
121
+ - .rspec
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - LICENSE.txt
125
+ - README.rdoc
126
+ - Rakefile
127
+ - VERSION
128
+ - lib/simple_units.rb
129
+ - lib/simple_units/composite.rb
130
+ - lib/simple_units/context.rb
131
+ - lib/simple_units/unit.rb
132
+ - spec/simple_units/composite_spec.rb
133
+ - spec/simple_units/context_spec.rb
134
+ - spec/simple_units/unit_spec.rb
135
+ - spec/simple_units_spec.rb
136
+ - spec/spec_helper.rb
137
+ homepage: http://github.com/foxnewsnetwork/simple_units
138
+ licenses:
139
+ - MIT
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ segments:
151
+ - 0
152
+ hash: -4292195142135224155
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ! '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 1.8.24
162
+ signing_key:
163
+ specification_version: 3
164
+ summary: Simple units implementation. Similar to ruby-units except with a lot less
165
+ features and zero collisons with rails.
166
+ test_files: []