Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-5009

Belongs to relationship makes all target association methods effectively public

    XMLWordPrintableJSON

Details

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major - P3 Major - P3
    • None
    • 7.1.4
    • Associations
    • Tried in macOS and Ubuntu

    Description

      When defining belongs_to/has_one associations, the methods in the associated object change visibilty and ruby's `defined?` doesn't detect them.
      When doing `parent.child = child`, the associated object is cloned (object_id changes) and while the class, ancestors, and everything looks and feels the same, something happens where the private methods are made public, and public methods are there but not recognized by ruby's `defined?`.
      Same happens when doing `child.parent = parent`

      Here's a minimal reproduction case:

      require 'bundler/inline'
       
      gemfile do
        source 'https://rubygems.org'
        gem 'mongoid', '~> 7.1.4'
        gem 'minitest', '~> 5.14.1', require: ['minitest', 'minitest/autorun']
      end
       
      class Parent
        include Mongoid::Document
       
        belongs_to :child
       
        def a_public_method
          'parent public'
        end
       
        private
       
        def a_private_method
          'parent private'
        end
      end
       
      class Child
        include Mongoid::Document
       
        has_one :parent
       
        def a_public_method
          'child public'
        end
       
        private
       
        def a_private_method
          'child private'
        end
      end
       
      class TestRelationships < Minitest::Test
        def test_child_private_methods_stay_private
          parent = Parent.new
          child = Child.new
       
          parent.child = child
       
          assert_raises NoMethodError do
            child.a_private_method
          end
       
          assert_raises NoMethodError do
            parent.child.a_private_method
          end
        end
       
        def test_child_methods_are_defined
          parent = Parent.new
          child = Child.new
       
          parent.child = child
       
          assert_equal 'method', defined?(child.a_public_method)
          assert_equal 'method', defined?(parent.child.a_public_method)
        end
       
        def test_parent_private_methods_stay_private
          child = Child.new
          parent = Parent.new
       
          child.parent = parent
       
          assert_raises NoMethodError do
            parent.a_private_method
          end
       
          assert_raises NoMethodError do
            child.parent.a_private_method
          end
        end
       
        def test_parent_methods_are_defined
          child = Child.new
          parent = Parent.new
       
          child.parent = parent
       
          assert_equal 'method', defined?(parent.a_public_method)
          assert_equal 'method', defined?(child.parent.a_public_method)
        end
      end
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            ejpastorino@gmail.com Esteban Pastorino
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated: