Skip to content

Commit

Permalink
Rework ResourceIdentity <=> operator
Browse files Browse the repository at this point in the history
add tests for ResourceIdentity, including that comparison does not allocate memory
  • Loading branch information
lgebhardt committed Jan 13, 2024
1 parent cd1a529 commit ee53cef
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
1 change: 1 addition & 0 deletions jsonapi-resources.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'database_cleaner'
spec.add_development_dependency 'hashie'
spec.add_development_dependency 'sorted_set'
spec.add_development_dependency 'memory_profiler'
spec.add_dependency 'activerecord', '>= 5.1'
spec.add_dependency 'railties', '>= 5.1'
spec.add_dependency 'concurrent-ruby'
Expand Down
13 changes: 12 additions & 1 deletion lib/jsonapi/resource_identity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module JSONAPI
# rid = ResourceIdentity.new(PostResource, 12)
#
class ResourceIdentity
include Comparable

# Store the identity parts as an array to avoid allocating a new array for the hash method to work on
def initialize(resource_klass, id)
@identity_parts = [resource_klass, id]
Expand Down Expand Up @@ -41,7 +43,16 @@ def hash
end

def <=>(other_identity)
self.id <=> other_identity.id
return nil unless other_identity.is_a?(ResourceIdentity)

case self.resource_klass.name <=> other_identity.resource_klass.name
when -1
-1
when 1
1
else
self.id <=> other_identity.id
end
end

# Creates a string representation of the identifier.
Expand Down
58 changes: 58 additions & 0 deletions test/unit/resource/resource_identity_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require File.expand_path('../../../test_helper', __FILE__)
require 'memory_profiler'

class ResourceIdentity < ActiveSupport::TestCase

def test_can_generate_a_consistent_hash_for_comparison
rid = JSONAPI::ResourceIdentity.new(PostResource, 12)
assert_equal(rid.hash, [PostResource, 12].hash)
end

def test_equality
rid = JSONAPI::ResourceIdentity.new(PostResource, 12)
rid2 = JSONAPI::ResourceIdentity.new(PostResource, 12)
assert_equal(rid, rid2) # uses == internally
assert rid.eql?(rid2)
end

def test_inequality
rid = JSONAPI::ResourceIdentity.new(PostResource, 12)
rid2 = JSONAPI::ResourceIdentity.new(PostResource, 13)
refute_equal(rid, rid2)
end

def test_sorting_by_resource_class_name
rid = JSONAPI::ResourceIdentity.new(CommentResource, 13)
rid2 = JSONAPI::ResourceIdentity.new(PostResource, 13)
rid3 = JSONAPI::ResourceIdentity.new(SectionResource, 13)
assert_equal([rid2, rid3, rid].sort, [rid, rid2, rid3])
end

def test_sorting_by_id_secondarily
rid = JSONAPI::ResourceIdentity.new(PostResource, 12)
rid2 = JSONAPI::ResourceIdentity.new(PostResource, 13)
rid3 = JSONAPI::ResourceIdentity.new(PostResource, 14)

assert_equal([rid2, rid3, rid].sort, [rid, rid2, rid3])
end

def test_to_s
rid = JSONAPI::ResourceIdentity.new(PostResource, 12)
assert_equal(rid.to_s, 'PostResource:12')
end

def test_comparisons_return_nil_for_non_resource_identity
rid = JSONAPI::ResourceIdentity.new(PostResource, 13)
rid2 = "PostResource:13"
assert_nil(rid <=> rid2)
end

def test_comparisons_allocate_no_new_memory
rid = JSONAPI::ResourceIdentity.new(PostResource, 13)
rid2 = JSONAPI::ResourceIdentity.new(PostResource, 13)
allocation_report = MemoryProfiler.report do
rid == rid2
end
assert_equal 0, allocation_report.total_allocated
end
end

0 comments on commit ee53cef

Please sign in to comment.