diff --git a/app/extensions/tree_node_extension.rb b/app/extensions/tree_node_extension.rb new file mode 100644 index 0000000..fe4f720 --- /dev/null +++ b/app/extensions/tree_node_extension.rb @@ -0,0 +1,18 @@ +module TreeNodeExtension + def distance_to_common_ancestor(another_node) + return 0 if self == another_node + + my_path = path_as_array + another_path = another_node.path_as_array + + common_elements = my_path.zip(another_path) + .take_while { |(p1, p2)| p1 == p2 } + .count + + return nil if common_elements.zero? + + [my_path.count, another_path.count].max - common_elements + end +end + +Tree::TreeNode.include(TreeNodeExtension) diff --git a/config/application.rb b/config/application.rb index e21736e..39a83b3 100644 --- a/config/application.rb +++ b/config/application.rb @@ -28,6 +28,8 @@ module WeddingPlanner # Common ones are `templates`, `generators`, or `middleware`, for example. config.autoload_lib(ignore: %w[assets tasks]) + config.eager_load_paths << root.join('extras') + # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files diff --git a/config/environments/development.rb b/config/environments/development.rb index 2e7fb48..794f390 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -9,7 +9,7 @@ Rails.application.configure do config.enable_reloading = true # Do not eager load code on boot. - config.eager_load = false + config.eager_load = true # Show full error reports. config.consider_all_requests_local = true diff --git a/config/environments/test.rb b/config/environments/test.rb index adbb4a6..3ada93b 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -15,7 +15,7 @@ Rails.application.configure do # this is usually not necessary, and can slow down your test suite. However, it's # recommended that you enable it in continuous integration systems to ensure eager # loading is working properly before deploying your code. - config.eager_load = ENV["CI"].present? + config.eager_load = true # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true diff --git a/spec/extensions/tree_spec.rb b/spec/extensions/tree_spec.rb new file mode 100644 index 0000000..cbefba4 --- /dev/null +++ b/spec/extensions/tree_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +module Tree + RSpec.describe TreeNode do + describe '#distance_to_common_ancestor' do + def assert_distance(node_1, node_2, distance) + aggregate_failures do + expect(node_1.distance_to_common_ancestor(node_2)).to eq(distance) + expect(node_2.distance_to_common_ancestor(node_1)).to eq(distance) + end + end + context 'when the two nodes are the same' do + it 'returns 0 when comparing the root itself' do + root = Tree::TreeNode.new('root') + assert_distance(root, root, 0) + end + + it 'returns 0 when comparing a child to itself' do + root = Tree::TreeNode.new('root') + child = root << Tree::TreeNode.new('child') + assert_distance(child, child, 0) + end + end + + context 'when the two nodes are siblings' do + it 'returns 1 when comparing siblings' do + root = Tree::TreeNode.new('root') + child1 = root << Tree::TreeNode.new('child1') + child2 = root << Tree::TreeNode.new('child2') + assert_distance(child1, child2, 1) + end + end + + context 'when one node is parent of the other' do + it 'returns 1 when comparing parent to child' do + root = Tree::TreeNode.new('root') + child = root << Tree::TreeNode.new('child') + assert_distance(root, child, 1) + end + end + + context 'when one node is grandparent of the other' do + it 'returns 2 when comparing grandparent to grandchild' do + root = Tree::TreeNode.new('root') + child = root << Tree::TreeNode.new('child') + grandchild = child << Tree::TreeNode.new('grandchild') + assert_distance(root, grandchild, 2) + end + end + + context 'when the two nodes are cousins' do + it 'returns 2 when comparing cousins' do + root = Tree::TreeNode.new('root') + child1 = root << Tree::TreeNode.new('child1') + child2 = root << Tree::TreeNode.new('child2') + grandchild1 = child1 << Tree::TreeNode.new('grandchild1') + grandchild2 = child2 << Tree::TreeNode.new('grandchild2') + assert_distance(grandchild1, grandchild2, 2) + end + end + + context 'when the two nodes are not related' do + it 'returns nil' do + root = Tree::TreeNode.new('root') + another_root = Tree::TreeNode.new('another_root') + assert_distance(root, another_root, nil) + end + end + end + end +end