Class: Weighable::Weight

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/weighable/weight.rb

Constant Summary collapse

UNIT =
{
  gram:      0,
  ounce:     1,
  pound:     2,
  milligram: 3,
  kilogram:  4,
  unit:      5
}.freeze
UNIT_ABBREVIATION =
{
  gram:      'g',
  ounce:     'oz',
  pound:     'lb',
  milligram: 'mg',
  kilogram:  'kg',
  unit:      nil
}.freeze
ABBREVIATION_ALIASES =
{
  'g'    => :gram,
  'oz'   => :ounce,
  'lb'   => :pound,
  'mg'   => :milligram,
  'kg'   => :kilogram,
  'ea'   => :unit,
  'each' => :unit,
  nil    => :unit
}.freeze
GRAMS_PER_OUNCE =
BigDecimal.new('28.34952')
GRAMS_PER_POUND =
BigDecimal.new('453.59237')
OUNCES_PER_POUND =
BigDecimal.new('16')
MILLIGRAMS_PER_GRAM =
BigDecimal.new('1000')
KILOGRAMS_PER_GRAM =
BigDecimal.new('0.001')
IDENTITY =
BigDecimal.new('1')
MILLIGRAMS_PER_OUNCE =
GRAMS_PER_OUNCE * MILLIGRAMS_PER_GRAM
KILOGRAMS_PER_OUNCE =
GRAMS_PER_OUNCE * KILOGRAMS_PER_GRAM
MILLIGRAMS_PER_POUND =
GRAMS_PER_POUND * MILLIGRAMS_PER_GRAM
KILOGRAMS_PER_POUND =
GRAMS_PER_POUND * KILOGRAMS_PER_GRAM
KILOGRAMS_PER_MILLIGRAM =
MILLIGRAMS_PER_GRAM**2
CONVERSIONS =
{
  UNIT[:unit] => {
    UNIT[:unit] => [:*, IDENTITY]
  },
  UNIT[:gram] => {
    UNIT[:gram]      => [:*, IDENTITY],
    UNIT[:ounce]     => [:/, GRAMS_PER_OUNCE],
    UNIT[:pound]     => [:/, GRAMS_PER_POUND],
    UNIT[:milligram] => [:*, MILLIGRAMS_PER_GRAM],
    UNIT[:kilogram]  => [:*, KILOGRAMS_PER_GRAM]
  },
  UNIT[:ounce] => {
    UNIT[:gram]      => [:*, GRAMS_PER_OUNCE],
    UNIT[:ounce]     => [:*, IDENTITY],
    UNIT[:pound]     => [:/, OUNCES_PER_POUND],
    UNIT[:milligram] => [:*, MILLIGRAMS_PER_OUNCE],
    UNIT[:kilogram]  => [:*, KILOGRAMS_PER_OUNCE]
  },
  UNIT[:pound] => {
    UNIT[:gram]      => [:*, GRAMS_PER_POUND],
    UNIT[:ounce]     => [:*, OUNCES_PER_POUND],
    UNIT[:pound]     => [:*, IDENTITY],
    UNIT[:milligram] => [:*, MILLIGRAMS_PER_POUND],
    UNIT[:kilogram]  => [:*, KILOGRAMS_PER_POUND]
  },
  UNIT[:milligram] => {
    UNIT[:gram]      => [:/, MILLIGRAMS_PER_GRAM],
    UNIT[:ounce]     => [:/, MILLIGRAMS_PER_OUNCE],
    UNIT[:pound]     => [:/, MILLIGRAMS_PER_POUND],
    UNIT[:milligram] => [:*, IDENTITY],
    UNIT[:kilogram]  => [:/, KILOGRAMS_PER_MILLIGRAM]
  },
  UNIT[:kilogram] => {
    UNIT[:gram]      => [:/, KILOGRAMS_PER_GRAM],
    UNIT[:ounce]     => [:/, KILOGRAMS_PER_OUNCE],
    UNIT[:pound]     => [:/, KILOGRAMS_PER_POUND],
    UNIT[:milligram] => [:*, KILOGRAMS_PER_MILLIGRAM],
    UNIT[:kilogram]  => [:*, IDENTITY]
  }
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, unit) ⇒ Weight

Returns a new instance of Weight.



109
110
111
112
# File 'lib/weighable/weight.rb', line 109

def initialize(value, unit)
  @value = value.to_d
  @unit  = unit.is_a?(Fixnum) ? unit : unit_from_symbol(unit.to_sym)
end

Instance Attribute Details

#unitObject (readonly)

Returns the value of attribute unit.



7
8
9
# File 'lib/weighable/weight.rb', line 7

def unit
  @unit
end

#valueObject (readonly)

Returns the value of attribute value.



7
8
9
# File 'lib/weighable/weight.rb', line 7

def value
  @value
end

Class Method Details

.from_value_and_unit(value, unit) ⇒ Object



97
98
99
100
101
# File 'lib/weighable/weight.rb', line 97

def self.from_value_and_unit(value, unit)
  unit = parse_unit(unit)
  fail ArgumentError, 'invalid weight' if unit.nil? || value.nil?
  Weight.new(value, unit)
end

.parse(string) ⇒ Object



92
93
94
95
# File 'lib/weighable/weight.rb', line 92

def self.parse(string)
  value, unit = string.split(' ')
  from_value_and_unit(value, unit)
end

.parse_unit(unit) ⇒ Object



103
104
105
106
107
# File 'lib/weighable/weight.rb', line 103

def self.parse_unit(unit)
  unit = ActiveSupport::Inflector.singularize(unit.downcase) unless unit.nil?
  unit_symbol = unit ? unit.to_sym : unit
  UNIT[unit_symbol] || ABBREVIATION_ALIASES[unit]
end

Instance Method Details

#*(other) ⇒ Object



154
155
156
157
158
159
160
161
# File 'lib/weighable/weight.rb', line 154

def *(other)
  if other.is_a? Weight
    other = other.to(unit_name)
    Weight.new(@value * other.value, unit_name)
  else
    Weight.new(@value * other, unit_name)
  end
end

#+(other) ⇒ Object



144
145
146
147
# File 'lib/weighable/weight.rb', line 144

def +(other)
  other = other.to(unit_name)
  Weight.new(@value + other.value, unit_name)
end

#-(other) ⇒ Object



149
150
151
152
# File 'lib/weighable/weight.rb', line 149

def -(other)
  other = other.to(unit_name)
  Weight.new(@value - other.value, unit_name)
end

#/(other) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/weighable/weight.rb', line 163

def /(other)
  if other.is_a? Weight
    other = other.to(unit_name)
    BigDecimal.new(@value / other.value)
  else
    Weight.new(@value / other, unit_name)
  end
end

#<(other) ⇒ Object



176
177
178
179
# File 'lib/weighable/weight.rb', line 176

def <(other)
  other = other.to(unit_name)
  @value < other.value
end

#<=(other) ⇒ Object



181
182
183
184
# File 'lib/weighable/weight.rb', line 181

def <=(other)
  other = other.to(unit_name)
  @value <= other.value
end

#<=>(other) ⇒ Object



196
197
198
199
# File 'lib/weighable/weight.rb', line 196

def <=>(other)
  other = other.to(unit_name)
  @value <=> other.value
end

#==(other) ⇒ Object



172
173
174
# File 'lib/weighable/weight.rb', line 172

def ==(other)
  other.class == self.class && other.value == @value && other.unit == @unit
end

#>(other) ⇒ Object



186
187
188
189
# File 'lib/weighable/weight.rb', line 186

def >(other)
  other = other.to(unit_name)
  @value > other.value
end

#>=(other) ⇒ Object



191
192
193
194
# File 'lib/weighable/weight.rb', line 191

def >=(other)
  other = other.to(unit_name)
  @value >= other.value
end

#round(precision = 0) ⇒ Object



201
202
203
204
# File 'lib/weighable/weight.rb', line 201

def round(precision = 0)
  @value = @value.round(precision)
  self
end

#to(unit) ⇒ Object



114
115
116
117
118
119
# File 'lib/weighable/weight.rb', line 114

def to(unit)
  new_unit = unit.is_a?(Fixnum) ? unit : unit_from_symbol(unit.to_sym)
  operator, conversion = conversion(@unit, new_unit)
  new_value = @value.public_send(operator, conversion)
  Weight.new(new_value, unit)
end

#to_s(only_unit: false) ⇒ Object



135
136
137
138
139
140
141
142
# File 'lib/weighable/weight.rb', line 135

def to_s(only_unit: false)
  if only_unit
    unit_abbreviation.to_s
  else
    value = @value.to_f == @value.to_i ? @value.to_i : @value.to_f
    [value, unit_abbreviation].compact.join(' ')
  end
end

#zero?Boolean

Returns:

  • (Boolean)


206
207
208
# File 'lib/weighable/weight.rb', line 206

def zero?
  @value.zero?
end