unit_measurements 5.1.1 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +16 -2
- data/lib/unit_measurements/base.rb +3 -0
- data/lib/unit_measurements/cache.rb +173 -0
- data/lib/unit_measurements/measurement.rb +103 -17
- data/lib/unit_measurements/unit_group.rb +15 -1
- data/lib/unit_measurements/unit_group_builder.rb +14 -1
- data/lib/unit_measurements/version.rb +1 -1
- data/units.md +7 -7
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30ecc167254df71dd7e6415ea85e4042837d37294041d5fc1791e395711a5774
|
4
|
+
data.tar.gz: c7e5382424fbb305607a312e6fec931e0967c09d402f08ce88343909a7c0a89e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b50e6cf5076ed8a27b16b81246c864cb0b3dcbeba9e91b400d7e377f91bd9497667312f2ff551cb43abc4a3520ee11d31f4926b20bbf40010f0895d19d0c32e7
|
7
|
+
data.tar.gz: 948c1541e6e57613839a88dee8c5f99e583f0137c2bfc3114fa1e9eb758bce608b6f194adbab2f8e85216768127630ec65c90bb4fd685054cbb69000fa0a9a9e
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## [5.2.0](https://github.com/shivam091/unit_measurements/compare/v5.1.1...v5.2.0) - 2023-10-22
|
2
|
+
|
3
|
+
### What's new
|
4
|
+
|
5
|
+
- Added ability to set name of the cache file for the unit group.
|
6
|
+
- Added support for caching conversion factors between units of the unit group.
|
7
|
+
|
8
|
+
----------
|
9
|
+
|
1
10
|
## [5.1.1](https://github.com/shivam091/unit_measurements/compare/v5.1.0...v5.1.1) - 2023-10-20
|
2
11
|
|
3
12
|
### What's updated
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -27,8 +27,9 @@ The `unit_measurements` gem is designed to simplify the handling of units for sc
|
|
27
27
|
1. Provides easy conversion between units.
|
28
28
|
2. Lightweight and easily extensible to include other units and conversions.
|
29
29
|
3. Built in support for various [unit groups](https://github.com/shivam091/unit_measurements/blob/main/units.md).
|
30
|
-
4.
|
31
|
-
5.
|
30
|
+
4. Ability to parse strings representing complex, fractional, mixed fractional, scientific numbers, and ratios.
|
31
|
+
5. Well organized and descriptive documentation published [here](https://shivam091.github.io/unit_measurements).
|
32
|
+
6. Supports caching of conversion factors between different units of the unit group.
|
32
33
|
|
33
34
|
## Disclaimer
|
34
35
|
|
@@ -74,6 +75,8 @@ UnitMeasurements::Length.new(1, "km")
|
|
74
75
|
This gem allows you to convert among units of same unit group. You can convert measurement to other unit using `#convert_to`
|
75
76
|
(aliased as `#to`, `#in`, and `#as`) or `#convert_to!` (aliased as `#to!`, `#in!`, and `#as!`) methods.
|
76
77
|
|
78
|
+
These methods provide `use_cache` parameter which can be used to indicate whether the caching of conversion factors should happen.
|
79
|
+
|
77
80
|
You can use `#convert_to` as:
|
78
81
|
|
79
82
|
```ruby
|
@@ -104,6 +107,8 @@ UnitMeasurements::Length.new(100, "m").convert_to("ft").convert_to!("in")
|
|
104
107
|
|
105
108
|
**Parse string without having to split out the quantity and source unit:**
|
106
109
|
|
110
|
+
This method provides `use_cache` parameter which can be used to indicate whether the caching of conversion factors should happen.
|
111
|
+
|
107
112
|
```ruby
|
108
113
|
UnitMeasurements::Length.parse("1 km")
|
109
114
|
#=> 1.0 km
|
@@ -254,6 +259,12 @@ UnitMeasurements::Length.unit_or_alias?("metre")
|
|
254
259
|
#=> true
|
255
260
|
```
|
256
261
|
|
262
|
+
**Clear cached data for the unit group:**
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
UnitMeasurements::Length.clear_cache
|
266
|
+
```
|
267
|
+
|
257
268
|
### Comparisons
|
258
269
|
|
259
270
|
You have ability to compare the measurements with the same or different units within the same unit group.
|
@@ -413,6 +424,9 @@ UnitMeasurements::Time = UnitMeasurements.build do
|
|
413
424
|
# You can also specify unit value as an array.
|
414
425
|
unit "h", value: [60, "min"], aliases: ["day", "days"]
|
415
426
|
end
|
427
|
+
|
428
|
+
# Sets the name of the cache file (optional).
|
429
|
+
cache "time_cache.json"
|
416
430
|
end
|
417
431
|
```
|
418
432
|
|
@@ -36,6 +36,8 @@ module UnitMeasurements
|
|
36
36
|
# system :imperial do
|
37
37
|
# unit "in", value: "25.4 mm", aliases: ['"', "inch", "inches"]
|
38
38
|
# end
|
39
|
+
#
|
40
|
+
# cache "length.json"
|
39
41
|
# end
|
40
42
|
#
|
41
43
|
# @param block
|
@@ -78,6 +80,7 @@ module UnitMeasurements
|
|
78
80
|
end
|
79
81
|
|
80
82
|
# The following requires load various components of the unit measurements library.
|
83
|
+
require "unit_measurements/cache"
|
81
84
|
require "unit_measurements/unit_group_builder"
|
82
85
|
require "unit_measurements/unit"
|
83
86
|
require "unit_measurements/unit_group"
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
module UnitMeasurements
|
6
|
+
# The +UnitMeasurements::Cache+ class manages caching of conversion factors
|
7
|
+
# between different units within a unit group. It provides methods to retrieve,
|
8
|
+
# set, and clear cached conversion factors.
|
9
|
+
#
|
10
|
+
# Cached conversion factors are stored in JSON file on the file system.
|
11
|
+
#
|
12
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
13
|
+
# @since 5.2.0
|
14
|
+
class Cache
|
15
|
+
# The directory path where cache files are stored.
|
16
|
+
#
|
17
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
18
|
+
# @since 5.2.0
|
19
|
+
CACHE_DIRECTORY = File.expand_path(File.join("..", "..", "cache"), __dir__).freeze
|
20
|
+
|
21
|
+
# Stores cached conversion factors between different units within a unit
|
22
|
+
# group.
|
23
|
+
#
|
24
|
+
# @return [Hash] The cached conversion factors.
|
25
|
+
#
|
26
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
27
|
+
# @since 5.2.0
|
28
|
+
attr_reader :cached_data
|
29
|
+
|
30
|
+
# Initializes a new +Cache+ instance for a specific unit group.
|
31
|
+
#
|
32
|
+
# Initialization first ensures existence of the cache directory. If the cache
|
33
|
+
# directory does not exist, it gets created.
|
34
|
+
#
|
35
|
+
# @param [UnitGroup] unit_group The unit group associated with the cache.
|
36
|
+
#
|
37
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
38
|
+
# @since 5.2.0
|
39
|
+
def initialize(unit_group)
|
40
|
+
ensure_cache_directory_exists
|
41
|
+
@cache_file = build_cache_file_path(unit_group)
|
42
|
+
@cached_data ||= load_cache
|
43
|
+
end
|
44
|
+
|
45
|
+
# Retrieves the conversion factor between source and target units from the
|
46
|
+
# cache.
|
47
|
+
#
|
48
|
+
# @param [String] source_unit The source unit name.
|
49
|
+
# @param [String] target_unit The target unit name.
|
50
|
+
#
|
51
|
+
# @return [Numeric|NilClass]
|
52
|
+
# The conversion factor, or +nil+ if not found in the cache.
|
53
|
+
#
|
54
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
55
|
+
# @since 5.2.0
|
56
|
+
def get(source_unit, target_unit)
|
57
|
+
cached_data.dig(source_unit, target_unit)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Sets the conversion factor between source and target units in the cache.
|
61
|
+
#
|
62
|
+
# @param [String] source_unit The source unit name.
|
63
|
+
# @param [String] target_unit The target unit name.
|
64
|
+
# @param [Numeric] conversion_factor The conversion factor.
|
65
|
+
#
|
66
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
67
|
+
# @since 5.2.0
|
68
|
+
def set(source_unit, target_unit, conversion_factor)
|
69
|
+
cached_data[source_unit] ||= {}
|
70
|
+
cached_data[source_unit][target_unit] = conversion_factor
|
71
|
+
|
72
|
+
store_cache
|
73
|
+
end
|
74
|
+
|
75
|
+
# Clears the entire cache.
|
76
|
+
#
|
77
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
78
|
+
# @since 5.2.0
|
79
|
+
def clear_cache
|
80
|
+
@cached_data = {}
|
81
|
+
store_cache
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# @private
|
87
|
+
# Loads the cache from the cache file.
|
88
|
+
#
|
89
|
+
# @return [Hash] The loaded cache data.
|
90
|
+
#
|
91
|
+
# @raise [Errno::ENOENT] If the cache file does not exist.
|
92
|
+
# @raise [Errno::EACCES]
|
93
|
+
# If the cache file cannot be accessed due to insufficient permissions.
|
94
|
+
# @raise [JSON::ParserError] If there's an error parsing the cache file.
|
95
|
+
#
|
96
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
97
|
+
# @since 5.2.0
|
98
|
+
def load_cache
|
99
|
+
return {} unless File.exist?(@cache_file)
|
100
|
+
|
101
|
+
begin
|
102
|
+
File.open(@cache_file, "r") { |file| JSON.load(file.read) }
|
103
|
+
rescue Errno::ENOENT, Errno::EACCES, JSON::ParserError => e
|
104
|
+
puts "Error loading cache"
|
105
|
+
{}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @private
|
110
|
+
# Stores the current cache data to the cache file. +cached_data+ is stored in
|
111
|
+
# prettier form.
|
112
|
+
#
|
113
|
+
# @raise [Errno::ENOENT] If the cache file does not exist.
|
114
|
+
# @raise [Errno::EACCES]
|
115
|
+
# If the cache file cannot be accessed due to insufficient permissions.
|
116
|
+
# @raise [Errno::ENOSPC]
|
117
|
+
# If there's not enough space to write to the cache file.
|
118
|
+
# @raise [JSON::GeneratorError] If there's an error generating JSON data.
|
119
|
+
#
|
120
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
121
|
+
# @since 5.2.0
|
122
|
+
def store_cache
|
123
|
+
begin
|
124
|
+
File.open(@cache_file, "w") do |file|
|
125
|
+
file.write(JSON.pretty_generate(cached_data))
|
126
|
+
end
|
127
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOSPC, JSON::GeneratorError => e
|
128
|
+
puts "Error saving cache: #{e.message}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @private
|
133
|
+
# Ensures that the cache directory exists. If the cache directory does not
|
134
|
+
# exist, it gets created.
|
135
|
+
#
|
136
|
+
# @raise [Errno::EEXIST] If the cache directory already exists.
|
137
|
+
# @raise [Errno::EACCES]
|
138
|
+
# If the cache directory cannot be accessed due to insufficient permissions.
|
139
|
+
# @raise [Errno::ENOSPC]
|
140
|
+
# If there's not enough space to create the cache directory.
|
141
|
+
#
|
142
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
143
|
+
# @since 5.2.0
|
144
|
+
def ensure_cache_directory_exists
|
145
|
+
begin
|
146
|
+
Dir.mkdir(CACHE_DIRECTORY) unless Dir.exist?(CACHE_DIRECTORY)
|
147
|
+
rescue Errno::EACCES, Errno::ENOSPC => e
|
148
|
+
puts "Error creating cache directory: #{e.message}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# @private
|
153
|
+
# Builds and returns an absolute path of the cache file.
|
154
|
+
#
|
155
|
+
# This method first checks if the cache file name is specified for the unit
|
156
|
+
# group. If yes, it builds absolute path of the cache file using specified
|
157
|
+
# cache file name. If not, it builds file name from of the name of the unit
|
158
|
+
# group. This file name is then used to build absolute path of the cache file.
|
159
|
+
#
|
160
|
+
# @param [UnitGroup] unit_group The unit group associated with the cache.
|
161
|
+
#
|
162
|
+
# @return [String] An absolute path of the cache file.
|
163
|
+
#
|
164
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
165
|
+
# @since 5.2.0
|
166
|
+
def build_cache_file_path(unit_group)
|
167
|
+
cache_file_name = unit_group.cache_file || unit_group.to_s.split("::").last.underscore
|
168
|
+
cache_file_name = File.basename(cache_file_name, ".json") + ".json"
|
169
|
+
|
170
|
+
Pathname.new(File.join(CACHE_DIRECTORY, cache_file_name)).cleanpath
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -120,6 +120,11 @@ module UnitMeasurements
|
|
120
120
|
# Converts the measurement to a +target_unit+ and returns new instance of the
|
121
121
|
# measurement.
|
122
122
|
#
|
123
|
+
# When +use_cache+ value is true, conversion factor between units are checked
|
124
|
+
# in cache file of the unit group. If cached conversion factor is present in
|
125
|
+
# the cache file, it is used for conversion otherwise conversion factor is
|
126
|
+
# stored in the cache before converting the measurement to the +target_unit+.
|
127
|
+
#
|
123
128
|
# @example
|
124
129
|
# UnitMeasurements::Length.new(1, "m").convert_to("cm")
|
125
130
|
# => 100.0 cm
|
@@ -127,9 +132,14 @@ module UnitMeasurements
|
|
127
132
|
# UnitMeasurements::Length.new(1, "cm").convert_to("primitive")
|
128
133
|
# => 0.01 m
|
129
134
|
#
|
135
|
+
# UnitMeasurements::Length.new(1, "m").convert_to("cm", use_cache: true)
|
136
|
+
# => 100.0 cm
|
137
|
+
#
|
130
138
|
# @param [String|Symbol] target_unit
|
131
139
|
# The target unit for conversion. Specifing +primitive+ will convert the
|
132
140
|
# measurement to a primitive unit of the unit group.
|
141
|
+
# @param [TrueClass|FalseClass] use_cache
|
142
|
+
# Indicates whether to use cached conversion factors.
|
133
143
|
#
|
134
144
|
# @return [Measurement]
|
135
145
|
# A new +Measurement+ instance with the converted +quantity+ and
|
@@ -137,16 +147,15 @@ module UnitMeasurements
|
|
137
147
|
#
|
138
148
|
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
139
149
|
# @since 1.0.0
|
140
|
-
def convert_to(target_unit)
|
150
|
+
def convert_to(target_unit, use_cache: false)
|
141
151
|
target_unit = if target_unit.to_s.eql?("primitive")
|
142
152
|
self.class.unit_group.primitive
|
143
153
|
else
|
144
154
|
unit_from_unit_or_name!(target_unit)
|
145
155
|
end
|
146
|
-
|
147
156
|
return self if target_unit == unit
|
148
157
|
|
149
|
-
conversion_factor = (
|
158
|
+
conversion_factor = calculate_conversion_factor(target_unit, use_cache)
|
150
159
|
|
151
160
|
self.class.new((quantity * conversion_factor), target_unit)
|
152
161
|
end
|
@@ -160,7 +169,17 @@ module UnitMeasurements
|
|
160
169
|
# UnitMeasurements::Length.new(1, "m").convert_to!("cm")
|
161
170
|
# => 100.0 cm
|
162
171
|
#
|
163
|
-
#
|
172
|
+
# UnitMeasurements::Length.new(1, "cm").convert_to!("primitive")
|
173
|
+
# => 0.01 m
|
174
|
+
#
|
175
|
+
# UnitMeasurements::Length.new(1, "m").convert_to!("cm", use_cache: true)
|
176
|
+
# => 100.0 cm
|
177
|
+
#
|
178
|
+
# @param [String|Symbol] target_unit
|
179
|
+
# The target unit for conversion. Specifing +primitive+ will convert the
|
180
|
+
# measurement to a primitive unit of the unit group.
|
181
|
+
# @param [TrueClass|FalseClass] use_cache
|
182
|
+
# Indicates whether to use cached conversion factors.
|
164
183
|
#
|
165
184
|
# @return [Measurement]
|
166
185
|
# The current +Measurement+ instance with updated +quantity+ and +unit+.
|
@@ -168,8 +187,8 @@ module UnitMeasurements
|
|
168
187
|
# @see #convert_to
|
169
188
|
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
170
189
|
# @since 1.0.0
|
171
|
-
def convert_to!(target_unit)
|
172
|
-
measurement = convert_to(target_unit)
|
190
|
+
def convert_to!(target_unit, use_cache: false)
|
191
|
+
measurement = convert_to(target_unit, use_cache: use_cache)
|
173
192
|
@quantity, @unit = measurement.quantity, measurement.unit
|
174
193
|
|
175
194
|
self
|
@@ -219,16 +238,20 @@ module UnitMeasurements
|
|
219
238
|
extend Forwardable
|
220
239
|
|
221
240
|
# Methods delegated from the unit group.
|
222
|
-
def_delegators :unit_group, :primitive, :units, :
|
223
|
-
:
|
224
|
-
:unit_or_alias?, :[],
|
241
|
+
def_delegators :unit_group, :primitive, :units, :cache_file, :unit_names,
|
242
|
+
:unit_with_name_and_aliases, :unit_names_with_aliases,
|
243
|
+
:unit_for, :unit_for!, :defined?, :unit_or_alias?, :[],
|
244
|
+
:units_for, :units_for!
|
225
245
|
|
226
246
|
# Parses an input string and returns a +Measurement+ instance depending on
|
227
247
|
# the input string. This method first normalizes the +input+ internally,
|
228
248
|
# using the +Normalizer+ before parsing it using the +Parser+.
|
229
249
|
#
|
250
|
+
# You can separate *source* and *target* units from each other in +input+
|
251
|
+
# using +to+, +in+, or +as+.
|
252
|
+
#
|
230
253
|
# If only the source unit is provided, it returns a new +Measurement+
|
231
|
-
# instance with the quantity in the source unit.If both source and target
|
254
|
+
# instance with the quantity in the source unit. If both source and target
|
232
255
|
# units are provided in the input string, it returns a new +Measurement+
|
233
256
|
# instance with the quantity converted to the target unit.
|
234
257
|
#
|
@@ -237,7 +260,7 @@ module UnitMeasurements
|
|
237
260
|
# => 2.0+3.0i km
|
238
261
|
#
|
239
262
|
# @example Parsing string representing a complex number, source, and target units:
|
240
|
-
# UnitMeasurements::Length.parse("2+3i km
|
263
|
+
# UnitMeasurements::Length.parse("2+3i km in m")
|
241
264
|
# => 2000.0+3000.0i m
|
242
265
|
#
|
243
266
|
# @example Parsing string representing a rational or mixed rational number and source unit:
|
@@ -260,10 +283,10 @@ module UnitMeasurements
|
|
260
283
|
# UnitMeasurements::Length.parse("2/3 km to m")
|
261
284
|
# => 666.666666666667 m
|
262
285
|
#
|
263
|
-
# UnitMeasurements::Length.parse("2 ½ km
|
286
|
+
# UnitMeasurements::Length.parse("2 ½ km in m")
|
264
287
|
# => 2500.0 m
|
265
288
|
#
|
266
|
-
# UnitMeasurements::Length.parse("2 1/2 km
|
289
|
+
# UnitMeasurements::Length.parse("2 1/2 km as m")
|
267
290
|
# => 2500.0 m
|
268
291
|
#
|
269
292
|
# @example Parsing string representing a scientific number and source unit:
|
@@ -281,7 +304,7 @@ module UnitMeasurements
|
|
281
304
|
# UnitMeasurements::Length.parse("2e+2 km to m")
|
282
305
|
# => 200000.0 m
|
283
306
|
#
|
284
|
-
# UnitMeasurements::Length.parse("2e⁻² km
|
307
|
+
# UnitMeasurements::Length.parse("2e⁻² km as m")
|
285
308
|
# => 20.0 m
|
286
309
|
#
|
287
310
|
# @example Parsing string representing a ratio and source unit:
|
@@ -289,10 +312,12 @@ module UnitMeasurements
|
|
289
312
|
# => 0.5 km
|
290
313
|
#
|
291
314
|
# @example Parsing string representing a ratio, source, and target units:
|
292
|
-
# UnitMeasurements::Length.parse("1:2 km
|
315
|
+
# UnitMeasurements::Length.parse("1:2 km in m")
|
293
316
|
# => 500.0 m
|
294
317
|
#
|
295
318
|
# @param [String] input The input string to be parsed.
|
319
|
+
# @param [TrueClass|FalseClass] use_cache
|
320
|
+
# Indicates whether to use cached conversion factors.
|
296
321
|
#
|
297
322
|
# @return [Measurement] The +Measurement+ instance.
|
298
323
|
#
|
@@ -303,11 +328,42 @@ module UnitMeasurements
|
|
303
328
|
# @see #convert_to
|
304
329
|
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
305
330
|
# @since 1.0.0
|
306
|
-
def parse(input)
|
331
|
+
def parse(input, use_cache: false)
|
307
332
|
input = Normalizer.normalize(input)
|
308
333
|
source, target = input.match(CONVERSION_STRING_REGEXP)&.captures
|
309
334
|
|
310
|
-
target ? _parse(source).convert_to(target) : _parse(source)
|
335
|
+
target ? _parse(source).convert_to(target, use_cache: use_cache) : _parse(source)
|
336
|
+
end
|
337
|
+
|
338
|
+
# Returns the +Cache+ instance for the unit group to store and retrieve
|
339
|
+
# conversion factors.
|
340
|
+
#
|
341
|
+
# @return [Cache] The +Cache+ instance.
|
342
|
+
#
|
343
|
+
# @example
|
344
|
+
# UnitMeasurements::Length.cached
|
345
|
+
# => #<UnitMeasurements::Cache:0x00007fe407249750>
|
346
|
+
#
|
347
|
+
# @see Cache
|
348
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
349
|
+
# @since 5.2.0
|
350
|
+
def cached
|
351
|
+
@cached ||= Cache.new(self)
|
352
|
+
end
|
353
|
+
|
354
|
+
# Clears the cached conversion factors of the unit group.
|
355
|
+
#
|
356
|
+
# @return [void]
|
357
|
+
#
|
358
|
+
# @example
|
359
|
+
# UnitMeasurements::Length.clear_cache
|
360
|
+
#
|
361
|
+
# @see Cache#clear_cache
|
362
|
+
#
|
363
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
364
|
+
# @since 5.2.0
|
365
|
+
def clear_cache
|
366
|
+
cached.clear_cache
|
311
367
|
end
|
312
368
|
|
313
369
|
private
|
@@ -384,5 +440,35 @@ module UnitMeasurements
|
|
384
440
|
def unit_from_unit_or_name!(value)
|
385
441
|
value.is_a?(Unit) ? value : self.class.send(:unit_group).unit_for!(value)
|
386
442
|
end
|
443
|
+
|
444
|
+
# Calculates the conversion factor between the current unit and the target
|
445
|
+
# unit.
|
446
|
+
#
|
447
|
+
# If caching is enabled and a cached factor is available, it will be used.
|
448
|
+
# Otherwise, the conversion factor will be computed and, if caching is
|
449
|
+
# enabled, stored in the cache.
|
450
|
+
#
|
451
|
+
# @param [Unit] target_unit The target unit for conversion.
|
452
|
+
# @param [TrueClass|FalseClass] use_cache
|
453
|
+
# Indicates whether caching should be used.
|
454
|
+
#
|
455
|
+
# @return [Numeric] The conversion factor.
|
456
|
+
#
|
457
|
+
# @see Unit
|
458
|
+
# @see #convert_to
|
459
|
+
#
|
460
|
+
# @note If caching is enabled, the calculated conversion factor will be stored in the cache.
|
461
|
+
#
|
462
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
463
|
+
# @since 5.2.0
|
464
|
+
def calculate_conversion_factor(target_unit, use_cache)
|
465
|
+
if use_cache && (cached_factor = self.class.cached.get(unit.name, target_unit.name))
|
466
|
+
cached_factor
|
467
|
+
else
|
468
|
+
factor = unit.conversion_factor / target_unit.conversion_factor
|
469
|
+
self.class.cached.set(unit.name, target_unit.name, factor) if use_cache
|
470
|
+
factor
|
471
|
+
end
|
472
|
+
end
|
387
473
|
end
|
388
474
|
end
|
@@ -36,16 +36,30 @@ module UnitMeasurements
|
|
36
36
|
# @since 1.0.0
|
37
37
|
attr_reader :units
|
38
38
|
|
39
|
+
# The name of the cache file.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# UnitMeasurements::Length.cache_file
|
43
|
+
# => "length.json"
|
44
|
+
#
|
45
|
+
# @return [String] The name of the cache file.
|
46
|
+
#
|
47
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
48
|
+
# @since 5.2.0
|
49
|
+
attr_reader :cache_file
|
50
|
+
|
39
51
|
# Initializes a new +UnitGroup+ instance.
|
40
52
|
#
|
41
53
|
# @param [String|Symbol, optional] primitive The name of the primitive unit.
|
42
54
|
# @param [Array<Unit>] units An array of +Unit+ instances.
|
55
|
+
# @param [String] cache_file The name of the cache file.
|
43
56
|
#
|
44
57
|
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
45
58
|
# @since 1.0.0
|
46
|
-
def initialize(primitive, units)
|
59
|
+
def initialize(primitive, units, cache_file)
|
47
60
|
@units = units.map { |unit| unit.with(unit_group: self) }
|
48
61
|
@primitive = unit_for!(primitive) if primitive
|
62
|
+
@cache_file = cache_file
|
49
63
|
end
|
50
64
|
|
51
65
|
# Returns the unit instance for a given unit name. It returns +nil+ if unit
|
@@ -82,7 +82,7 @@ module UnitMeasurements
|
|
82
82
|
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
83
83
|
# @since 1.0.0
|
84
84
|
def build
|
85
|
-
UnitGroup.new(@primitive, @units)
|
85
|
+
UnitGroup.new(@primitive, @units, @cache_file)
|
86
86
|
end
|
87
87
|
|
88
88
|
# Defines the +unit system+ within the unit group and evaluates the provided
|
@@ -130,6 +130,19 @@ module UnitMeasurements
|
|
130
130
|
@primitive = primitive
|
131
131
|
end
|
132
132
|
|
133
|
+
# Sets the name of the cache file for the unit group.
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# cache "conversion_cache.json"
|
137
|
+
#
|
138
|
+
# @param [String] cache_file The name of the cache file.
|
139
|
+
#
|
140
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
141
|
+
# @since 5.2.0
|
142
|
+
def cache(cache_file)
|
143
|
+
@cache_file = cache_file
|
144
|
+
end
|
145
|
+
|
133
146
|
private
|
134
147
|
|
135
148
|
# @private
|
data/units.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# Bundled unit groups and units
|
2
2
|
|
3
|
-
As there are lots of units bundled with `unit_measurements`, we recommend you to
|
4
|
-
bundled units before converting your measurements.
|
3
|
+
As there are lots of units bundled with `unit_measurements`, we recommend you to
|
4
|
+
check below list of bundled units before converting your measurements.
|
5
5
|
|
6
6
|
**Notes:**
|
7
|
-
1. Unit names suffixed with `*` support
|
8
|
-
2. Unit names suffixed with `**` support
|
9
|
-
|
7
|
+
1. Unit names suffixed with `*` support [Decimal SI prefixes](README.md#decimal-si-prefixes).
|
8
|
+
2. Unit names suffixed with `**` support [Binary SI prefixes](README.md#binary-si-prefixes)
|
9
|
+
in addition to [Decimal SI prefixes](README.md#decimal-si-prefixes).
|
10
10
|
3. Primitive unit of the unit group is in _emphasised typeface_.
|
11
11
|
|
12
12
|
## 1. Length/Distance
|
@@ -125,7 +125,7 @@ These units are defined in `UnitMeasurements::Area`.
|
|
125
125
|
| 12 | fur² | fur^2, sq fur, square furlong, square furlongs |
|
126
126
|
| 13 | rod² | rod^2, sq rod, square rod, square rods |
|
127
127
|
|
128
|
-
## 9. Volume
|
128
|
+
## 9. Volume & Capacity
|
129
129
|
|
130
130
|
These units are defined in `UnitMeasurements::Volume`.
|
131
131
|
|
@@ -328,7 +328,7 @@ These units are defined in `UnitMeasurements::ElectricalElastance`.
|
|
328
328
|
| _1_ | _D*_ | _F⁻¹, daraf, darafs, reciprocal farad, reciprocal farads_ |
|
329
329
|
| 2 | V/C | V·C⁻¹, volt/coulomb, volts/coulomb, volt per coulomb, volts per coulomb |
|
330
330
|
|
331
|
-
## 24. Electrical resistance
|
331
|
+
## 24. Electrical resistance/Impedance
|
332
332
|
|
333
333
|
These units are defined in `UnitMeasurements::ElectricalResistance`.
|
334
334
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unit_measurements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harshal LADHE
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/unit_measurements.rb
|
108
108
|
- lib/unit_measurements/arithmetic.rb
|
109
109
|
- lib/unit_measurements/base.rb
|
110
|
+
- lib/unit_measurements/cache.rb
|
110
111
|
- lib/unit_measurements/comparison.rb
|
111
112
|
- lib/unit_measurements/conversion.rb
|
112
113
|
- lib/unit_measurements/errors/parse_error.rb
|