unitwise 0.6.1 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f269726294777e995dada36f1169f639de28b5f
4
- data.tar.gz: e9bc9e48ee65a4d08539d5ee85c7cb2d14d65573
3
+ metadata.gz: d9050a8b1974209dc285b85f896030daed2e6319
4
+ data.tar.gz: 239e8d8949dfadf97acd2b5d431d7c9722d93b9e
5
5
  SHA512:
6
- metadata.gz: e5f8cd371aac1c89b4eeab25f3f5d92fa45029244073deb0515dd9ef4c5347d8b91a96838b71319ec040147fed46a0f4b91656296839c408230f9f823bf14860
7
- data.tar.gz: 17cdcce509f3db09c4cb607f8d51c64d0ea5a6ae51653f0a8c56de61756f75d280f677ac6a06c3086058a6f83d8c121a570ef234c6d23be3788038b67a74496e
6
+ metadata.gz: 3ebf1ae8eaa28fbff80dadf844629f74e36593c094ee1b8a82aee615e1989b1d995a5512e573405422814c8bb581b5e44bad928372f91dccf40eff3584b6d854
7
+ data.tar.gz: b8290d0f28ab189333ed4b16efdf5d5ea42f9d0d0b3d65d4822cda9e33ee234ee1da2ed544487b4be9814a4d4cd07aba2480d1ab714262e1c75dfee5812d99b7
data/Gemfile CHANGED
@@ -1,5 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in unitwise.gemspec
4
- gem 'pry'
5
2
  gemspec
data/lib/unitwise/atom.rb CHANGED
@@ -4,8 +4,7 @@ module Unitwise
4
4
  # 'meter', 'hour', 'pound force'.
5
5
  class Atom < Base
6
6
  liner :classification, :property, :metric, :special, :arbitrary, :dim
7
-
8
- include Unitwise::Compatible
7
+ include Compatible
9
8
 
10
9
  class << self
11
10
  # Array of hashes representing atom properties.
@@ -71,6 +70,7 @@ module Unitwise
71
70
  def depth
72
71
  base? ? 0 : scale.depth + 1
73
72
  end
73
+ memoize :depth
74
74
 
75
75
  # Determine if this is the last atom in the scale chain
76
76
  # @return [true, false]
@@ -116,5 +116,6 @@ module Unitwise
116
116
  def root_terms
117
117
  base? ? [Term.new(:atom_code => primary_code)] : scale.root_terms
118
118
  end
119
+ memoize :root_terms
119
120
  end
120
121
  end
data/lib/unitwise/base.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'yaml'
2
1
  module Unitwise
3
2
  # The base class that Atom and Prefix are extended from. This class provides
4
3
  # shared functionality for said classes.
5
4
  class Base
6
5
  liner :names, :primary_code, :secondary_code, :symbol, :scale
6
+ include Memoizable
7
7
 
8
8
  # The list of tracked items.
9
9
  # @return [Array] An array of memoized instances.
@@ -30,14 +30,6 @@ module Unitwise
30
30
  end
31
31
  end
32
32
 
33
- # Setup a new instance. Takes a hash of attributes, or an array of
34
- # attribute values.
35
- # @api public
36
- def initialize(*args)
37
- super(*args)
38
- freeze
39
- end
40
-
41
33
  # Setter for the names attribute. Will always set as an array.
42
34
  # @api semipublic
43
35
  def names=(names)
@@ -52,6 +44,7 @@ module Unitwise
52
44
  n.downcase.strip.gsub(/\s/, '_').gsub(/\W/, '')
53
45
  end
54
46
  end
47
+ memoize :slugs
55
48
 
56
49
  # String representation for the instance.
57
50
  # @return [String]
@@ -6,6 +6,13 @@ module Unitwise
6
6
  # @api private
7
7
  def self.included(base)
8
8
  base.send :include, Comparable
9
+ base.send :include, Memoizable unless base < Memoizable
10
+ base.send :memoize, :composition, :composition_string
11
+ end
12
+
13
+ def initialize(*args)
14
+ super(*args)
15
+ freeze
9
16
  end
10
17
 
11
18
  # A representation of a unit based on the atoms it's derived from.
@@ -1,5 +1,3 @@
1
- require 'parslet'
2
-
3
1
  require 'unitwise/expression/matcher'
