measurement 0.2.2 → 0.2.3

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/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.2.3 Group formats
2
+
1
3
  v0.2.2 Better formatting functions
2
4
 
3
5
  v0.2.1 Added methods to Float, Fixnum and String - to_measurement
@@ -21,14 +21,14 @@ require File.join(File.dirname(__FILE__), '..', 'measurement')
21
21
  # puts Length.parse('180.34cm').in_feet_and_inches => 5' 11"
22
22
  #
23
23
  class Length < Measurement::Base
24
- base :metre, :metres, :suffix => 'm'
25
- unit 1000, :kilometre, :kilometres, :km, :suffix => 'km'
26
- unit 0.01, :centimetre, :centimetres, :cm, :suffix => 'cm'
27
- unit 0.001, :millimetre, :mm, :suffix => 'mm'
24
+ base :metre, :metres, :suffix => 'm', :group => :metric
25
+ unit 1000, :kilometre, :kilometres, :km, :suffix => 'km', :group => :metric
26
+ unit 0.01, :centimetre, :centimetres, :cm, :suffix => 'cm', :group => :metric
27
+ unit 0.001, :millimetre, :mm, :suffix => 'mm', :group => :metric
28
28
 
29
- unit 0.0254, :inch, :inches, :suffix => '"'
30
- unit 0.3048, :feet, :foot, :suffix => "'"
31
- unit 1609.34, :mile, :miles, :suffix => ' miles'
29
+ unit 0.0254, :inch, :inches, :suffix => '"', :group => :imperial
30
+ unit 0.3048, :feet, :foot, :suffix => "'", :group => :imperial
31
+ unit 1609.34, :mile, :miles, :suffix => ' miles', :group => :imperial
32
32
  unit 0.1016, :hand, :hands, :suffix => ' hands'
33
33
 
34
34
  unit 299792458, :light_seconds, :suffix => ' light seconds'
@@ -1,16 +1,27 @@
1
1
  module Measurement
2
2
  class Unit
3
- attr_reader :names
3
+ include Comparable
4
+
5
+ attr_reader :names, :scale, :groups
4
6
 
5
7
  def initialize(scale, *args)
6
8
  @options = args.last.is_a?(Hash) ? args.pop : {}
7
9
  @names = args
8
10
  @scale = scale
11
+ @groups = [@options[:group]].flatten
12
+ end
13
+
14
+ def <=>(anOther)
15
+ scale <=> anOther.scale
9
16
  end
10
17
 
11
18
  def has_name?(name)
12
19
  names.include?(name)
13
20
  end
21
+
22
+ def in_group?(group)
23
+ groups.include?(group.to_sym)
24
+ end
14
25
 
15
26
  def from(amount)
16
27
  amount.to_f * @scale
@@ -16,9 +16,10 @@ require File.join(File.dirname(__FILE__), '..', 'measurement')
16
16
  # puts Length.parse('100kg').in_lbs_and_oz => 220lbs 7oz
17
17
  #
18
18
  class Weight < Measurement::Base
19
- base :gram, :grams, :suffix => 'g'
20
- unit 1000.0, :kilogram, :kilograms, :kg, :kgs, :suffix => 'kg'
21
- unit 453.59236, :pounds, :pound, :lbs, :suffix => 'lbs'
22
- unit 28.3495231, :ounces, :ounce, :oz, :suffix => 'oz'
23
- unit 6350.29318, :stone, :st, :suffix => 'st'
19
+ base :gram, :grams, :suffix => 'g', :group => :metric
20
+ unit 1000.0, :kilogram, :kilograms, :kg, :kgs, :suffix => 'kg', :group => :metric
21
+
22
+ unit 453.59236, :pounds, :pound, :lbs, :suffix => 'lbs', :group => [:imperial, :us]
23
+ unit 28.3495231, :ounces, :ounce, :oz, :suffix => 'oz', :group => :us
24
+ unit 6350.29318, :stone, :st, :suffix => 'st', :group => :imperial
24
25
  end
data/lib/measurement.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require File.join(File.dirname(__FILE__), 'measurement', 'unit')
2
+ require File.join(File.dirname(__FILE__), 'measurement', 'unit_group')
2
3
 
3
4
  module Measurement
4
5
  class NoUnitFoundException < Exception
@@ -62,21 +63,23 @@ module Measurement
62
63
  end
63
64
 
64
65
  def self.register_measurement
65
- method_name = name.gsub(/\s/, '_').gsub(/.[A-Z]/) do |s|
66
- s[0,1] + '_' + s[1,1].downcase
67
- end.downcase
66
+ if name && name.length > 0
67
+ method_name = name.gsub(/\s/, '_').gsub(/.[A-Z]/) do |s|
68
+ s[0,1] + '_' + s[1,1].downcase
69
+ end.downcase
68
70
 
69
- [Fixnum, Float].each do |klass|
70
- klass.class_eval %Q{
71
- def to_#{method_name}
72
- #{name}.new(self)
73
- end}
74
- end
71
+ [Fixnum, Float].each do |klass|
72
+ klass.class_eval %Q{
73
+ def to_#{method_name}
74
+ #{name}.new(self)
75
+ end}
76
+ end
75
77
 
76
- String.class_eval %Q{
77
- def to_#{method_name}
78
- #{name}.parse(self)
79
- end}
78
+ String.class_eval %Q{
79
+ def to_#{method_name}
80
+ #{name}.parse(self)
81
+ end}
82
+ end
80
83
  end
81
84
 
82
85
  def self.units # :nodoc:
@@ -101,6 +104,7 @@ module Measurement
101
104
  #
102
105
  # * <tt>prefix</tt> - A prefix to use when formatting the unit.
103
106
  # * <tt>suffix</tt> - A suffix to use when formatting the unit.
107
+ # * <tt>group</tt> - A group that can be used when formatting to combine the unit formats.
104
108
  #
105
109
  def self.unit(unit, *args)
106
110
  add_unit(Unit.new(unit, *args))
@@ -109,14 +113,29 @@ module Measurement
109
113
  def self.add_unit(unit) # :nodoc:
110
114
  units << unit
111
115
  end
116
+
117
+ def self.fetch_group(scale) # :nodoc:
118
+ scale = scale.to_sym
119
+ @groups ||= {}
120
+ @groups[scale] ||= begin
121
+ group = units.inject([]) do |m,n|
122
+ m << n if n.in_group?(scale)
123
+ m
124
+ end
125
+
126
+ if group.any?
127
+ UnitGroup.new(group)
128
+ end
129
+ end
130
+ end
112
131
 
113
- def self.fetch_scale(scale = nil) # :nodoc:
132
+ def self.fetch_scale(scale = nil, raise_error = true) # :nodoc:
114
133
  unit = (scale.nil? ? base : units.detect do |unit|
115
134
  unit.has_name?(scale.to_sym)
116
- end)
135
+ end) || fetch_group(scale)
117
136
 
118
137
  unless unit
119
- raise NoUnitFoundException.new(scale)
138
+ raise NoUnitFoundException.new(scale) if raise_error
120
139
  else
121
140
  unit
122
141
  end
@@ -252,25 +271,22 @@ module Measurement
252
271
  #
253
272
  # Length.new(1.8034).in_feet_and_inches => 5' 11"
254
273
  #
274
+ # The unit group can also be specified to get a similar effect:
275
+ #
276
+ # Length.new(1.8034).to_s(:metric) => '1m 80cm 3mm'
277
+ #
255
278
  # A precision can be specified, otherwise the measurement
256
279
  # is rounded to the nearest integer.
257
280
  def to_s(unit = nil, precision = 0)
258
281
  if unit.to_s =~ /_and_/
259
- units = unit.to_s.split('_and_')
260
- amount = @amount
261
- strs = []
262
-
263
- while unit = units.shift
264
- n_in = self.class.to(amount, unit.to_sym)
265
- n_in = n_in.floor unless units.empty?
266
- n_out = self.class.from(n_in, unit.to_sym)
267
- amount -= self.class.from(n_in, unit.to_sym)
268
- strs << self.class.format(n_out, unit.to_sym, 0)
282
+ units = unit.to_s.split('_and_').map do |unit|
283
+ self.class.fetch_scale(unit)
269
284
  end
270
-
271
- strs.join(' ')
285
+
286
+ UnitGroup.new(units).format(@amount, precision)
272
287
  else
273
- self.class.format(@amount, unit, precision)
288
+ unit = self.class.fetch_scale(unit)
289
+ unit.format(@amount, precision)
274
290
  end
275
291
  end
276
292
  alias_method :format, :to_s
data/measurement.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{measurement}
5
- s.version = "0.2.2"
5
+ s.version = "0.2.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Jeremy Wells"]
9
- s.date = %q{2010-02-28}
9
+ s.date = %q{2010-03-01}
10
10
  s.description = %q{A library for holding, converting and formatting measurements}
11
11
  s.email = %q{jemmyw@gmail.com}
12
12
  s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "lib/measurement.rb", "lib/measurement/length.rb", "lib/measurement/unit.rb", "lib/measurement/weight.rb"]
@@ -105,4 +105,41 @@ describe Measurement::Base do
105
105
  length.in_cm_and_mm.should == length.to_s(:cm_and_mm)
106
106
  end
107
107
  end
108
+
109
+ describe '#to_s' do
110
+ before do
111
+ @klass = Class.new(Measurement::Base)
112
+ @klass.base :grams, :group => :metric, :suffix => 'g'
113
+ @klass.unit 1000, :kilograms, :group => :metric, :suffix => 'kg'
114
+ @instance = @klass.new(1500)
115
+ end
116
+
117
+ it 'should return the base unit format if no unit is specified' do
118
+ @instance.to_s.should == '1500g'
119
+ end
120
+
121
+ it 'should return the unit format if a unit is specified' do
122
+ @instance.to_s(:kilograms).should == '2kg'
123
+ end
124
+
125
+ it 'should return the unit format with precision if specified' do
126
+ @instance.to_s(:kilograms, 1).should == '1.5kg'
127
+ end
128
+
129
+ it 'should return the combined unit formats if separated by and' do
130
+ @instance.to_s(:kilograms_and_grams).should == '1kg 500g'
131
+ end
132
+
133
+ it 'should return the combined unit formats if a group is specified' do
134
+ @instance.to_s(:metric).should == '1kg 500g'
135
+ end
136
+
137
+ it 'should not return any lower bound measurments if they are 0' do
138
+ @klass.new(10000).to_s(:metric).should == '10kg'
139
+ end
140
+
141
+ it 'should not return any upper bound measurements if they are 0' do
142
+ @klass.new(10).to_s(:metric).should == '10g'
143
+ end
144
+ end
108
145
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: measurement
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Wells
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-28 00:00:00 +13:00
12
+ date: 2010-03-01 00:00:00 +13:00
13
13
  default_executable:
14
14
  dependencies: []
15
15