This project is archived and is in readonly mode.

#4354 ✓stale
feldercarb

Unable to create has_one association within after_initialize of nested belongs_to association

Reported by feldercarb | April 9th, 2010 @ 06:52 AM

When following an after_initialize chain through multiple layers of an object hierarchy, has_one associations created within a belongs_to association do not remain in the object hierarchy when returning up the chain.

The following classes are from the associated test case:

class Book < ActiveRecord::Base
    has_many :stories
    def after_initialize
        stories.build( :book => self ) if stories.empty?
    end
end

class Story < ActiveRecord::Base
    belongs_to :book
    belongs_to :author
    def after_initialize
        build_author if author.nil?
    end
end

class Author < ActiveRecord::Base
    has_one :profile
    def after_initialize
        build_profile if profile.nil?
    end
end

class Profile < ActiveRecord::Base
    belongs_to :author
end

If the above objects are defined, then creating a new Book will fire all after_initialize methods and we should end up with a Book with one Story attributed to one Author who has one Profile

Stepping through the methods proves that the Author.after_initialize creates the Profile, but when we return to the Story level, the Author does not have the created Profile.

Therefore the test case:

class BookTest < ActiveSupport::TestCase
    test "book has author profiles" do
        b = Book.new
        assert_not_nil b.stories.first.author.profile, "Author profile is missing"
    end
end

will fail when it should succeed.

Comments and changes to this ticket

  • feldercarb

    feldercarb April 9th, 2010 @ 03:56 PM

    I have a temporary work-around for this which requires the removal of all after_initialize methods and calling the after_initialize functionality manually.

    If you go in and change all of the after_initialize methods to something like "build_associations", then call the build_association methods after each object is created, and chain the build_associations methods, it works.

    So if we change the models from the first report to:

    class Book < ActiveRecord::Base
        has_many :stories
        def build_associations
            s = stories.build( :book => self ) if stories.empty?
            s.build_associations
        end
    end
    
    class Story < ActiveRecord::Base
        belongs_to :book
        belongs_to :author
        def build_associations
            build_author if author.nil?
            author.build_associations
        end
    end
    
    class Author < ActiveRecord::Base
        has_one :profile
        def build_associations
            build_profile if profile.nil?
        end
    end
    

    The test will succeed. (See attached belongstoafterinitializefailureworking.tgz file for full app)

    I don't know the full reasoning behind this except that we are not inside the framework's object initialization process when we initialize the associations.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:44 PM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:44 PM

    • State changed from “open” to “stale”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Pages