4
2
  require 'unitwise/expression/parser'
5
3
  require 'unitwise/expression/transformer'
@@ -4,19 +4,13 @@ module Unitwise
4
4
  # magnitude and direction. This class should be considered mostly privateish.
5
5
  class Scale
6
6
  liner :value, :unit
7
-
8
7
  include Unitwise::Compatible
9
8
 
10
- def initialize(*args)
11
- super(*args)
12
- freeze
13
- end
14
-
15
- # The unit associated with this scale.
16
- # @return [Unitwise::Unit]
9
+ # Set the unit vector.
10
+ # @param value [String, Unitwise::Unit]
17
11
  # @api public
18
- def unit
19
- @unit.is_a?(Unit) ? @unit : Unit.new(@unit)
12
+ def unit=(value)
13
+ @unit = value.is_a?(Unit) ? value : Unit.new(value)
20
14
  end
21
15
 
22
16
  # List the atoms associated with this scale's unit.
@@ -40,13 +34,6 @@ module Unitwise
40
34
  unit.special?
41
35
  end
42
36
 
43
- # Return a converted value for this scale, based on it's function for
44
- # scales with special units.
45
- # @param x [Numeric] Value to convert to or from
46
- # @param forward [true, false] whether to convert to this unit or from it.
47
- # @return [Numeric]
48
- # @api public
49
-
50
37
  # Get a scalar value for this scale.
51
38
  # @param magnitude [Numeric] An optional magnitude on this scale.
52
39
  # @return [Numeric] A scalar value on a linear scale
@@ -59,7 +46,7 @@ module Unitwise
59
46
  end
60
47
  end
61
48
 
62
- # Get a magnitude based on a linear scale value. Only used by scales with
49
+ # Get a magnitude based on a linear scale value. Only used by scales with
63
50
  # special atoms in it's hierarchy.
64
51
  # @param scalar [Numeric] A linear scalar value
65
52
  # @return [Numeric] The equivalent magnitude on this scale
@@ -78,6 +65,7 @@ module Unitwise
78
65
  def root_terms
79
66
  unit.root_terms
80
67
  end
68
+ memoize :root_terms
81
69
 
82
70
  # How far away is this instances unit from the deepest leve atom.
83
71
  # @return [Integer]
@@ -85,6 +73,7 @@ module Unitwise
85
73
  def depth
86
74
  unit.depth + 1
87
75
  end
76
+ memoize :depth
88
77
 
89
78
  # Convert to a simple string representing the scale.
90
79
  # @api public
@@ -95,5 +84,18 @@ module Unitwise
95
84
  def inspect
96
85
  "#<#{self.class} value=#{value} unit=#{unit}>"
97
86
  end
87
+
88
+ # Redefine hash for apropriate hash/key lookup
89
+ # @api semipublic
90
+ def hash
91
+ [value, unit.to_s, self.class].hash
92
+ end
93
+ memoize :hash
94
+
95
+ # Redefine hash equality to match the hashes
96
+ # @api semipublic
97
+ def eql?(other)
98
+ hash == other.hash
99
+ end
98
100
  end
99
101
  end
data/lib/unitwise/term.rb CHANGED
@@ -1,17 +1,9 @@
1
- require 'signed_multiset'
2
1
  module Unitwise
3
2
  # A Term is the combination of an atom, prefix, factor and annotation.
4
3
  # Not all properties have to be present. Examples: 'g', 'mm', 'mi2', '4[pi]',
5
4
  # 'kJ{Electric Potential}'
6
5
  class Term < Liner.new(:atom, :prefix, :factor, :exponent, :annotation)
7
- include Unitwise::Compatible
8
-
9
- # Setup a new term. Send a hash of properties, or ordered property values.
10
- # @api public
11
- def initialize(*args)
12
- super(*args)
13
- freeze
14
- end
6
+ include Compatible
15
7
 
16
8
  # Set the atom.
17
9
  # @param value [String, Atom] Either a string representing an Atom, or an
@@ -40,6 +32,7 @@ module Unitwise
40
32
  def depth
41
33
  atom ? atom.depth + 1 : 0
42
34
  end
35
+ memoize :depth
43
36
 
44
37
  # Determine if this is the last term in the scale chain
45
38
  # @return [true, false]
@@ -90,6 +83,7 @@ module Unitwise
90
83
  end
91
84
  end
92
85
  end
86
+ memoize :root_terms
93
87
 
94
88
  # Term multiplication. Multiply by a Unit, another Term, or a Numeric.
95
89
  # params other [Unit, Term, Numeric]
@@ -134,6 +128,7 @@ module Unitwise
134
128
  [(factor if factor != 1), prefix.to_s,
135
129
  atom.to_s, (exponent if exponent != 1)].compact.join('')
136
130
  end
131
+ memoize :to_s
137
132
 
138
133
  private
139
134
 
data/lib/unitwise/unit.rb CHANGED
@@ -4,7 +4,7 @@ module Unitwise
4
4
  # a magnitude, but it does have a scale.
5
5
  class Unit
6
6
  liner :expression, :terms
7
- include Unitwise::Compatible
7
+ include Compatible
8
8
 
9
9
  # Create a new unit. You can send an expression or a collection of terms
10
10
  # @param input [String, Unit, [Term]] A string expression, a unit, or a
@@ -17,32 +17,34 @@ module Unitwise
17
17
  @expression = input.to_s
18
18
  else
19
19
  @terms = input
20
+ @expression = Expression.compose(input)
20
21
  end
21
- end
22
-
23
- def expression
24
- @expression ||= (Expression.compose(@terms) if @terms)
22
+ freeze
25
23
  end
26
24
 
27
25
  def terms
28
- @terms ||= (Expression.decompose(@expression) if @expression)
26
+ @terms || Expression.decompose(expression)
29
27
  end
30
28
 
31
29
  def atoms
32
30
  terms.map(&:atom)
33
31
  end
32
+ memoize :atoms
34
33
 
35
34
  def special?
36
35
  terms.count == 1 && terms.all?(&:special?)
37
36
  end
37
+ memoize :special?
38
38
 
39
39
  def depth
40
40
  terms.map(&:depth).max + 1
41
41
  end
42
+ memoize :depth
42
43
 
43
44
  def root_terms
44
45
  terms.map(&:root_terms).flatten
45
46
  end
47
+ memoize :root_terms
46
48
 
47
49
  def scalar(magnitude = 1)
48
50
  terms.reduce(1) do |prod, term|
@@ -1,3 +1,3 @@
1
1
  module Unitwise
2
- VERSION = '0.6.1'
2
+ VERSION = '0.6.2'
3
3
  end
data/lib/unitwise.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  require 'liner'
2
+ require 'memoizable'
3
+ require 'parslet'
4
+ require 'signed_multiset'
5
+ require 'yaml'
2
6
 
3
7
  require 'unitwise/version'
4
8
  require 'unitwise/base'
@@ -4,15 +4,15 @@ module ScaleTests
4
4
  base.class_eval do
5
5
  subject { described_class.new(4, "J") }
6
6
 
7
- let(:mph) { Unitwise::Measurement.new(60, '[mi_i]/h') }
8
- let(:kmh) { Unitwise::Measurement.new(100, 'km/h') }
9
- let(:mile) { Unitwise::Measurement.new(3, '[mi_i]') }
10
- let(:hpm) { Unitwise::Measurement.new(6, 'h/[mi_i]') }
11
- let(:cui) { Unitwise::Measurement.new(12, "[in_i]3") }
12
- let(:cel) { Unitwise::Measurement.new(22, 'Cel') }
13
- let(:k) { Unitwise::Measurement.new(373.15, 'K') }
14
- let(:f) { Unitwise::Measurement.new(98.6, '[degF]')}
15
- let(:r) { Unitwise::Measurement.new(491.67, '[degR]') }
7
+ let(:mph) { described_class.new(60, '[mi_i]/h') }
8
+ let(:kmh) { described_class.new(100, 'km/h') }
9
+ let(:mile) { described_class.new(3, '[mi_i]') }
10
+ let(:hpm) { described_class.new(6, 'h/[mi_i]') }
11
+ let(:cui) { described_class.new(12, "[in_i]3") }
12
+ let(:cel) { described_class.new(22, 'Cel') }
13
+ let(:k) { described_class.new(373.15, 'K') }
14
+ let(:f) { described_class.new(98.6, '[degF]')}
15
+ let(:r) { described_class.new(491.67, '[degR]') }
16
16
 
17
17
  describe "#new" do
18
18
  it "must set attributes" do
@@ -79,6 +79,12 @@ module ScaleTests
79
79
  end
80
80
  end
81
81
 
82
+ describe "#frozen?" do
83
+ it "must be frozen" do
84
+ subject.frozen?.must_equal true
85
+ end
86
+ end
87
+
82
88
  end
83
89
  end
84
90
  end
@@ -120,4 +120,10 @@ describe Unitwise::Atom do
120
120
  skip("need to figure out mocking and stubbing with minitest")
121
121
  end
122
122
  end
123
+
124
+ describe "#frozen?" do
125
+ it "should be frozen" do
126
+ second.frozen?.must_equal true
127
+ end
128
+ end
123
129
  end
@@ -117,13 +117,44 @@ describe Unitwise::Measurement do
117
117
  describe "#coerce" do
118
118
  let(:meter) { Unitwise::Measurement.new(1, 'm') }
119
119
  it "must coerce numerics" do
120
- meter.coerce(5).must_equal [ Unitwise::Measurement.new(5, '1'), meter ]
120
+ (5 * meter).must_equal Unitwise::Measurement.new(5, 'm')
121
121
  end
122
122
  it "should raise an error for other crap" do
123
123
  lambda { meter.coerce("foo") }.must_raise TypeError
124
124
  end
125
125
  end
126
126
 
127
+ describe "equality" do
128
+ let(:m) { Unitwise::Measurement.new(1,'m') }
129
+ let(:mm) { Unitwise::Measurement.new(1000,'mm') }
130
+ let(:foot) { Unitwise::Measurement.new(1,'foot') }
131
+ let(:g) { Unitwise::Measurement.new(1,'gram') }
132
+ it "should be ==" do
133
+ assert m == m
134
+ assert m == mm
135
+ refute m == foot
136
+ refute m == g
137
+ end
138
+ it "should be ===" do
139
+ assert m == m
140
+ assert m === mm
141
+ refute m === foot
142
+ refute m == g
143
+ end
144
+ it "should be equal?" do
145
+ assert m.equal?(m)
146
+ refute m.equal?(mm)
147
+ refute m.equal?(foot)
148
+ refute m.equal?(g)
149
+ end
150
+ it "should be eql?" do
151
+ assert m.eql?(m)
152
+ refute m.equal?(mm)
153
+ refute m.equal?(foot)
154
+ refute m.equal?(g)
155
+ end
156
+ end
157
+
127
158
  describe "#method_missing" do
128
159
  let(:meter) { Unitwise::Measurement.new(1, 'm')}
129
160
  it "must convert 'to_mm'" do
@@ -40,5 +40,10 @@ describe Unitwise::Term do
40
40
  end
41
41
  end
42
42
 
43
+ describe "#frozen?" do
44
+ it "should be frozen" do
45
+ subject.frozen?.must_equal true
46
+ end
47
+ end
43
48
  end
44
49
  end
@@ -50,16 +50,22 @@ describe Unitwise::Unit do
50
50
  describe "#*" do
51
51
  it "should multiply units" do
52
52
  mult = kg * ms2
53
- mult.expression.to_s.must_match /kg.*\/s2/
54
- mult.expression.to_s.must_match /m.*\/s2/
53
+ mult.expression.to_s.must_match(/kg.*\/s2/)
54
+ mult.expression.to_s.must_match(/m.*\/s2/)
55
55
  end
56
56
  end
57
57
 
58
58
  describe "#/" do
59
59
  it "should divide units" do
60
60
  div = kg / ms2
61
- div.expression.to_s.must_match /kg.*\/m/
62
- div.expression.to_s.must_match /s2.*\/m/
61
+ div.expression.to_s.must_match(/kg.*\/m/)
62
+ div.expression.to_s.must_match(/s2.*\/m/)
63
+ end
64
+ end
65
+
66
+ describe "#frozen?" do
67
+ it "should be frozen" do
68
+ kg.frozen?.must_equal true
63
69
  end
64
70
  end
65
71
 
data/unitwise.gemspec CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Unitwise::VERSION
9
9
  gem.authors = ['Josh Lewis']
10
10
  gem.email = ['josh.w.lewis@gmail.com']
11
- gem.description = 'Ruby implementation of the Unified Code for Units of ' \
12
- 'Measure (UCUM)'
13
- gem.summary = 'Unitwise is a library for performing mathematical '\
14
- 'operations and conversions on all units defined by '\
15
- 'the Unified Code for Units of Measure(UCUM).'
11
+ gem.description = 'Physical quantity and units of measure conversion ' \
12
+ 'and math library'
13
+ gem.summary = 'Convert between and perform mathematical operations ' \
14
+ 'on physical quantities and units of measure defined ' \
15
+ 'by the Unified Code for Units of Measure.'
16
16
  gem.homepage = 'http://github.com/joshwlewis/unitwise'
17
17
  gem.license = 'MIT'
18
18
 
@@ -20,19 +20,21 @@ Gem::Specification.new do |gem|
20
20
  gem.test_files = gem.files.grep(/^test\//)
21
21
  gem.require_paths = ['lib']
22
22
 
23
- gem.add_dependency 'liner', '~> 0.2.4'
24
- gem.add_dependency 'signed_multiset', '~> 0.2.0'
23
+ gem.add_dependency 'liner', '~> 0.2'
24
+ gem.add_dependency 'signed_multiset', '~> 0.2'
25
+ gem.add_dependency 'memoizable', '~> 0.4'
25
26
 
26
27
  if RUBY_VERSION > '1.8.7'
27
- gem.add_dependency 'parslet', '~> 1.5'
28
- gem.add_development_dependency 'nokogiri', '~> 1.5'
29
- gem.add_development_dependency 'coveralls', '~> 0.6'
28
+ gem.add_dependency 'parslet', '~> 1.5'
29
+ gem.add_development_dependency 'nokogiri', '~> 1.5'
30
+ gem.add_development_dependency 'coveralls', '~> 0.6'
30
31
  else
31
- gem.add_dependency 'parslet', '~> 1.5.0'
32
- gem.add_development_dependency 'nokogiri', '~> 1.5.10'
32
+ gem.add_dependency 'parslet', '~> 1.5.0'
33
+ gem.add_development_dependency 'nokogiri', '~> 1.5.10'
33
34
  end
34
35
 
35
- gem.add_development_dependency 'minitest', '>= 5.0'
36
- gem.add_development_dependency 'rake', '>= 10.0'
37
- gem.add_development_dependency 'nori', '~> 2.3'
36
+ gem.add_development_dependency 'pry', '~> 0.9'
37
+ gem.add_development_dependency 'minitest', '~> 5.0'
38
+ gem.add_development_dependency 'rake', '~> 10.0'
39
+ gem.add_development_dependency 'nori', '~> 2.3'
38
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unitwise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lewis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-19 00:00:00.000000000 Z
11
+ date: 2014-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liner
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.4
19
+ version: '0.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.4
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: signed_multiset
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.0
33
+ version: '0.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.0
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: memoizable
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: parslet
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,32 +94,46 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: minitest
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - ">="
115
+ - - "~>"
88
116
  - !ruby/object:Gem::Version
89
117
  version: '5.0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - ">="
122
+ - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '5.0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: rake
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - ">="
129
+ - - "~>"
102
130
  - !ruby/object:Gem::Version
103
131
  version: '10.0'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
- - - ">="
136
+ - - "~>"
109
137
  - !ruby/object:Gem::Version
110
138
  version: '10.0'
111
139
  - !ruby/object:Gem::Dependency
@@ -122,7 +150,7 @@ dependencies:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
152
  version: '2.3'
125
- description: Ruby implementation of the Unified Code for Units of Measure (UCUM)
153
+ description: Physical quantity and units of measure conversion and math library
126
154
  email:
127
155
  - josh.w.lewis@gmail.com
128
156
  executables: []
@@ -209,8 +237,8 @@ rubyforge_project:
209
237
  rubygems_version: 2.2.0
210
238
  signing_key:
211
239
  specification_version: 4
212
- summary: Unitwise is a library for performing mathematical operations and conversions
213
- on all units defined by the Unified Code for Units of Measure(UCUM).
240
+ summary: Convert between and perform mathematical operations on physical quantities
241
+ and units of measure defined by the Unified Code for Units of Measure.
214
242
  test_files:
215
243
  - test/support/scale_tests.rb
216
244
  - test/test_helper.rb