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

Access an instance's connection via its class, rather than via #connection #9371

Merged
merged 1 commit into from Mar 9, 2013

Conversation

Projects
None yet
6 participants
@benmoss
Copy link
Contributor

benmoss commented Feb 22, 2013

Had a problem today where we had a belongs_to :connection on our model. Hadn't occurred to me that this might be a problem, but when we ran our tests we were getting an obscure undefined method substitute_at for nil:NilClass exception whenever an instance of this class was being destroyed.

Discovered the root cause was this method, which was attempting to call connection on the instance, which in turn delegates to the class. This seems like a pretty safe change to make, I can't think of any possible repercussions. I wasn't sure if this warranted a regression test, but I'd be happy to provide one if it's required.

@senny

This comment has been minimized.

Copy link
Member

senny commented Feb 22, 2013

not sure about the test either but we need a CHANGELOG entry for sure. I'm leaning towards creating a test.

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Feb 23, 2013

Added a test and a CHANGELOG entry

@senny

View changes

activerecord/test/cases/persistence_test.rb Outdated
@@ -315,6 +315,11 @@ def test_destroy
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
end

def test_destroy_doesnt_rely_on_connection_instance_method
warehouse = WarehouseThing.find(1)
assert_nothing_raised(NoMethodError) { warehouse.destroy }

This comment has been minimized.

@senny

senny Feb 24, 2013

Member

maybe we should assert here that #connection returns "a connection" and supply a description in the assertion message why this is relevant. Otherwise the connection method could be easily removed from the model and we could run back into regressions.

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Feb 24, 2013

I experimented with removing the connection instance method from core and these were the only other places in the codebase that seemed to rely on it:

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb#L22
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb#L29
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb#L44
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locking/optimistic.rb#L89
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locking/optimistic.rb#L120

It seems like it only makes sense to try to make the earlier change if I change all these others as well, otherwise it'll only be a matter of time until they likely bite me or someone else. Do you think this is worthwhile? It still seems like it's going to be hard to protect against others introducing new code that relies on it, the only sure-fire way to remove it as a 'reserved method' would be to rename it or remove it entirely, but both of those seem like too big of changes to the AR interface.

@rafaelfranca

This comment has been minimized.

Copy link
Member

rafaelfranca commented Feb 24, 2013

I think you can change all these places, but we can't protect for introducing new code without removing connection from the instance. We can't do this without a deprecation cycle.

@jonleighton @tenderlove WDYT about removing connection method from instance?

@jonleighton

This comment has been minimized.

Copy link
Member

jonleighton commented Feb 24, 2013

I am in favour. I've encountered this problem myself.

@rafaelfranca

This comment has been minimized.

Copy link
Member

rafaelfranca commented Feb 24, 2013

@benmoss mind to update your pull request deprecating connection at instance level and removing all the use in the Rails codebase?

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Feb 24, 2013

Sure, awesome!

@steveklabnik

This comment has been minimized.

Copy link
Member

steveklabnik commented Feb 25, 2013

Neat.

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Mar 8, 2013

Any word on this?

@jonleighton

This comment has been minimized.

Copy link
Member

jonleighton commented Mar 8, 2013

@benmoss I'll merge this, but it needs a rebase. Please comment when you have rebased as github doesn't send a notification when there's a code update.

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Mar 9, 2013

Rebased!

@carlosantoniodasilva

View changes

activerecord/CHANGELOG.md Outdated
@@ -1717,5 +1717,8 @@

*Aaron Patterson*

* `connection` is deprecated as an instance method.

*Ben Moss*

This comment has been minimized.

@carlosantoniodasilva

carlosantoniodasilva Mar 9, 2013

Member

Can you please move this to the top of the changelog, right after the "unreleased" title?

@carlosantoniodasilva

View changes

activerecord/test/cases/fixtures_test.rb Outdated
def test_connection
assert_kind_of Course, courses(:ruby)
assert_equal Course.connection, courses(:ruby).connection
end

This comment has been minimized.

@carlosantoniodasilva

carlosantoniodasilva Mar 9, 2013

Member

It'd be better to change the test to ensure it's deprecated instead:

def test_connection_instance_method_deprecation
  assert_deprecated { courses(:ruby).connection }
end

Or something like that.

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Mar 9, 2013

Fixed! Sorry about that.

@carlosantoniodasilva

This comment has been minimized.

Copy link
Member

carlosantoniodasilva commented Mar 9, 2013

@benmoss no problem, looks good to me now. Thanks.

@jonleighton all yours :)

@jonleighton

This comment has been minimized.

Copy link
Member

jonleighton commented Mar 9, 2013

@benmoss could you add the reasoning for the change to your commit message / the changelog? thanks

@benmoss

This comment has been minimized.

Copy link
Contributor Author

benmoss commented Mar 9, 2013

Done

Deprecate #connection in favour of accessing it via the class
This allows end-users to have a `connection` method on their models
without clashing with ActiveRecord internals.

jonleighton added a commit that referenced this pull request Mar 9, 2013

Merge pull request #9371 from benmoss/access-connection-via-class
Access an instance's connection via its class, rather than via #connection

@jonleighton jonleighton merged commit 15970ef into rails:master Mar 9, 2013

yahonda added a commit to yahonda/oracle-enhanced that referenced this pull request Mar 10, 2013

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