Skip to content

Instantly share code, notes, and snippets.

@JoelQ
Last active January 10, 2024 01:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JoelQ/8d78e8960e3d7cd60402f1f2de648bfa to your computer and use it in GitHub Desktop.
Save JoelQ/8d78e8960e3d7cd60402f1f2de648bfa to your computer and use it in GitHub Desktop.
Implementing value object semantics as an RSpec shared_example.
class Dollar
attr_reader :cents
def initialize(cents:)
@cents = cents
end
def hash
[self.class, cents].hash
end
def ==(other)
cents == other.cents
end
alias_method :eql?, :==
end
require_relative "dollar"
require_relative "value_object_shared_examples"
RSpec.describe Dollar do
it_behaves_like "value object" do
let(:item) { Dollar.new(cents: 5) }
let(:same) { Dollar.new(cents: 5) }
let(:different) { Dollar.new(cents: 10) }
end
end
class Duration
attr_reader :milliseconds
def initialize(milliseconds:)
@milliseconds = milliseconds
end
def hash
[self.class, milliseconds].hash
end
def ==(other)
milliseconds == other.milliseconds
end
alias_method :eql?, :==
end
require_relative "duration"
require_relative "value_object_shared_examples"
RSpec.describe Duration do
it_behaves_like "value object" do
let(:item) { Duration.new(milliseconds: 1000) }
let(:same) { Duration.new(milliseconds: 1000) }
let(:different) { Duration.new(milliseconds: 1234) }
end
end
% rspec duration_spec.rb dollar_spec.rb --format documentation
Randomized with seed 9567
Dollar
behaves like value object
#==
two instances are not == if they have a different value
two instances are == if they have the same value
#hash
is the same as another instance of the same value
is the different from another instance of a different value
#equal?
is equal if two object share the same identity
is not equal if two different objects share the same value
#eql?
two instances are not eql if they have a different value
two instances are eql if they have the same value
Duration
behaves like value object
#==
two instances are == if they have the same value
two instances are not == if they have a different value
#hash
is the same as another instance of the same value
is the different from another instance of a different value
#eql?
two instances are eql if they have the same value
two instances are not eql if they have a different value
#equal?
is not equal if two different objects share the same value
is equal if two object share the same identity
Finished in 0.00453 seconds (files took 0.11736 seconds to load)
16 examples, 0 failures
Randomized with seed 9567
RSpec.shared_examples_for "value object" do
describe "#hash" do
it "is the same as another instance of the same value" do
expect(item.hash).to eq same.hash
end
it "is the different from another instance of a different value" do
expect(item.hash).not_to eq different.hash
end
end
describe "#eql?" do
it "two instances are eql if they have the same value" do
expect(item).to be_eql same
end
it "two instances are not eql if they have a different value" do
expect(item).not_to be_eql different
end
end
describe "#==" do
it "two instances are == if they have the same value" do
expect(item).to eq same
end
it "two instances are not == if they have a different value" do
expect(item).not_to eq different
end
end
describe "#equal?" do
it "is equal if two object share the same identity" do
expect(item).to be_equal item
end
it "is not equal if two different objects share the same value" do
expect(item).not_to be_equal same
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment