Skip to content

Commit

Permalink
Merge pull request #67 from shivam091/5.14.0
Browse files Browse the repository at this point in the history
5.14.0
  • Loading branch information
shivam091 authored Nov 27, 2023
2 parents d52fd2f + eba1eb0 commit 12e56f5
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [5.14.0](https://github.com/shivam091/unit_measurements/compare/v5.13.0...v5.14.0) - 2023-11-29

### What's new

- Added `.define_numeric_methods` support to define numeric extension methods for units.

----------

## [5.13.0](https://github.com/shivam091/unit_measurements/compare/v5.12.0...v5.13.0) - 2023-11-27

### What's new
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
unit_measurements (5.13.0)
unit_measurements (5.14.0)
activesupport (~> 7.0)

GEM
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,31 @@ Length = UnitMeasurements::Length
Volume = UnitMeasurements::Volume
```

## Extras

### Numeric extension methods

The `.define_numeric_methods` method allows you to instantiate measurements in a
manner similar to how `ActiveSupport::Duration` objects are created in Rails,
providing a familiar syntax and functionality.

To define numeric extension methods for specific units within a unit group, use
the following syntax:

```ruby
UnitMeasurements::Length.define_numeric_methods("metre", "foot", "inch")
```

This will enable the usage of these units as methods to instantiate and use measurements:

```ruby
1.m #=> Instantiate a measurement representing 1 metre.
5.feet #=> Instantiate a measurement representing 5 feet.
10.inches #=> Instantiate a measurement representing 10 inches.
1.foot == 12.inches #=> equality comparison between two measurements.
1.ft + 12.in #=> adds quantity of two measurements.
```

## Contributing

1. Fork it
Expand Down
2 changes: 2 additions & 0 deletions lib/unit_measurements/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ def configure
end

# The following requires load various components of the unit measurements library.
require "unit_measurements/extras/numeric_methods"

require "unit_measurements/configuration"
require "unit_measurements/cache"
require "unit_measurements/unit_group_builder"
Expand Down
81 changes: 81 additions & 0 deletions lib/unit_measurements/extras/numeric_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- encoding: utf-8 -*-
# -*- frozen_string_literal: true -*-
# -*- warn_indent: true -*-

module UnitMeasurements
# This module provides methods to define +Numeric+ extension methods for a list
# of units within a unit group. If units are empty, it defaults to defining
# methods for all units in the unit group.
#
# This module is included in the +Measurement+ class to allow defining numeric
# extension methods for specified units.
#
# @see Measurement
#
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
# @since 5.14.0
module NumericMethods
# @scope class
# Defines +Numeric+ extension methods for specified units within the unit
# group. If units are empty, it defaults to defining methods for all units
# within the unit group.
#
# @param [Array<String|Symbol>] units
# An array of units' names for which numeric methods need to be defined.
# If empty, methods will be defined for all units in the unit group.
#
# @return [Array<Unit>] An array of units for which methods are defined.
#
# @example Define numeric methods for metres, centimetres, and millimetres:
# UnitMeasurements::Length.define_numeric_methods("metres", :cm, :mm)
#
# @example Define numeric methods for all units in the unit group:
# UnitMeasurements::Length.define_numeric_methods
#
# @see #define_numeric_method_for
#
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
# @since 5.14.0
def define_numeric_methods(*units)
unit_group = self
units = units.empty? ? unit_group.units : units

units.inject([]) do |units, unit|
units << define_numeric_method_for(unit, unit_group)
end
end

private

# @private
# @scope class
# This method defines a numeric method for a specific unit within a unit group.
# The method is defined dynamically using +define_method+ and associates the
# unit with the numeric value.
#
# @param [String|Symbol|Unit] unit
# The unit for which the numeric method is defined.
# @param [UnitGroup] unit_group The unit group to which the unit belongs.
#
# @return [Unit] The unit instance for which the method was defined.
#
# @see #define_numeric_methods
#
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
# @since 5.14.0
def define_numeric_method_for(unit, unit_group)
unit = unit.is_a?(Unit) ? unit : unit_group.unit_for!(unit)

unit.names.each do |method_name|
# Check if the name contains alphabetic characters
next unless method_name =~ /^[a-zA-Z]+$/

Numeric.define_method(method_name) do
unit_group.new(self, unit)
end
end

unit
end
end
end
3 changes: 3 additions & 0 deletions lib/unit_measurements/measurement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module UnitMeasurements
# @see Conversion
# @see Formatter
# @see Math
# @see NumericMethods
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
# @since 1.0.0
class Measurement
Expand All @@ -32,6 +33,8 @@ class Measurement
include Formatter
include Math

extend NumericMethods

# Regular expression to match conversion strings.
#
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
Expand Down
2 changes: 1 addition & 1 deletion lib/unit_measurements/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

module UnitMeasurements
# Current stable version.
VERSION = "5.13.0"
VERSION = "5.14.0"
end
33 changes: 33 additions & 0 deletions spec/unit_measurements/extras/numeric_methods_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- encoding: utf-8 -*-
# -*- frozen_string_literal: true -*-
# -*- warn_indent: true -*-

# spec/unit_measurements/extras/numeric_methods_spec.rb

RSpec.describe UnitMeasurements::NumericMethods do
let(:unit_group) { UnitMeasurements::Length }
let(:m) { unit_group.unit_for!(:m) }
let(:cm) { unit_group.unit_for!(:cm) }

context "when units are specified" do
it "defines extension methods for specified units" do
unit_group.define_numeric_methods("m", "cm")

expect(Numeric.method_defined?("m")).to be_truthy
expect(Numeric.method_defined?("cm")).to be_truthy

expect(1.cm).to be_instance_of(unit_group)
end
end

context "when units are specified" do
it "defines extension methods for all units within the unit group" do
unit_group.define_numeric_methods

expect(Numeric.method_defined?("ft")).to be_truthy
expect(Numeric.method_defined?("in")).to be_truthy

expect(1.ft).to be_instance_of(unit_group)
end
end
end

0 comments on commit 12e56f5

Please sign in to comment.