Short Ruby Newsletter

Share this post

Ruby Value Objects

newsletter.shortruby.com
Code Summaries

Ruby Value Objects

#code #summaries #ruby #codesummary #value #objects

Lucian Ghinda
Sep 13, 2022
Share this post

Ruby Value Objects

newsletter.shortruby.com

This is a #codesummary for https://thoughtbot.com/blog/value-object-semantics-in-ruby

# Code Summary for https://thoughtbot.com/blog/value-object-semantics-in-ruby  # Part 1/4 : Concepts of equality in Ruby  # Two concepts of equality in Ruby: # 1️⃣ Equal by identity (when objects are the same object in memory) # 2️⃣ Equal by value (when objects represents the same value)  # Some objects supports by default comparison by value obj_a = "Model" obj_a.object_id # 31320  obj_b = "Model" obj_b.object_id # 55600  obj_a == obj_b # ✅ true because == compares in this case by value obj_a.equal?(obj_b) # ❌ false because .equal? compares by identity  # But when you create your own class, by default the comparison is by identity class Duration   def initialize(duration) = @duration = duration end  Duration.new(5) == Duration.new(5) # ❌ false - compared by default by identify
# Code Summary for https://thoughtbot.com/blog/value-object-semantics-in-ruby  # Part 2/4 : Value objects # 1. Should == each other # 2. Should NOT #equal? each other (as equal? should compare by identity) # 3. Should #hash to the same value # 4. Should #eql? each other (Ruby expects objects that have them same hash to be eql?)  class Duration    attr_reader :minutes       def initialize(minutes) = @minutes = minutes       def ==(other) = minutes == other.minutes    alias_method :eql?, :==       def hash = [self.class, minutes].hash  end  # #hash and #eql? are importyant as it allows the value object to be used as hash key  events = { Duration.new(5) => [ 1, 2, 3], Duration.new(10) => [5, 6, 7] }  events[Duration.new(5)] # will return [1, 2, 3]  # Struct objects are compared by value by default Duration = Struct.new(:minutes)  Duration.new(5) == Duration.new(5)
# Code Summary for https://thoughtbot.com/blog/value-object-semantics-in-ruby  # Part 3/4: Value objects should be immutable  # add freeze to make the object immutable  class Duration   attr_reader :minutes      def initialize(minutes)      @minutes = minutes      freeze    end    def add(other) = @minutes += other.minutes      def +(other) = Duration.new(self.minutes + other.minutes) end  d = Duration.new(5) t = Duration.new(10) d.add(t) # ❌ will throw error FrozenError  s = (d + t) # will create a new object
 # Part 4/4: An extra note about working with strings and freeze  # If you add at the top of your file the magic comment  # # frozen_string_literal: true  # or freeze the string  obj_a = "Model".freeze obj_b = "Model".freeze  # Then "Model" will always be the same object  obj_a.equal?(obj_b) # ✅ true obj_a.object_id == obj_b.object_id # ✅ true obj_a == obj_b # ✅ true

If you like this kind of content you should consider subscribing to my weekly newsletter with fresh content about Ruby and Rails.

Share this post

Ruby Value Objects

newsletter.shortruby.com
Previous
Next
Comments
TopNewCommunity

No posts

Ready for more?

© 2023 Lucian Ghinda
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing