physical 0.4.7 → 0.4.9
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/CHANGELOG.md +22 -1
- data/lib/physical/cuboid.rb +2 -21
- data/lib/physical/location.rb +7 -2
- data/lib/physical/package.rb +14 -9
- data/lib/physical/property_readers.rb +28 -0
- data/lib/physical/shipment.rb +3 -1
- data/lib/physical/spec_support/factories/location_factory.rb +1 -0
- data/lib/physical/spec_support/factories/shipment_factory.rb +1 -0
- data/lib/physical/spec_support/shared_examples/a_cuboid.rb +197 -0
- data/lib/physical/spec_support/shared_examples/has_property_readers.rb +87 -0
- data/lib/physical/spec_support/shared_examples.rb +2 -43
- data/lib/physical/version.rb +1 -1
- data/lib/physical.rb +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8198a4417d9f1dd923a4bfee9bf8695ecb1c270853182a92835e64c1b9f4e10c
|
4
|
+
data.tar.gz: 8a007792624c95421bce9a09abb978de1142b8a2bfbfe6cef049c860ca101416
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b39b9310b28cd5bd9cfe3ea0511f6c615f3c130060693296e6aa01b18d3c893c9cd1704954133e9655c6a47fbe66f636eabc95c4a012f1e34ae4a0e634f6c0b3
|
7
|
+
data.tar.gz: 4881137e7cd922d5a9e56bcaec2fd5701b1e21f3e4ed53528585c14a2c24e0f2b90d93b2b36c7327160dae03cdc9c3e0f3a6171abb898d17843de862bf1f02a1
|
data/CHANGELOG.md
CHANGED
@@ -6,12 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## Unreleased
|
8
8
|
|
9
|
+
## [0.4.9] - 2023-08-02
|
10
|
+
|
11
|
+
### Added
|
12
|
+
- Extract cuboid property handling into mixin [#25]
|
13
|
+
- Add properties to `Physical::Location` [#26]
|
14
|
+
- Add pallets to `Physical::Shipment` [#29]
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- Faster package weight and volume calculations [#23]
|
18
|
+
|
19
|
+
## [0.4.8] - 2023-03-21
|
20
|
+
|
21
|
+
### Added
|
22
|
+
- Add `#items_value` to `Physical::Package` [#21]
|
23
|
+
|
9
24
|
## [0.4.7] - 2022-12-14
|
10
25
|
|
11
26
|
### Changed
|
12
|
-
- Relax Dry::Types dependency to "~> 1.0"
|
27
|
+
- Relax Dry::Types dependency to "~> 1.0" [#20]
|
13
28
|
|
14
29
|
## [0.4.5] - 2022-09-28
|
30
|
+
|
15
31
|
### Added
|
16
32
|
- Add `Physical::Pallet` class [#12]
|
17
33
|
- Convenience methods for weight, volume, and fill [#15]
|
@@ -24,22 +40,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
24
40
|
- Ruby 3 support [#18]
|
25
41
|
|
26
42
|
## [0.4.4] - 2019-10-29
|
43
|
+
|
27
44
|
### Added
|
28
45
|
- Add `#sku`, `#cost` and `#description` to `Physical::Item`
|
29
46
|
|
30
47
|
## [0.4.3] - 2019-10-14
|
48
|
+
|
31
49
|
### Added
|
32
50
|
- Add `#latitude` and `#longitude` to `Physical::Location`
|
33
51
|
|
34
52
|
## [0.4.2] - 2019-09-04
|
53
|
+
|
35
54
|
### Changed
|
36
55
|
- Relax `Measured` Gem dependency
|
37
56
|
|
38
57
|
## [0.4.1] - 2019-07-15
|
58
|
+
|
39
59
|
### Added
|
40
60
|
- Add `max_weight` to `Physical::Package`
|
41
61
|
|
42
62
|
## [0.4.0] - 2019-07-10
|
63
|
+
|
43
64
|
### Added
|
44
65
|
- `Measured::Density` Type and density calculations [@tvdeyen](https://github.com/mamhoff/physical/pull/19)
|
45
66
|
- Use `Measured::Density` Type when initializing `Physical::Package#void_fill_density` [@mamhoff](https://github.com/mamhoff/physical/pull/22)
|
data/lib/physical/cuboid.rb
CHANGED
@@ -4,6 +4,8 @@ require 'measured'
|
|
4
4
|
|
5
5
|
module Physical
|
6
6
|
class Cuboid
|
7
|
+
include PropertyReaders
|
8
|
+
|
7
9
|
attr_reader :dimensions, :length, :width, :height, :weight, :id, :properties
|
8
10
|
|
9
11
|
def initialize(id: nil, dimensions: [], weight: Measured::Weight(0, :g), properties: {})
|
@@ -33,27 +35,6 @@ module Physical
|
|
33
35
|
|
34
36
|
private
|
35
37
|
|
36
|
-
NORMALIZED_METHOD_REGEX = /(\w+)\??$/.freeze
|
37
|
-
|
38
|
-
def method_missing(method)
|
39
|
-
symbolized_properties = properties.symbolize_keys
|
40
|
-
method_name = normalize_method_name(method)
|
41
|
-
if symbolized_properties.key?(method_name)
|
42
|
-
symbolized_properties[method_name]
|
43
|
-
else
|
44
|
-
super
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def respond_to_missing?(method, *args)
|
49
|
-
method_name = normalize_method_name(method)
|
50
|
-
properties.symbolize_keys.key?(method_name) || super
|
51
|
-
end
|
52
|
-
|
53
|
-
def normalize_method_name(method)
|
54
|
-
method.to_s.sub(NORMALIZED_METHOD_REGEX, '\1').to_sym
|
55
|
-
end
|
56
|
-
|
57
38
|
def fill_dimensions(dimensions)
|
58
39
|
dimensions.fill(dimensions.length..2) do |index|
|
59
40
|
@dimensions[index] || Measured::Length(self.class::DEFAULT_LENGTH, :cm)
|
data/lib/physical/location.rb
CHANGED
@@ -4,6 +4,8 @@ require 'carmen'
|
|
4
4
|
|
5
5
|
module Physical
|
6
6
|
class Location
|
7
|
+
include PropertyReaders
|
8
|
+
|
7
9
|
ADDRESS_TYPES = %w(residential commercial po_box).freeze
|
8
10
|
|
9
11
|
attr_reader :country,
|
@@ -20,7 +22,8 @@ module Physical
|
|
20
22
|
:address_type,
|
21
23
|
:company_name,
|
22
24
|
:latitude,
|
23
|
-
:longitude
|
25
|
+
:longitude,
|
26
|
+
:properties
|
24
27
|
|
25
28
|
def initialize(
|
26
29
|
name: nil,
|
@@ -37,7 +40,8 @@ module Physical
|
|
37
40
|
email: nil,
|
38
41
|
address_type: nil,
|
39
42
|
latitude: nil,
|
40
|
-
longitude: nil
|
43
|
+
longitude: nil,
|
44
|
+
properties: {}
|
41
45
|
)
|
42
46
|
|
43
47
|
@country = if country.is_a?(Carmen::Country)
|
@@ -65,6 +69,7 @@ module Physical
|
|
65
69
|
@address_type = address_type
|
66
70
|
@latitude = latitude
|
67
71
|
@longitude = longitude
|
72
|
+
@properties = properties
|
68
73
|
end
|
69
74
|
|
70
75
|
def residential?
|
data/lib/physical/package.rb
CHANGED
@@ -3,24 +3,31 @@
|
|
3
3
|
module Physical
|
4
4
|
class Package
|
5
5
|
extend Forwardable
|
6
|
-
attr_reader :container, :items, :void_fill_density, :
|
6
|
+
attr_reader :id, :container, :items, :void_fill_density, :items_weight, :used_volume
|
7
7
|
|
8
8
|
def initialize(id: nil, container: nil, items: [], void_fill_density: Measured::Density(0, :g_ml), dimensions: nil, weight: nil, properties: {})
|
9
9
|
@id = id || SecureRandom.uuid
|
10
10
|
@void_fill_density = Types::Density[void_fill_density]
|
11
11
|
@container = container || Physical::Box.new(dimensions: dimensions || [], weight: weight || Measured::Weight(0, :g), properties: properties)
|
12
|
+
|
12
13
|
@items = Set[*items]
|
14
|
+
@items_weight = @items.map(&:weight).reduce(Measured::Weight(0, :g), &:+)
|
15
|
+
@used_volume = @items.map(&:volume).reduce(Measured::Volume(0, :ml), &:+)
|
13
16
|
end
|
14
17
|
|
15
18
|
delegate [:dimensions, :width, :length, :height, :properties, :volume] => :container
|
16
19
|
|
17
20
|
def <<(other)
|
18
21
|
@items.add(other)
|
22
|
+
@items_weight += other.weight
|
23
|
+
@used_volume += other.volume
|
19
24
|
end
|
20
25
|
alias_method :add, :<<
|
21
26
|
|
22
27
|
def >>(other)
|
23
28
|
@items.delete(other)
|
29
|
+
@items_weight -= other.weight
|
30
|
+
@used_volume -= other.volume
|
24
31
|
end
|
25
32
|
alias_method :delete, :>>
|
26
33
|
|
@@ -28,9 +35,12 @@ module Physical
|
|
28
35
|
container.weight + items_weight + void_fill_weight
|
29
36
|
end
|
30
37
|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
38
|
+
# Cost is optional. We will only return an aggregate if all items
|
39
|
+
# have cost defined. Otherwise we will return nil.
|
40
|
+
# @return Money
|
41
|
+
def items_value
|
42
|
+
items_cost = items.map(&:cost)
|
43
|
+
items_cost.reduce(&:+) if items_cost.compact.size == items_cost.size
|
34
44
|
end
|
35
45
|
|
36
46
|
def void_fill_weight
|
@@ -39,11 +49,6 @@ module Physical
|
|
39
49
|
Measured::Weight(void_fill_density.convert_to(:g_ml).value * remaining_volume.convert_to(:ml).value, :g)
|
40
50
|
end
|
41
51
|
|
42
|
-
# @return [Measured::Volume]
|
43
|
-
def used_volume
|
44
|
-
items.map(&:volume).reduce(Measured::Volume(0, :ml), &:+)
|
45
|
-
end
|
46
|
-
|
47
52
|
def remaining_volume
|
48
53
|
container.inner_volume - used_volume
|
49
54
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Physical
|
4
|
+
module PropertyReaders
|
5
|
+
private
|
6
|
+
|
7
|
+
NORMALIZED_METHOD_REGEX = /(\w+)\??$/.freeze
|
8
|
+
|
9
|
+
def method_missing(method)
|
10
|
+
symbolized_properties = properties.symbolize_keys
|
11
|
+
method_name = normalize_method_name(method)
|
12
|
+
if symbolized_properties.key?(method_name)
|
13
|
+
symbolized_properties[method_name]
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to_missing?(method, *args)
|
20
|
+
method_name = normalize_method_name(method)
|
21
|
+
properties.symbolize_keys.key?(method_name) || super
|
22
|
+
end
|
23
|
+
|
24
|
+
def normalize_method_name(method)
|
25
|
+
method.to_s.sub(NORMALIZED_METHOD_REGEX, '\1').to_sym
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/physical/shipment.rb
CHANGED
@@ -6,14 +6,16 @@ module Physical
|
|
6
6
|
:origin,
|
7
7
|
:destination,
|
8
8
|
:service_code,
|
9
|
+
:pallets,
|
9
10
|
:packages,
|
10
11
|
:options
|
11
12
|
|
12
|
-
def initialize(id: nil, origin: nil, destination: nil, service_code: nil, packages: [], options: {})
|
13
|
+
def initialize(id: nil, origin: nil, destination: nil, service_code: nil, pallets: [], packages: [], options: {})
|
13
14
|
@id = id || SecureRandom.uuid
|
14
15
|
@origin = origin
|
15
16
|
@destination = destination
|
16
17
|
@service_code = service_code
|
18
|
+
@pallets = pallets
|
17
19
|
@packages = packages
|
18
20
|
@options = options
|
19
21
|
end
|
@@ -14,6 +14,7 @@ FactoryBot.define do
|
|
14
14
|
city { 'Herndon' }
|
15
15
|
sequence(:zip, 10_001, &:to_s)
|
16
16
|
phone { '555-555-0199' }
|
17
|
+
email { 'jane@company.com' }
|
17
18
|
region { country.subregions.coded(region_code) }
|
18
19
|
country { Carmen::Country.coded(country_code) }
|
19
20
|
initialize_with { new(**attributes) }
|
@@ -4,6 +4,7 @@ FactoryBot.define do
|
|
4
4
|
factory :physical_shipment, class: "Physical::Shipment" do
|
5
5
|
origin { FactoryBot.build(:physical_location) }
|
6
6
|
destination { FactoryBot.build(:physical_location) }
|
7
|
+
pallets { build_list(:physical_pallet, 1) }
|
7
8
|
packages { build_list(:physical_package, 2) }
|
8
9
|
service_code { "usps_priority_mail" }
|
9
10
|
initialize_with { new(**attributes) }
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples "a cuboid" do
|
4
|
+
subject(:cuboid) { described_class.new(**args) }
|
5
|
+
|
6
|
+
it_behaves_like "has property readers"
|
7
|
+
|
8
|
+
let(:args) do
|
9
|
+
{
|
10
|
+
dimensions: [
|
11
|
+
Measured::Length.new(1.1, :cm),
|
12
|
+
Measured::Length.new(3.3, :cm),
|
13
|
+
Measured::Length.new(2.2, :cm)
|
14
|
+
]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
it { is_expected.to be_a(Physical::Cuboid) }
|
19
|
+
it { is_expected.to respond_to(:id) }
|
20
|
+
|
21
|
+
describe "#dimensions" do
|
22
|
+
subject(:dimensions) { cuboid.dimensions }
|
23
|
+
|
24
|
+
it "has dimensions as Measured::Length objects with rational values" do
|
25
|
+
expect(dimensions).to eq(
|
26
|
+
[
|
27
|
+
Measured::Length.new(1.1, :cm),
|
28
|
+
Measured::Length.new(3.3, :cm),
|
29
|
+
Measured::Length.new(2.2, :cm)
|
30
|
+
]
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when given a one-element dimensions array" do
|
35
|
+
let(:args) do
|
36
|
+
{
|
37
|
+
dimensions: [Measured::Length(2, :cm)]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "the other dimensions are filled up with default length" do
|
42
|
+
expect(dimensions).to eq(
|
43
|
+
[
|
44
|
+
Measured::Length.new(2, :cm),
|
45
|
+
Measured::Length.new(default_length, :cm),
|
46
|
+
Measured::Length.new(default_length, :cm)
|
47
|
+
]
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when given a two-element dimensions array" do
|
53
|
+
let(:args) do
|
54
|
+
{
|
55
|
+
dimensions: [1, 2].map { |d| Measured::Length(d, :cm) }
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
it "the last dimension is filled up with default length" do
|
60
|
+
expect(dimensions).to eq(
|
61
|
+
[
|
62
|
+
Measured::Length.new(1, :cm),
|
63
|
+
Measured::Length.new(2, :cm),
|
64
|
+
Measured::Length.new(default_length, :cm)
|
65
|
+
]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when given no arguments" do
|
71
|
+
let(:args) { {} }
|
72
|
+
|
73
|
+
it "assumes cm as the dimension_unit and the default length as value" do
|
74
|
+
expect(dimensions).to eq(
|
75
|
+
[
|
76
|
+
Measured::Length.new(default_length, :cm),
|
77
|
+
Measured::Length.new(default_length, :cm),
|
78
|
+
Measured::Length.new(default_length, :cm)
|
79
|
+
]
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "dimension methods" do
|
86
|
+
it "has getter methods for each dimension as Measured::Length object" do
|
87
|
+
expect(cuboid.length).to eq(Measured::Length.new(1.1, :cm))
|
88
|
+
expect(cuboid.width).to eq(Measured::Length.new(3.3, :cm))
|
89
|
+
expect(cuboid.height).to eq(Measured::Length.new(2.2, :cm))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#weight" do
|
94
|
+
subject(:weight) { cuboid.weight }
|
95
|
+
|
96
|
+
context "with no weight given" do
|
97
|
+
let(:args) { {} }
|
98
|
+
it { is_expected.to eq(Measured::Weight(0, :g)) }
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with a weight" do
|
102
|
+
let(:args) { { weight: Measured::Weight(1, :lb) } }
|
103
|
+
it { is_expected.to eq(Measured::Weight(453.59237, :g)) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#volume" do
|
108
|
+
subject(:volume) { cuboid.volume }
|
109
|
+
|
110
|
+
context "if all three dimensions are given" do
|
111
|
+
let(:args) do
|
112
|
+
{
|
113
|
+
dimensions: [1.1, 2.1, 3.2].map { |d| Measured::Length(d, :cm) }
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
it { is_expected.to eq(Measured::Volume(7.392, :ml)) }
|
118
|
+
end
|
119
|
+
|
120
|
+
context "if a dimension is missing" do
|
121
|
+
let(:args) do
|
122
|
+
{
|
123
|
+
dimensions: [1.1, 2.1].map { |d| Measured::Length(d, :cm) }
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
it { is_expected.to eq(Measured::Volume(default_length, :ml)) }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#density" do
|
132
|
+
subject(:density) { cuboid.density.value.to_f }
|
133
|
+
|
134
|
+
let(:args) do
|
135
|
+
{
|
136
|
+
dimensions: dimensions,
|
137
|
+
weight: weight
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
context "if volume is larger than 0" do
|
142
|
+
let(:dimensions) do
|
143
|
+
[1.1, 2.1, 3.2].map { |d| Measured::Length(d, :in) }
|
144
|
+
end
|
145
|
+
|
146
|
+
context "if weight is 1" do
|
147
|
+
let(:weight) { Measured::Weight(1, :pound) }
|
148
|
+
|
149
|
+
it "returns the density in gramms per cubiq centimeter (ml)" do
|
150
|
+
is_expected.to eq(3.7445758536530196)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "if weight is 0" do
|
155
|
+
let(:weight) { Measured::Weight(0, :pound) }
|
156
|
+
|
157
|
+
it { is_expected.to eq(0.0) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "if volume is 0" do
|
162
|
+
let(:dimensions) do
|
163
|
+
[1.1, 2.1].map { |d| Measured::Length(d, :in) }
|
164
|
+
end
|
165
|
+
|
166
|
+
let(:weight) { Measured::Weight(1, :pound) }
|
167
|
+
let(:expected_volume) { default_length.zero? ? BigDecimal::INFINITY : 0 }
|
168
|
+
|
169
|
+
it { is_expected.to eq(expected_volume) }
|
170
|
+
end
|
171
|
+
|
172
|
+
context "if volume is infinite" do
|
173
|
+
let(:dimensions) do
|
174
|
+
[1.1, 2.1].map { |d| Measured::Length(d, :in) }
|
175
|
+
end
|
176
|
+
|
177
|
+
let(:weight) { Measured::Weight(1, :pound) }
|
178
|
+
let(:expected_volume) { default_length.zero? ? BigDecimal::INFINITY : 0 }
|
179
|
+
|
180
|
+
it { is_expected.to eq(expected_volume) }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#==" do
|
185
|
+
let(:args) { Hash[id: 123] }
|
186
|
+
let(:other_cuboid) { described_class.new(**args) }
|
187
|
+
let(:non_cuboid) { double(id: 123) }
|
188
|
+
|
189
|
+
it "compares cuboids" do
|
190
|
+
aggregate_failures do
|
191
|
+
expect(cuboid == other_cuboid).to be(true)
|
192
|
+
expect(cuboid == non_cuboid).to be(false)
|
193
|
+
expect(cuboid.nil?).to be(false)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'has property readers' do
|
4
|
+
subject(:instance) { described_class.new(**args) }
|
5
|
+
|
6
|
+
describe "#properties" do
|
7
|
+
subject(:properties) { instance.properties }
|
8
|
+
|
9
|
+
let(:args) do
|
10
|
+
{
|
11
|
+
properties: { flammable: true }
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it { is_expected.to eq({ flammable: true }) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "properties methods" do
|
19
|
+
context "if method is a property" do
|
20
|
+
let(:args) do
|
21
|
+
{
|
22
|
+
properties: { already_packaged: true }
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns its value" do
|
27
|
+
expect(instance.already_packaged).to be(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it { is_expected.to respond_to(:already_packaged?) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "if method is a string property" do
|
34
|
+
let(:args) do
|
35
|
+
{
|
36
|
+
properties: { "already_packaged" => true }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns its value" do
|
41
|
+
expect(instance.already_packaged).to be(true)
|
42
|
+
end
|
43
|
+
|
44
|
+
it { is_expected.to respond_to(:already_packaged?) }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "if method is a boolean property" do
|
48
|
+
let(:args) do
|
49
|
+
{
|
50
|
+
properties: { already_packaged: true }
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "it is also accessible by its predicate method" do
|
55
|
+
expect(instance.already_packaged?).to be(true)
|
56
|
+
end
|
57
|
+
|
58
|
+
it { is_expected.to respond_to(:already_packaged?) }
|
59
|
+
|
60
|
+
context "with a falsey value" do
|
61
|
+
let(:args) do
|
62
|
+
{
|
63
|
+
properties: { already_packaged: false }
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns its value" do
|
68
|
+
expect(instance.already_packaged).to be(false)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "if method is not a property" do
|
74
|
+
let(:args) do
|
75
|
+
{
|
76
|
+
properties: {}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
it "raises method missing" do
|
81
|
+
expect { instance.already_packaged? }.to raise_error(NoMethodError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it { is_expected.not_to respond_to(:already_packaged?) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -1,45 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
{
|
6
|
-
dimensions: [
|
7
|
-
Measured::Length.new(1.1, :cm),
|
8
|
-
Measured::Length.new(3.3, :cm),
|
9
|
-
Measured::Length.new(2.2, :cm)
|
10
|
-
]
|
11
|
-
}
|
12
|
-
end
|
13
|
-
|
14
|
-
it { is_expected.to be_a(Physical::Cuboid) }
|
15
|
-
|
16
|
-
it "has dimensions as Measured::Length objects with rational values" do
|
17
|
-
expect(subject.dimensions).to eq(
|
18
|
-
[
|
19
|
-
Measured::Length.new(1.1, :cm),
|
20
|
-
Measured::Length.new(3.3, :cm),
|
21
|
-
Measured::Length.new(2.2, :cm)
|
22
|
-
]
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "has getter methods for each dimension as Measured::Length object" do
|
27
|
-
expect(subject.length).to eq(Measured::Length.new(1.1, :cm))
|
28
|
-
expect(subject.width).to eq(Measured::Length.new(3.3, :cm))
|
29
|
-
expect(subject.height).to eq(Measured::Length.new(2.2, :cm))
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "#==" do
|
33
|
-
let(:args) { Hash[id: 123] }
|
34
|
-
let(:other_cuboid) { described_class.new(**args) }
|
35
|
-
let(:non_cuboid) { double(id: 123) }
|
36
|
-
|
37
|
-
it "compares cuboids" do
|
38
|
-
aggregate_failures do
|
39
|
-
expect(subject == other_cuboid).to be(true)
|
40
|
-
expect(subject == non_cuboid).to be(false)
|
41
|
-
expect(subject.nil?).to be(false)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
3
|
+
require "physical/spec_support/shared_examples/a_cuboid"
|
4
|
+
require "physical/spec_support/shared_examples/has_property_readers"
|
data/lib/physical/version.rb
CHANGED
data/lib/physical.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: physical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Meyerhoff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: carmen
|
@@ -199,6 +199,7 @@ files:
|
|
199
199
|
- lib/physical/location.rb
|
200
200
|
- lib/physical/package.rb
|
201
201
|
- lib/physical/pallet.rb
|
202
|
+
- lib/physical/property_readers.rb
|
202
203
|
- lib/physical/shipment.rb
|
203
204
|
- lib/physical/spec_support/factories/box_factory.rb
|
204
205
|
- lib/physical/spec_support/factories/item_factory.rb
|
@@ -207,6 +208,8 @@ files:
|
|
207
208
|
- lib/physical/spec_support/factories/pallet_factory.rb
|
208
209
|
- lib/physical/spec_support/factories/shipment_factory.rb
|
209
210
|
- lib/physical/spec_support/shared_examples.rb
|
211
|
+
- lib/physical/spec_support/shared_examples/a_cuboid.rb
|
212
|
+
- lib/physical/spec_support/shared_examples/has_property_readers.rb
|
210
213
|
- lib/physical/test_support.rb
|
211
214
|
- lib/physical/types.rb
|
212
215
|
- lib/physical/version.rb
|
@@ -230,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
233
|
- !ruby/object:Gem::Version
|
231
234
|
version: '0'
|
232
235
|
requirements: []
|
233
|
-
rubygems_version: 3.
|
236
|
+
rubygems_version: 3.4.10
|
234
237
|
signing_key:
|
235
238
|
specification_version: 4
|
236
239
|
summary: A facade to deal with physical packages
|