gorilla 0.0.1.beta
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/README.rdoc +3 -0
- data/Rakefile +13 -0
- data/lib/gorilla.rb +11 -0
- data/lib/gorilla/all.rb +5 -0
- data/lib/gorilla/core_ext.rb +72 -0
- data/lib/gorilla/scanner.rb +222 -0
- data/lib/gorilla/scanners.rb +9 -0
- data/lib/gorilla/scanners/omni_scanner.rb +21 -0
- data/lib/gorilla/scanners/temperature_scanner.rb +11 -0
- data/lib/gorilla/scanners/time_scanner.rb +34 -0
- data/lib/gorilla/scanners/volume_scanner.rb +15 -0
- data/lib/gorilla/scanners/weight_scanner.rb +10 -0
- data/lib/gorilla/scantron_ext.rb +83 -0
- data/lib/gorilla/temperature.rb +19 -0
- data/lib/gorilla/time.rb +51 -0
- data/lib/gorilla/unit.rb +453 -0
- data/lib/gorilla/version.rb +10 -0
- data/lib/gorilla/volume.rb +13 -0
- data/lib/gorilla/weight.rb +8 -0
- data/test/gorilla/scanners/temperature_scanner_test.rb +42 -0
- data/test/gorilla/scanners/time_scanner_test.rb +123 -0
- data/test/gorilla/scanners/volume_scanner_test.rb +148 -0
- data/test/gorilla/scanners/weight_scanner_test.rb +57 -0
- data/test/gorilla/time_test.rb +14 -0
- data/test/test_helper.rb +10 -0
- metadata +122 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'gorilla/unit'
|
|
3
|
+
|
|
4
|
+
module Gorilla
|
|
5
|
+
class Temperature < Unit
|
|
6
|
+
unit :celsius, lambda { |t| (t * Rational(9, 5)) + 32 }, :fahrenheit
|
|
7
|
+
unit :fahrenheit, lambda { |t| (t - 32) * Rational(5, 9) }, :celsius
|
|
8
|
+
|
|
9
|
+
self.pluralize = false
|
|
10
|
+
|
|
11
|
+
def humanized_amount
|
|
12
|
+
"#{super}°"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def humanized_unit
|
|
16
|
+
super.capitalize if unit
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/gorilla/time.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'gorilla/unit'
|
|
2
|
+
|
|
3
|
+
module Gorilla
|
|
4
|
+
class Time < Unit
|
|
5
|
+
base :second, :metric => true
|
|
6
|
+
|
|
7
|
+
unit :minute, 60, :second
|
|
8
|
+
unit :hour, 60, :minute
|
|
9
|
+
unit :day, 24, :hour
|
|
10
|
+
unit :week, 7, :day
|
|
11
|
+
unit :month, 30, :day
|
|
12
|
+
unit :year, 52, :week
|
|
13
|
+
unit :decade, 10, :year
|
|
14
|
+
unit :century, 10, :decade
|
|
15
|
+
unit :millennium, 10, :century
|
|
16
|
+
|
|
17
|
+
# Expands in favor of non-metric units first. This behavior can be
|
|
18
|
+
# overridden by providing a block, and negated if the block returns +true+.
|
|
19
|
+
#
|
|
20
|
+
# ==== Example
|
|
21
|
+
#
|
|
22
|
+
# time = Gorilla::Time.new 1000, :second
|
|
23
|
+
# time.expand
|
|
24
|
+
# # => [(16 minutes), (40 seconds)]
|
|
25
|
+
#
|
|
26
|
+
# time.expand(:metric => true) { true }
|
|
27
|
+
# # => [(1 kilosecond)]
|
|
28
|
+
def expand options = {}, &block
|
|
29
|
+
block ||= lambda { |t| !t.metric? || t.unit == :second }
|
|
30
|
+
super options, &block
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns a string which represents the duration as defined by ISO 8601.
|
|
34
|
+
#
|
|
35
|
+
# time = 1.year + 2.weeks + 3.days + 4.hours + 5.minutes + 6.5.seconds
|
|
36
|
+
# time.iso8601
|
|
37
|
+
# # => "P1Y2W3DT4H5M6.5S"
|
|
38
|
+
def iso8601
|
|
39
|
+
string = 'P'
|
|
40
|
+
day = self.class.new 1, :day
|
|
41
|
+
|
|
42
|
+
expand.each do |measured|
|
|
43
|
+
string << 'T' if !string.include?('T') && measured < day
|
|
44
|
+
string << measured.humanized_amount
|
|
45
|
+
string << measured.unit.to_s[0, 1].capitalize
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
string
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/gorilla/unit.rb
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# require 'bigdecimal'
|
|
2
|
+
|
|
3
|
+
module Gorilla
|
|
4
|
+
# The base unit class from which all inherit.
|
|
5
|
+
class Unit
|
|
6
|
+
# Pluralize by default.
|
|
7
|
+
@pluralize = true
|
|
8
|
+
|
|
9
|
+
# Maps metric prefixes to scale.
|
|
10
|
+
METRIC_MAP = {
|
|
11
|
+
:yotta => 1_000_000_000_000_000_000_000_000,
|
|
12
|
+
:zetta => 1_000_000_000_000_000_000_000,
|
|
13
|
+
:exa => 1_000_000_000_000_000_000,
|
|
14
|
+
:peta => 1_000_000_000_000_000,
|
|
15
|
+
:tera => 1_000_000_000_000,
|
|
16
|
+
:giga => 1_000_000_000,
|
|
17
|
+
:mega => 1_000_000,
|
|
18
|
+
:kilo => 1_000,
|
|
19
|
+
:hecto => 100,
|
|
20
|
+
:deca => 10,
|
|
21
|
+
:deci => Rational(1, 10),
|
|
22
|
+
:centi => Rational(1, 100),
|
|
23
|
+
:milli => Rational(1, 1_000),
|
|
24
|
+
:micro => Rational(1, 1_000_000),
|
|
25
|
+
:nano => Rational(1, 1_000_000_000),
|
|
26
|
+
:pico => Rational(1, 1_000_000_000_000),
|
|
27
|
+
:femto => Rational(1, 1_000_000_000_000_000),
|
|
28
|
+
:atto => Rational(1, 1_000_000_000_000_000_000),
|
|
29
|
+
:zepto => Rational(1, 1_000_000_000_000_000_000_000),
|
|
30
|
+
:yocto => Rational(1, 1_000_000_000_000_000_000_000_000)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# The base unit of the class.
|
|
35
|
+
attr_accessor :base_unit
|
|
36
|
+
|
|
37
|
+
# Whether or not to pluralize a unit.
|
|
38
|
+
attr_accessor :pluralize
|
|
39
|
+
|
|
40
|
+
# Defines the base unit of the class.
|
|
41
|
+
#
|
|
42
|
+
# ==== Example
|
|
43
|
+
#
|
|
44
|
+
# class Coolness < Gorilla::Unit
|
|
45
|
+
# base :Fonzie, :metric => true
|
|
46
|
+
# end
|
|
47
|
+
def base name, options = {}
|
|
48
|
+
self.base_unit = name
|
|
49
|
+
unit name, Rational(1), options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Defines a unit of the class.
|
|
53
|
+
#
|
|
54
|
+
# The rule can be a Numeric factor or Proc relative to another unit. An
|
|
55
|
+
# optional hash of data can be appended to the rule and will be
|
|
56
|
+
# accessible wherever that rule is yielded to a block.
|
|
57
|
+
#
|
|
58
|
+
# ==== Example
|
|
59
|
+
#
|
|
60
|
+
# Gorilla::Weight.class_eval do
|
|
61
|
+
# unit :sun, 2 * (10 ** 30), :kilogram
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# Gorilla::Temperature.class_eval do
|
|
65
|
+
# unit :Q, lambda { |t| t + 57 }, :celsius, :source => 'Zork'
|
|
66
|
+
# end
|
|
67
|
+
def unit *args
|
|
68
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
69
|
+
name, conversion, other = args
|
|
70
|
+
|
|
71
|
+
if conversion.respond_to? :call
|
|
72
|
+
(options[:rules] ||= {})[other] = conversion
|
|
73
|
+
elsif other
|
|
74
|
+
options[:factor] = Rational rules[other][:factor], conversion
|
|
75
|
+
else
|
|
76
|
+
options[:factor] = Rational conversion
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
rules[name] = options
|
|
80
|
+
|
|
81
|
+
if options[:metric]
|
|
82
|
+
METRIC_MAP.each_pair do |prefix, factor|
|
|
83
|
+
subname = :"#{prefix}#{name}"
|
|
84
|
+
unit subname, factor, name
|
|
85
|
+
rules[subname][:metric] = true
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns the hash of rules for the current class.
|
|
91
|
+
def rules
|
|
92
|
+
Gorilla.units[name] ||= {}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def inherited klass
|
|
98
|
+
klass.pluralize = pluralize
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# The unit amount (can be +nil+).
|
|
103
|
+
attr_reader :amount
|
|
104
|
+
|
|
105
|
+
# The unit name.
|
|
106
|
+
attr_reader :unit
|
|
107
|
+
|
|
108
|
+
# Instantiates a new unit for the class. Assumes the base unit if one is
|
|
109
|
+
# defined.
|
|
110
|
+
#
|
|
111
|
+
# ==== Example
|
|
112
|
+
#
|
|
113
|
+
# Gorilla::Unit.new 1 # => (1)
|
|
114
|
+
# Gorilla::Time.new 1 # => (1 second)
|
|
115
|
+
# Gorilla::Time.new 1, :minute # => (1 minute)
|
|
116
|
+
def initialize amount, unit = self.class.base_unit
|
|
117
|
+
if unit && self.class.rules[unit].nil?
|
|
118
|
+
raise TypeError, "no such unit #{self.class.name}:#{unit}"
|
|
119
|
+
elsif unit.nil? && !instance_of?(Unit)
|
|
120
|
+
raise ArgumentError, "unit can't be nil for #{self.class.name}"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
@amount, @unit = (amount.to_r if amount), unit
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Converts an instance to a new unit.
|
|
127
|
+
#
|
|
128
|
+
# ==== Example
|
|
129
|
+
#
|
|
130
|
+
# Gorilla::Weight.new(1, :pound).convert_to(:ounce) # => (16 ounces)
|
|
131
|
+
def convert_to other_unit
|
|
132
|
+
return dup if unit == other_unit
|
|
133
|
+
|
|
134
|
+
unless self.class.rules.key? other_unit
|
|
135
|
+
raise TypeError, "no such unit #{self.class.name}:#{other_unit}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if unit and rules = self.class.rules[unit][:rules]
|
|
139
|
+
unless rules.key? other_unit
|
|
140
|
+
raise TypeError, "can't convert to #{self.class.name}:#{other_unit}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
amount = rules[other_unit].call normalized_amount
|
|
144
|
+
return self.class.new amount, other_unit
|
|
145
|
+
else
|
|
146
|
+
amount = normalized_amount
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
new = self.class.new amount
|
|
150
|
+
new.unit = other_unit
|
|
151
|
+
new
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Returns whether a unit was defined as metric.
|
|
155
|
+
#
|
|
156
|
+
# ==== Example
|
|
157
|
+
#
|
|
158
|
+
# class Coolness < Gorilla::Unit
|
|
159
|
+
# base :Fonzie, :metric => true
|
|
160
|
+
# end
|
|
161
|
+
# Coolness.new(1, :megaFonzie).metric? # => true
|
|
162
|
+
def metric?
|
|
163
|
+
unit and self.class.rules[unit][:metric] || false
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Normalizes and expands a unit into an array of units. Filters rules based
|
|
167
|
+
# on provided options, and yields each unit to an optional block. If the
|
|
168
|
+
# block returns +false+, the unit will be omitted.
|
|
169
|
+
#
|
|
170
|
+
# ==== Example
|
|
171
|
+
#
|
|
172
|
+
# Gorilla::Weight.new(24, :ounce).expand
|
|
173
|
+
# # => [(1 pound), (8 ounces)]
|
|
174
|
+
#
|
|
175
|
+
# # The block provided here is also the default for Gorilla::Time.
|
|
176
|
+
# Gorilla::Time.new(1000, :second).expand { |t|
|
|
177
|
+
# !t.metric? && t.unit != :minute || t.unit == :second
|
|
178
|
+
# }
|
|
179
|
+
# # => [(16 minutes), (40 seconds)]
|
|
180
|
+
def expand options = {}
|
|
181
|
+
rules = rules_for_options options
|
|
182
|
+
return [self] if rules.empty?
|
|
183
|
+
|
|
184
|
+
clone = self
|
|
185
|
+
units = []
|
|
186
|
+
rules.sort_by { |_, r| r[:factor] }.each do |rule|
|
|
187
|
+
clone = clone.convert_to rule[0]
|
|
188
|
+
next unless yield clone if block_given?
|
|
189
|
+
amount = clone.truncate
|
|
190
|
+
units << clone and break if clone.metric? && amount > 0
|
|
191
|
+
units << self.class.new(amount, clone.unit) if amount > 0
|
|
192
|
+
clone %= 1
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
units
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Normalizes a unit to the nearest whole number. Filters rules based on
|
|
199
|
+
# provided options, and yields each unit to an optional block. If the block
|
|
200
|
+
# returns +false+, the unit will be omitted.
|
|
201
|
+
#
|
|
202
|
+
# ==== Example
|
|
203
|
+
#
|
|
204
|
+
# weight = Gorilla::Weight.new 0.021, :kilogram # => (0.021 kilograms)
|
|
205
|
+
# weight.normalize
|
|
206
|
+
# # => (21 grams)
|
|
207
|
+
#
|
|
208
|
+
# weight.normalize { |w| w.metric? && w.amount >= 1 }
|
|
209
|
+
# # => (2.1 decagrams)
|
|
210
|
+
def normalize options = {}
|
|
211
|
+
rules = rules_for_options options
|
|
212
|
+
return if rules.empty?
|
|
213
|
+
|
|
214
|
+
rules.sort_by { |_, r| r[:factor] }.each do |rules|
|
|
215
|
+
clone = convert_to rules[0]
|
|
216
|
+
block_given? and case yield clone
|
|
217
|
+
when true then return clone when false then next
|
|
218
|
+
end
|
|
219
|
+
return clone if clone.amount >= 1 && (clone % 1).round(10).zero?
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def normalize! options = {}, &block
|
|
226
|
+
normalized = normalize options, &block
|
|
227
|
+
return if eql? normalized
|
|
228
|
+
@amount, @unit = normalized.amount, normalized.unit
|
|
229
|
+
self
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def coerced_amount
|
|
233
|
+
return unless self.amount
|
|
234
|
+
amount = metric? ? self.amount.to_f : self.amount.to_r
|
|
235
|
+
amount = amount.to_f if amount.denominator > 100
|
|
236
|
+
amount = amount.to_i if amount.denominator == 1
|
|
237
|
+
amount
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def humanized_amount
|
|
241
|
+
return unless amount = coerced_amount
|
|
242
|
+
|
|
243
|
+
if amount.is_a?(Rational) && amount.numerator > amount.denominator
|
|
244
|
+
amount = "#{amount.floor} #{amount % 1}"
|
|
245
|
+
else
|
|
246
|
+
amount = "#{amount}"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
amount = amount.split '.'
|
|
250
|
+
amount[0].gsub! /(?!\.)(\d)(?=(\d{3})+(?!\d))/, '\1,'
|
|
251
|
+
amount.join '.'
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def humanized_unit
|
|
255
|
+
return unless unit
|
|
256
|
+
humanized = unit.to_s.gsub '_', ' '
|
|
257
|
+
humanized << (humanized.end_with?('s') ? 'es' : 's') if pluralize?
|
|
258
|
+
humanized
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def to_s
|
|
262
|
+
[humanized_amount, humanized_unit].compact.join(' ')
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def inspect
|
|
266
|
+
"(#{to_s})"
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
include Comparable
|
|
270
|
+
|
|
271
|
+
def <=> other
|
|
272
|
+
return unless self.class == other.class
|
|
273
|
+
normalized_amount <=> other.normalized_amount
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def == other
|
|
277
|
+
return amount == other if instance_of? Unit
|
|
278
|
+
self.class == other.class && normalized_amount == other.normalized_amount
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def + other
|
|
282
|
+
self.class.new amount + other.convert_to(unit).amount, unit
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def - other
|
|
286
|
+
self.class.new amount - other.convert_to(unit).amount, unit
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def * other
|
|
290
|
+
self.class.new amount * other, unit
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def / other
|
|
294
|
+
self.class.new amount / other, unit
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def % other
|
|
298
|
+
self.class.new amount % other, unit
|
|
299
|
+
end
|
|
300
|
+
alias modulo %
|
|
301
|
+
|
|
302
|
+
def ** other
|
|
303
|
+
self.class.new amount ** other, unit
|
|
304
|
+
end
|
|
305
|
+
alias power! **
|
|
306
|
+
|
|
307
|
+
def abs
|
|
308
|
+
self.class.new amount.abs, unit
|
|
309
|
+
end
|
|
310
|
+
alias magnitude abs
|
|
311
|
+
|
|
312
|
+
def abs2
|
|
313
|
+
self.class.new amount.abs2, unit
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def ceil
|
|
317
|
+
amount.ceil
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def coerce other
|
|
321
|
+
case other
|
|
322
|
+
when Unit
|
|
323
|
+
[other, convert_to(other.unit)]
|
|
324
|
+
when Numeric
|
|
325
|
+
[self.class.new(other, unit), self]
|
|
326
|
+
else
|
|
327
|
+
raise TypeError, "#{self.class} can't be coerced into #{other.class}"
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def denominator
|
|
332
|
+
amount.denominator
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def div n
|
|
336
|
+
to_i.div n
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def eql? other
|
|
340
|
+
unit.eql?(other.unit) && normalized_amount.eql?(other.normalized_amount)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def even?
|
|
344
|
+
amount.even?
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def floor
|
|
348
|
+
amount.floor
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def finite?
|
|
352
|
+
amount.finite?
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def infinite?
|
|
356
|
+
amount.infinite?
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def integer?
|
|
360
|
+
amount && coerced_amount.integer?
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def nonzero?
|
|
364
|
+
amount.zero?
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def numerator
|
|
368
|
+
amount.numerator
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def odd?
|
|
372
|
+
amount && amount.odd?
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def real?
|
|
376
|
+
amount && amount.real?
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def round digits
|
|
380
|
+
amount.round digits
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def to_f
|
|
384
|
+
amount.to_f
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def to_i
|
|
388
|
+
amount.to_i
|
|
389
|
+
end
|
|
390
|
+
alias to_int to_i
|
|
391
|
+
alias truncate to_i
|
|
392
|
+
|
|
393
|
+
def to_r
|
|
394
|
+
amount.to_r
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def zero?
|
|
398
|
+
amount.zero?
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
protected
|
|
402
|
+
|
|
403
|
+
def unit= unit
|
|
404
|
+
@unit = unit and @amount *= factor || 1
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def normalized_amount
|
|
408
|
+
factor ? Rational(amount, factor) : amount
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
private
|
|
412
|
+
|
|
413
|
+
def factor
|
|
414
|
+
return if instance_of? Unit
|
|
415
|
+
self.class.rules[unit][:factor] if self.class.rules.key? unit
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def rules_for_options options
|
|
419
|
+
rules = self.class.rules.reject { |_, r| r[:factor].nil? }
|
|
420
|
+
|
|
421
|
+
unless options.empty?
|
|
422
|
+
rules.reject! { |_, r|
|
|
423
|
+
options.none? { |k, v| r[k] == v || r[k].nil? && v == false }
|
|
424
|
+
}
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
rules
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def pluralize?
|
|
431
|
+
return false unless self.class.pluralize
|
|
432
|
+
return true unless coerced_amount
|
|
433
|
+
|
|
434
|
+
case abs = coerced_amount.abs
|
|
435
|
+
when Rational then abs <= 0 || abs > 1
|
|
436
|
+
when Numeric then abs != 1
|
|
437
|
+
else false
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def method_missing method_name, *args, &block
|
|
442
|
+
if args.empty? && unit = method_name.to_s.sub!(/^to_/, '')
|
|
443
|
+
if Gorilla.units.key? unit
|
|
444
|
+
return convert_to unit
|
|
445
|
+
elsif Gorilla.const_defined? :CoreExt
|
|
446
|
+
return convert_to 1.send(unit).unit rescue super
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
super
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
end
|