Many association not working when building documents #233

Open
alexkwolfe opened this Issue Mar 20, 2011 · 5 comments

Comments

Projects
None yet
5 participants

When building new documents and setting up associations between them, MongoMapper refuses to set references to one another before the documents are persisted. This creates a problem for setting up complex associations in Rails controller new actions.

See the following test case. The test passes when the documents are persisted, but fails when they are not.

  require 'test/unit'
  require 'mongo_mapper'

  class Account
    include MongoMapper::Document
    key :name
    many :users
  end

  class User
    include MongoMapper::Document
    key :email
    belongs_to :account
  end

  class AssociationTest < Test::Unit::TestCase
    def setup
      MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
      MongoMapper.database   =  'association_test'
    end

    def test_unpersisted
      account = Account.new(:name => "Tom's account")
      user = account.users.build(:email => 'tom@jones.com')
      assert_equal user, account.users.first
      assert_equal account, user.account
    end

    def test_persisted
      account = Account.create(:name => "Tom's account")
      user = account.users.create(:email => 'tom@jones.com')
      assert_equal user, account.users.first
      assert_equal account, user.account
    end
  end

DAddYE commented Apr 5, 2011

This can be available in 0.9?

Contributor

bkeepers commented Apr 10, 2011

If someone submits a patch, then sure. :)

+1 This issue is intimately related to issue #218: you should be able to setup an object (new or existing) with all its associations without issuing any query, check for validity then save if everything is ok which would also trigger the save for associated objects which are not persisted. In my opinion, built-in associations are mostly useless until we can do that. Please note that mongoid hasn't succeed in making this right either.

Contributor

brianhempel commented May 17, 2011

Thoughts on building up associations without saving:

I love the idea of associations not saving until told, but the gotcha is that MongoMapper associations only talk to each other through the database. So if you haven't saved yet, not all of your logical associations will be available. For example...

article.comments[0].article

...won't work until the article has been saved. The comment won't find its article because it's not in the database yet.

You could get around that by writing logic so MongoMapper could pull some magic to find the docs in memory, but that would likely break MongoMapper's current behavior of allowing arbitrary query code on the association, e.g. ...

class Article
    include MongoMapper::Document
    many :comments, :sort => :created_at.desc, :deleted_at => nil
end

...because to properly honor that you'd have to recreate MongoDB's querying inside MongoMapper for an article to find its comments in memory.

So it seems to be a "pick your poison" situation:

  1. Don't change the current behavior and have association assignment trigger saves, allowing article.comments[0].article to work.
  2. Build out associations without saving but have article.comments[0].article be broken until everything is saved.
  3. Build out associations without saving and disallow query criteria on association definitions, then article.comments[0].article could probably be made to work right without saving the docs.
  4. Build out associations without saving, and add lots of logic to MongoMapper so that no association API changes are needed and article.comments[0].article will always work as expected even when the docs aren't saved.

Thoughts?

I would tend to prefer poison number 2 or 3. Most of the time, I need to validate an object and its associations before saving, the current behavior make this hard to do. Also, because MongoDB has no transaction, you mostly never want to issue multiple queries to update a document when one would be enough. I'm using MongoMapper on multiple production projects, but avoid using any built-in association.

I love the idea of associations not saving until told, but the gotcha is that MongoMapper associations only talk to each other through the database.

I understand it clear, I would already have submitted a patch if it were just a bug, but it seems more like a design flaw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment