This repository was archived by the owner on Jun 13, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 537
Expand file tree
/
Copy pathpackage.rb
More file actions
165 lines (139 loc) · 4.91 KB
/
package.rb
File metadata and controls
165 lines (139 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
module ActiveShipping #:nodoc:
class Package
cattr_accessor :default_options
attr_reader :options, :value, :currency
# Package.new(100, [10, 20, 30], :units => :metric)
# Package.new(Measured::Weight.new(100, :g), [10, 20, 30].map {|m| Length.new(m, :centimetres)})
# Package.new(100.grams, [10, 20, 30].map(&:centimetres))
def initialize(grams_or_ounces, dimensions, options = {})
options = @@default_options.update(options) if @@default_options
options.symbolize_keys!
@options = options
@dimensions = [dimensions].flatten.reject(&:nil?)
imperial = (options[:units] == :imperial)
weight_imperial = dimensions_imperial = imperial if options.include?(:units)
if options.include?(:weight_units)
weight_imperial = (options[:weight_units] == :imperial)
end
if options.include?(:dim_units)
dimensions_imperial = (options[:dim_units] == :imperial)
end
@weight_unit_system = weight_imperial ? :imperial : :metric
@dimensions_unit_system = dimensions_imperial ? :imperial : :metric
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Measured::Weight, @weight_unit_system, :grams, :ounces)
if @dimensions.blank?
zero_length = Measured::Length.new(0, (dimensions_imperial ? :inches : :centimetres))
@dimensions = [zero_length] * 3
else
process_dimensions
end
@value = Package.cents_from(options[:value])
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
@gift = options[:gift] ? true : false
@oversized = options[:oversized] ? true : false
@unpackaged = options[:unpackaged] ? true : false
end
def unpackaged?
@unpackaged
end
def oversized?
@oversized
end
def cylinder?
@cylinder
end
alias_method :tube?, :cylinder?
def gift?
@gift
end
def ounces(options = {})
weight(options).convert_to(:oz).value.to_f
end
alias_method :oz, :ounces
def grams(options = {})
weight(options).convert_to(:g).value.to_f
end
alias_method :g, :grams
def pounds(options = {})
weight(options).convert_to(:lb).value.to_f
end
alias_method :lb, :pounds
alias_method :lbs, :pounds
def kilograms(options = {})
weight(options).convert_to(:kg).value.to_f
end
alias_method :kg, :kilograms
alias_method :kgs, :kilograms
def inches(measurement = nil)
@inches ||= @dimensions.map { |m| m.convert_to(:in).value.to_f }
measurement.nil? ? @inches : measure(measurement, @inches)
end
alias_method :in, :inches
def centimetres(measurement = nil)
@centimetres ||= @dimensions.map { |m| m.convert_to(:cm).value.to_f }
measurement.nil? ? @centimetres : measure(measurement, @centimetres)
end
alias_method :cm, :centimetres
def weight(options = {})
case options[:type]
when nil, :actual
@weight
when :volumetric, :dimensional
@volumetric_weight ||= begin
m = Measured::Weight.new((centimetres(:box_volume) / 6.0), :grams)
@weight_unit_system == :imperial ? m.convert_to(:oz) : m
end
when :billable
[weight, weight(:type => :volumetric)].max
end
end
alias_method :mass, :weight
def self.cents_from(money)
return nil if money.nil?
if money.respond_to?(:cents)
return money.cents
else
case money
when Float
(money * 100).round
when String
money =~ /\./ ? (money.to_f * 100).round : money.to_i
else
money.to_i
end
end
end
private
def attribute_from_metric_or_imperial(obj, klass, unit_system, metric_unit, imperial_unit)
if obj.is_a?(klass)
return obj
else
return klass.new(obj, (unit_system == :imperial ? imperial_unit : metric_unit))
end
end
def measure(measurement, ary)
case measurement
when Integer then ary[measurement]
when :x, :max, :length, :long then ary[2]
when :y, :mid, :width, :wide then ary[1]
when :z, :min, :height, :depth, :high, :deep then ary[0]
when :girth, :around, :circumference
self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 2) : (2 * ary[0]) + (2 * ary[1])
when :volume then self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume, ary)
when :box_volume then ary[0] * ary[1] * ary[2]
end
end
def process_dimensions
@dimensions = @dimensions.map do |l|
attribute_from_metric_or_imperial(l, Measured::Length, @dimensions_unit_system, :centimetres, :inches)
end.sort
# [1,2] => [1,1,2]
# [5] => [5,5,5]
# etc..
2.downto(@dimensions.length) do |_n|
@dimensions.unshift(@dimensions[0])
end
end
end
end