Class: Weighable::Weight

Inherits:
Object
  • Object
show all
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
ABBREVATION_ALIASES =
{
  'g'  => :gram,
  'oz' => :ounce,
  'lb' => :pound,
  'mg' => :milligram,
  'kg' => :kilogram,
  'ea' => :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.



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

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.



5
6
7
# File 'lib/weighable/weight.rb', line 5

def unit
  @unit
end

#valueObject (readonly)

Returns the value of attribute value.



5
6
7
# File 'lib/weighable/weight.rb', line 5

def value
  @value
end

Class Method Details

.parse(string) ⇒ Object



89
90
91
92
93
94
# File 'lib/weighable/weight.rb', line 89

def self.parse(string)
  value, unit = string.split(' ')
  unit = ABBREVATION_ALIASES[unit]
  fail ArgumentError, 'invalid weight' if unit.nil?
  Weight.new(value, unit)
end

Instance Method Details

#*(other) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/weighable/weight.rb', line 141

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



131
132
133
134
# File 'lib/weighable/weight.rb', line 131

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

#-(other) ⇒ Object



136
137
138
139
# File 'lib/weighable/weight.rb', line 136

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

#/(other) ⇒ Object



150
151
152
153
154
155
156
157
# File 'lib/weighable/weight.rb', line 150

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



163
164
165
166
# File 'lib/weighable/weight.rb', line 163

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

#<=(other) ⇒ Object



168
169
170
171
# File 'lib/weighable/weight.rb', line 168

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

#==(other) ⇒ Object



159
160
161
# File 'lib/weighable/weight.rb', line 159

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

#>(other) ⇒ Object



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

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

#>=(other) ⇒ Object



178
179
180
181
# File 'lib/weighable/weight.rb', line 178

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

#round(precision = 0) ⇒ Object



183
184
185
186
# File 'lib/weighable/weight.rb', line 183

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

#to(unit) ⇒ Object



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

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



122
123
124
125
126
127
128
129
# File 'lib/weighable/weight.rb', line 122

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