diff options
author | Kevin Deisz <kevin.deisz@gmail.com> | 2018-08-27 13:52:14 -0400 |
---|---|---|
committer | Kevin Deisz <kevin.deisz@gmail.com> | 2018-08-27 15:22:37 -0400 |
commit | 1c7275a0ba05aaa27e5999eaa10b698d890fa157 (patch) | |
tree | c8823e5ea69a613761c1dd44188fcd821e3389ed /activerecord | |
parent | 3218a662818a52bd20eb93ee5468e62bdc9ccdf6 (diff) | |
download | rails-1c7275a0ba05aaa27e5999eaa10b698d890fa157.tar.gz rails-1c7275a0ba05aaa27e5999eaa10b698d890fa157.tar.bz2 rails-1c7275a0ba05aaa27e5999eaa10b698d890fa157.zip |
Find inverse associations with plural names
Previously ActiveRecord couldn't find inverse associations if they were plural, which is a pretty standard use case. This commit changes the behavior to first attempt to find the singular version, then attempt to find the plural version. That makes it work and find plural associations as in the example below:
```
class Post
has_many :comments
end
class Comment
belongs_to :post
end
```
Previously the `:post` association reflection would only attempt to find a `comment` inverse, as opposed to both a `comment` and `comments` inverse.
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 20 | ||||
-rw-r--r-- | activerecord/test/cases/associations/inverse_associations_test.rb | 11 |
2 files changed, 26 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 6d2f75a3ae..b2110f727c 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -612,9 +612,21 @@ module ActiveRecord # returns either +nil+ or the inverse association name that it finds. def automatic_inverse_of - if can_find_inverse_of_automatically?(self) - inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym + return unless can_find_inverse_of_automatically?(self) + inverse_name_candidates = + if options[:as] + [options[:as]] + else + active_record_name = active_record.name.demodulize + [active_record_name, ActiveSupport::Inflector.pluralize(active_record_name)] + end + + inverse_name_candidates.map! do |candidate| + ActiveSupport::Inflector.underscore(candidate).to_sym + end + + inverse_name_candidates.detect do |inverse_name| begin reflection = klass._reflect_on_association(inverse_name) rescue NameError @@ -623,9 +635,7 @@ module ActiveRecord reflection = false end - if valid_inverse_reflection?(reflection) - return inverse_name - end + valid_inverse_reflection?(reflection) end end diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index da3a42e2b5..0808aa7a52 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -20,6 +20,7 @@ require "models/company" require "models/project" require "models/author" require "models/post" +require "models/department" class AutomaticInverseFindingTests < ActiveRecord::TestCase fixtures :ratings, :comments, :cars @@ -724,6 +725,16 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase # fails because Interest does have the correct inverse_of assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.polymorphic_man = Interest.first } end + + def test_favors_has_one_associations_for_inverse_of + inverse_name = Post.reflect_on_association(:author).inverse_of.name + assert_equal :post, inverse_name + end + + def test_finds_inverse_of_for_plural_associations + inverse_name = Department.reflect_on_association(:hotel).inverse_of.name + assert_equal :departments, inverse_name + end end # NOTE - these tests might not be meaningful, ripped as they were from the parental_control plugin |