unit_measurements 5.1.0 → 5.2.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/pages.yml +1 -1
- data/.gitignore +1 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +1 -1
- data/README.md +26 -12
- 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/unit_measurements.gemspec +1 -1
- data/units.md +7 -7
- metadata +5 -3
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/.github/workflows/pages.yml
CHANGED
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
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
|
+
|
10
|
+
## [5.1.1](https://github.com/shivam091/unit_measurements/compare/v5.1.0...v5.1.1) - 2023-10-20
|
11
|
+
|
12
|
+
### What's updated
|
13
|
+
|
14
|
+
- Updated readme and documentation.
|
15
|
+
- Updated documentation hosting link to `https://shivam091.github.io/unit_measurements`.
|
16
|
+
|
17
|
+
----------
|
18
|
+
|
1
19
|
## [5.1.0](https://github.com/shivam091/unit_measurements/compare/v5.0.0...v5.1.0) - 2023-10-19
|
2
20
|
|
3
21
|
### What's new
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,11 +24,12 @@ The `unit_measurements` gem is designed to simplify the handling of units for sc
|
|
24
24
|
|
25
25
|
## Features
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
1. Provides easy conversion between units.
|
28
|
+
2. Lightweight and easily extensible to include other units and conversions.
|
29
|
+
3. Built in support for various [unit groups](https://github.com/shivam091/unit_measurements/blob/main/units.md).
|
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
|
@@ -127,7 +132,7 @@ UnitMeasurements::Length.parse("2e+2 km to m")
|
|
127
132
|
#=> 200000.0 m
|
128
133
|
```
|
129
134
|
You can check supported special characters for exponents
|
130
|
-
[here](https://
|
135
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Normalizer.html).
|
131
136
|
|
132
137
|
**Parse complex numbers, source unit, and (or) target unit:**
|
133
138
|
|
@@ -148,7 +153,7 @@ UnitMeasurements::Length.parse("2/3 km to m")
|
|
148
153
|
```
|
149
154
|
|
150
155
|
You can check supported special characters for fractional notations
|
151
|
-
[here](https://
|
156
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Normalizer.html).
|
152
157
|
|
153
158
|
**Parse ratios, source unit, and (or) target unit:**
|
154
159
|
|
@@ -170,7 +175,7 @@ UnitMeasurements::Length.new(100, "m").to("in").format("%.4<quantity>f %<unit>s"
|
|
170
175
|
```
|
171
176
|
|
172
177
|
You can check more about formatting along with their examples
|
173
|
-
[here](https://
|
178
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Formatter.html).
|
174
179
|
|
175
180
|
**Extract the unit and the quantity from measurement:**
|
176
181
|
|
@@ -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.
|
@@ -265,7 +276,7 @@ UnitMeasurements::Length.parse("1 km") != UnitMeasurements::Length.parse("1 m")
|
|
265
276
|
```
|
266
277
|
|
267
278
|
You can check supported comparisons along with their examples
|
268
|
-
[here](https://
|
279
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Comparison.html).
|
269
280
|
|
270
281
|
### Arithmetic
|
271
282
|
|
@@ -282,7 +293,7 @@ UnitMeasurements::Length.new(2, "km") * 2+2i
|
|
282
293
|
```
|
283
294
|
|
284
295
|
You can check supported arithmetic operations along with their examples
|
285
|
-
[here](https://
|
296
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Arithmetic.html).
|
286
297
|
|
287
298
|
### Math
|
288
299
|
|
@@ -294,7 +305,7 @@ UnitMeasurements::Length.new(17.625, "m").round
|
|
294
305
|
```
|
295
306
|
|
296
307
|
You can check supported mathematical functions along with their examples
|
297
|
-
[here](https://
|
308
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Math.html).
|
298
309
|
|
299
310
|
### Conversions
|
300
311
|
|
@@ -307,7 +318,7 @@ UnitMeasurements::Length.new(2.25567, "km").to_i
|
|
307
318
|
```
|
308
319
|
|
309
320
|
You can check more about them along with their examples
|
310
|
-
[here](https://
|
321
|
+
[here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Conversion.html).
|
311
322
|
|
312
323
|
## Units
|
313
324
|
|
@@ -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/unit_measurements.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
23
23
|
|
24
24
|
spec.metadata["homepage_uri"] = spec.homepage
|
25
|
-
spec.metadata["documentation_uri"] = "https://
|
25
|
+
spec.metadata["documentation_uri"] = "https://shivam091.github.io/unit_measurements"
|
26
26
|
spec.metadata["source_code_uri"] = "https://github.com/shivam091/unit_measurements"
|
27
27
|
spec.metadata["changelog_uri"] = "https://github.com/shivam091/unit_measurements/blob/main/CHANGELOG.md"
|
28
28
|
spec.metadata["bug_tracker_uri"] = "https://github.com/shivam091/unit_measurements/issues"
|
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
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- ".github/workflows/pages.yml"
|
98
98
|
- ".gitignore"
|
99
99
|
- ".rspec"
|
100
|
+
- ".yardopts"
|
100
101
|
- CHANGELOG.md
|
101
102
|
- Gemfile
|
102
103
|
- Gemfile.lock
|
@@ -106,6 +107,7 @@ files:
|
|
106
107
|
- lib/unit_measurements.rb
|
107
108
|
- lib/unit_measurements/arithmetic.rb
|
108
109
|
- lib/unit_measurements/base.rb
|
110
|
+
- lib/unit_measurements/cache.rb
|
109
111
|
- lib/unit_measurements/comparison.rb
|
110
112
|
- lib/unit_measurements/conversion.rb
|
111
113
|
- lib/unit_measurements/errors/parse_error.rb
|
@@ -178,7 +180,7 @@ licenses:
|
|
178
180
|
metadata:
|
179
181
|
allowed_push_host: https://rubygems.org
|
180
182
|
homepage_uri: https://github.com/shivam091/unit_measurements
|
181
|
-
documentation_uri: https://
|
183
|
+
documentation_uri: https://shivam091.github.io/unit_measurements
|
182
184
|
source_code_uri: https://github.com/shivam091/unit_measurements
|
183
185
|
changelog_uri: https://github.com/shivam091/unit_measurements/blob/main/CHANGELOG.md
|
184
186
|
bug_tracker_uri: https://github.com/shivam091/unit_measurements/issues
|