aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorKevin Deisz <kevin.deisz@gmail.com>2018-08-27 13:52:14 -0400
committerKevin Deisz <kevin.deisz@gmail.com>2018-08-27 15:22:37 -0400
commit1c7275a0ba05aaa27e5999eaa10b698d890fa157 (patch)
treec8823e5ea69a613761c1dd44188fcd821e3389ed /activerecord
parent3218a662818a52bd20eb93ee5468e62bdc9ccdf6 (diff)
downloadrails-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.rb20
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb11
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