Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nil is not behaving like nil #197

Open
trogdoro opened this issue Jul 27, 2011 · 5 comments
Open

nil is not behaving like nil #197

trogdoro opened this issue Jul 27, 2011 · 5 comments

Comments

@trogdoro
Copy link

Whenever I have a one linked association that is empty, the nil value returned is not the correct nil. Normally nil has an object_id equal to 4. This nil has an object_id that is something else. You can emulate the problem by putting the following in your associations spec:

it "should actually be nil" do
  @user.emergency_contact = @friend1
  @user.save

  @friend1.destroy
  @found = User.find(@user.key)
  @found.emergency_contact.object_id.should == nil.object_id
end

This bug renders things like "if" and "unless" useless. Even the && and || operators treat this nil as truthy.

@myronmarston
Copy link
Contributor

This is due to the fact that ripple is using a proxy for the association. It is proxying to nil, but the proxy itself is not nil.

You can check nil with association.nil?.

I agree this is a gotcha, but I'm not sure what the solution should be.

@seancribbs
Copy link
Contributor

Feels like there could be a special-case/guard on the accessor method if the target is nil. That said, .nil? is a good workaround.

@seancribbs
Copy link
Contributor

Another thing I noticed about the snippet is that the target is not actually nil because the link still exists, even though the object on the other side doesn't. There is no referential integrity.

@myronmarston
Copy link
Contributor

Feels like there could be a special-case/guard on the accessor method if the target is nil.

I like this idea. I've used the nil? work around in multiple places and it would be nice to not have to.

I was actually just bitten last night by a bug due to a nil-proxy being truthy. I can take a look at fixing this the next time I'm working on ripple.

One concern, though: once we change the association accessor to return nil, you can't call methods on it anymore (like my_document.my_association.build(:attribute => :hash)--will this potentially break people's apps?

@seancribbs
Copy link
Contributor

@myronmarston I think ActiveRecord went the route of my_document.build_my_association for singular associations.

seancribbs added a commit that referenced this issue Nov 1, 2012
For now, rather than rewriting the entire associations design, we
simply define methods on the owner class that will delegate to the
association proxy as necessary, namely the build/create methods. The
regular accessor now returns the proxy's target directly. All
library-internal calls that expected a proxy to be returned from the
accessor now request the proxy through #get_proxy.

This refactoring has some unresolved problems:

1. Nested attributes callbacks cause linked documents to be saved
   twice when the owner is saved.
2. Because of lazy target-class resolution, we cannot proactively
   define *_keys or *_links accessors on the owner class. In the
   future we should probably do explicit association-type
   declarations, e.g. `embed_one`, `link_to_many`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants