measurement 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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